* src/pic/gen.c (popGetExternal): augmented to also create references
[fw/sdcc] / src / pic / gen.c
index 9a221d2572e7dc313a9e59175548df408d33b20b..fb514994de2692dc1787786dd2d4ed9d27581249 100644 (file)
@@ -5,7 +5,7 @@
          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
-    cont'd   -  Raphael Neider rneider@web.de (2005)
+    cont'd   -  Raphael Neider <rneider AT web.de> (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
 #include <string.h>
 #include <ctype.h>
 #include "SDCCglobl.h"
-#include "newalloc.h"
+#include "newalloc.h" 
 
 #include "common.h"
 #include "SDCCpeeph.h"
 #include "ralloc.h"
 #include "pcode.h"
 #include "gen.h"
+#include "glue.h"
 
-/* When changing these, you must also update the assembler template
- * in device/lib/libsdcc/macros.inc */
-#define GPTRTAG_DATA   0x00
-#define GPTRTAG_CODE   0x80
+/* The PIC port(s) need not differentiate between POINTER and FPOINTER. */
+#define PIC_IS_DATA_PTR(x)     (IS_DATA_PTR(x) || IS_FARPTR(x))
+#define PIC_IS_FARPTR(x)       (PIC_IS_DATA_PTR(x))
 
 extern void genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
 extern void genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
@@ -55,6 +55,7 @@ extern void printpBlock(FILE *of, pBlock *pb);
 
 static int labelOffset=0;
 extern int debug_verbose;
+extern int pic14_hasInterrupt;
 //static int optimized_for_speed = 0;
 
 /* max_key keeps track of the largest label number used in 
@@ -63,10 +64,10 @@ for the next function.
 */
 static int max_key=0;
 static int GpsuedoStkPtr=0;
+static int pic14_inISR = 0;
 
 pCodeOp *popGetImmd(char *name, unsigned int offset, int index,int is_func);
 extern char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
-unsigned int pic14aopLiteral (value *val, int offset);
 const char *AopType(short type);
 
 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0x00ff)
@@ -76,8 +77,8 @@ kludgy & hacky stuff. This is what it is all about
 CODE GENERATION for a specific MCU . some of the
 routines may be reusable, will have to see */
 
-static char *zero = "#0x00";
-static char *one  = "#0x01";
+static char *zero = "0x00";
+static char *one  = "0x01";
 static char *spname = "sp";
 
 char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" };
@@ -110,7 +111,7 @@ typedef struct resolvedIfx {
 
 extern int pic14_ptrRegReq ;
 extern int pic14_nRegs;
-extern FILE *codeOutFile;
+extern struct dbuf_s *codeOutBuf;
 static void saverbank (int, iCode *,bool);
 
 static lineNode *lineHead = NULL;
@@ -185,7 +186,7 @@ void DEBUGpic14_emitcode (char *inst,char *fmt, ...)
 {
        va_list ap;
        char lb[INITIAL_INLINEASM];  
-       unsigned char *lbp = lb;
+       unsigned char *lbp = (unsigned char *)lb;
        
        if(!debug_verbose && !options.debug)
                return;
@@ -269,8 +270,15 @@ void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
 {
        if(pcop)
                addpCode2pBlock(pb,newpCode(poc,pcop));
-       else
+       else {
+               static int has_warned = 0;
+               
                DEBUGpic14_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
+               if (!has_warned) {
+                       has_warned = 1;
+                       fprintf( stderr, "WARNING: encountered NULL pcop--this is probably a compiler bug...\n" );
+               }
+       }
 }
 
 void emitpcodeNULLop(PIC_OPCODE poc)
@@ -288,7 +296,7 @@ void pic14_emitcode (char *inst,char *fmt, ...)
 {
        va_list ap;
        char lb[INITIAL_INLINEASM];  
-       unsigned char *lbp = lb;
+       char *lbp = lb;
        
        va_start(ap,fmt);   
        
@@ -309,6 +317,7 @@ void pic14_emitcode (char *inst,char *fmt, ...)
        (lineHead = newLineNode(lb)));
        lineCurr->isInline = _G.inLine;
        lineCurr->isDebug  = _G.debugLine;
+       lineCurr->isLabel = (lbp[strlen (lbp) - 1] == ':');
        
        if(debug_verbose)
                addpCode2pBlock(pb,newpCodeCharP(lb));
@@ -502,84 +511,7 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
        if (sym->aop)
                return sym->aop;
        
-#if 0
-       /* 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 && !options.stack10bit) || sym->iaccess) {
-               sym->aop = aop = newAsmop(0);
-               aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
-               aop->size = getSize(sym->type);
-               
-               /* now assign the address of the variable to 
-               the pointer register */
-               if (aop->type != AOP_STK) {
-                       
-                       if (sym->onStack) {
-                               if ( _G.accInUse )
-                                       pic14_emitcode("push","acc");
-                               
-                               pic14_emitcode("mov","a,_bp");
-                               pic14_emitcode("add","a,#0x%02x",
-                                       ((sym->stack < 0) ?
-                                       ((char)(sym->stack - _G.nRegsSaved )) :
-                               ((char)sym->stack)) & 0xff);
-                               pic14_emitcode("mov","%s,a",
-                                       aop->aopu.aop_ptr->name);
-                               
-                               if ( _G.accInUse )
-                                       pic14_emitcode("pop","acc");
-                       } else
-                               pic14_emitcode("mov","%s,#%s",
-                               aop->aopu.aop_ptr->name,
-                               sym->rname);
-                       aop->paged = space->paged;
-               } else
-                       aop->aopu.aop_stk = sym->stack;
-               return aop;
-       }
-       
-       if (sym->onStack && options.stack10bit)
-       {
-               /* It's on the 10 bit stack, which is located in
-               * far data space.
-               */
-               
-               //DEBUGpic14_emitcode(";","%d",__LINE__);
-               
-               if ( _G.accInUse )
-                       pic14_emitcode("push","acc");
-               
-               pic14_emitcode("mov","a,_bp");
-               pic14_emitcode("add","a,#0x%02x",
-                       ((sym->stack < 0) ?
-                       ((char)(sym->stack - _G.nRegsSaved )) :
-               ((char)sym->stack)) & 0xff);
-               
-               genSetDPTR(1);
-               pic14_emitcode ("mov","dpx1,#0x40");
-               pic14_emitcode ("mov","dph1,#0x00");
-               pic14_emitcode ("mov","dpl1, a");
-               genSetDPTR(0);
-               
-               if ( _G.accInUse )
-                       pic14_emitcode("pop","acc");
-               
-               sym->aop = aop = newAsmop(AOP_DPTR2);
-               aop->size = getSize(sym->type); 
-               return aop;
-       }
-#endif
-
        //DEBUGpic14_emitcode(";","%d",__LINE__);
-       /* if in bit space */
-       if (IN_BITSPACE(space)) {
-               sym->aop = aop = newAsmop (AOP_CRY);
-               aop->aopu.aop_dir = sym->rname ;
-               aop->size = getSize(sym->type);
-               //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
-               return aop;
-       }
        /* if it is in direct space */
        if (IN_DIRSPACE(space)) {
                sym->aop = aop = newAsmop (AOP_DIR);
@@ -937,9 +869,12 @@ void aopOp (operand *op, iCode *ic, bool result)
                /* else spill location  */
                if (sym->usl.spillLoc)
                {
+                       asmop *oldAsmOp = NULL;
+
                        if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
                        {
                                /* force a new aop if sizes differ */
+                               oldAsmOp = sym->usl.spillLoc->aop;
                                sym->usl.spillLoc->aop = NULL;
                        }
                        DEBUGpic14_emitcode(";","%s %d %s sym->rname = %s, offset %d",
@@ -948,6 +883,11 @@ void aopOp (operand *op, iCode *ic, bool result)
                                sym->rname, sym->usl.spillLoc->offset);
                
                        sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
+                       if (getSize(sym->type) != getSize(sym->usl.spillLoc->type))
+                       {
+                               /* Don't reuse the new aop, go with the last one */
+                               sym->usl.spillLoc->aop = oldAsmOp;
+                       }
                        //aop->aopu.pcop = popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
                        aop->aopu.pcop = popRegFromString(sym->usl.spillLoc->rname, 
                                getSize(sym->type), 
@@ -1087,6 +1027,7 @@ char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
        //DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        /* offset is greater than
        size then zero */
+       assert(aop);
        if (offset > (aop->size - 1) &&
                aop->type != AOP_LIT)
                return zero;
@@ -1196,9 +1137,8 @@ char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
                return "AOP_accumulator_bug";
                
        case AOP_LIT:
-               sprintf(s,"0x%02x", pic14aopLiteral (aop->aopu.aop_lit,offset));
-               rs = Safe_calloc(1,strlen(s)+1);
-               strcpy(rs,s);   
+               sprintf(s, "0x%02x", pic14aopLiteral (aop->aopu.aop_lit, offset));
+               rs = Safe_strdup(s);
                return rs;
                
        case AOP_STR:
@@ -1215,6 +1155,9 @@ char *aopGet (asmop *aop, int offset, bool bit16, bool dname)
                        pCodeOp *pcop = aop->aopu.pcop;
                        DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop));
                        if(pcop->name) {
+                               if (pcop->type == PO_IMMEDIATE) {
+                                       offset += PCOI(pcop)->index;
+                               }
                                if (offset) {
                                        DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset);
                                        sprintf(s,"(%s+%d)", pcop->name,offset);
@@ -1329,26 +1272,31 @@ pCodeOp *popGetWithString(char *str, int isExtern)
        return pcop;
 }
 
-pCodeOp *popGetExternal (char *str)
+pCodeOp *popGetExternal (char *str, int isReg)
 {
-       pCodeOp *pcop = popGetWithString (str, 1);
+       pCodeOp *pcop;
+       
+       if (isReg) {
+           pcop = newpCodeOpRegFromStr(str);
+       } else {
+           pcop = popGetWithString (str, 1);
+       }
        
        if (str) {
          symbol *sym;
-         bool found = 0;
 
-         for (sym = setFirstItem (externs); !found && sym; sym = setNextItem (externs))
+         for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
          {
-           if (!strcmp (str, sym->rname))
-             found = 1;
+           if (!strcmp (str, sym->rname)) break;
          }
          
-         if (!found)
+         if (!sym)
          {
            sym = newSymbol(str, 0);
            strncpy(sym->rname, str, SDCC_NAME_MAX);
            addSet (&externs, sym);
          } // if
+         sym->used++;
        }
        return pcop;
 }
@@ -1423,10 +1371,15 @@ pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname)
 
        assert (aop);
 
+
        /* XXX: still needed for BIT operands (AOP_CRY) */
        if (offset > (aop->size - 1) &&
-               aop->type != AOP_LIT)
+               aop->type != AOP_LIT &&
+               aop->type != AOP_PCODE)
+       {
+               printf( "%s: (offset[%d] > AOP_SIZE(op)[%d]-1) && AOP_TYPE(op) != AOP_LIT)\n", __FUNCTION__, offset, aop->size);
                return NULL;  //zero;
+       }
        
        /* depending on type */
        switch (aop->type) {
@@ -1878,13 +1831,26 @@ static void get_returnvalue (operand *op, int offset, int idx)
 
 static void call_libraryfunc (char *name)
 {
-  /* library code might reside in different page... */
-  emitpcode (POC_PAGESEL, popGetWithString (name, 1));
-  /* call the library function */
-  emitpcode (POC_CALL, popGetExternal (name));
-  /* might return from different page... */
-  emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
+    symbol *sym;
+
+    /* library code might reside in different page... */
+    emitpcode (POC_PAGESEL, popGetWithString (name, 1));
+    /* call the library function */
+    emitpcode (POC_CALL, popGetExternal (name, 0));
+    /* might return from different page... */
+    emitpcode (POC_PAGESEL, popGetWithString ("$", 0));
+
+    /* create symbol, mark it as `extern' */
+    sym = findSym(SymbolTab, NULL, name);
+    if (!sym) {
+       sym = newSymbol(name, 0);
+       strncpy(sym->rname, name, SDCC_NAME_MAX);
+       addSym(SymbolTab, sym, sym->rname, 0, 0, 0);
+       addSet(&externs, sym); 
+    } // if
+    sym->used++;
 }
+
 #if 0
 /*-----------------------------------------------------------------*/
 /* reAdjustPreg - points a register back to where it should        */
@@ -2591,7 +2557,7 @@ static void genCall (iCode *ic)
 {
        sym_link *dtype;         
        symbol *sym;
-       unsigned char *name;
+       char *name;
        int isExtern;
        
        FENTRY;
@@ -2666,13 +2632,28 @@ static void genCall (iCode *ic)
        /* make the call */
        sym = OP_SYMBOL(IC_LEFT(ic));
        name = sym->rname[0] ? sym->rname : sym->name;
-       isExtern = IS_EXTERN(sym->etype);
+       /*
+        * As SDCC emits code as soon as it reaches the end of each
+        * function's definition, prototyped functions that are implemented
+        * after the current one are always considered EXTERN, which
+        * introduces many unneccessary PAGESEL instructions.
+        * XXX: Use a post pass to iterate over all `CALL _name' statements
+        * and insert `PAGESEL _name' and `PAGESEL $' around the CALL
+        * only iff there is no definition of the function in the whole
+        * file (might include this in the PAGESEL pass).
+        */
+       isExtern = IS_EXTERN(sym->etype) || pic14_inISR;
        if (isExtern) {
-               emitpcode(POC_PAGESEL,popGetWithString(name,1)); /* Extern functions maybe on another page - must call pagesel */
+               /* Extern functions and ISRs maybe on a different page;
+                * must call pagesel */
+               emitpcode(POC_PAGESEL,popGetWithString(name,1));
        }
        emitpcode(POC_CALL,popGetWithString(name,isExtern));
        if (isExtern) {
-               emitpcode(POC_PAGESEL,popGetWithString("$",0)); /* May have returned from another page - must call pagesel to restore PCLATH before next goto or call instruction */
+               /* May have returned from a different page;
+                * must use pagesel to restore PCLATH before next
+                * goto or call instruction */
+               emitpcode(POC_PAGESEL,popGetWithString("$",0));
        }
        GpsuedoStkPtr=0;
        /* if we need assign a result value */
@@ -2762,7 +2743,7 @@ static void genPcall (iCode *ic)
        */
        emitpcode(POC_CALL,popGetLabel(albl->key));
        pcop = popGetLabel(blbl->key);
-       emitpcode(POC_PAGESEL,popGetWithString(pcop->name,0)); /* Must restore PCLATH before goto, without destroying W */
+       emitpcode(POC_PAGESEL,pcop); /* Must restore PCLATH before goto, without destroying W */
        emitpcode(POC_GOTO,pcop);
        emitpLabel(albl->key);
        
@@ -2824,12 +2805,6 @@ static int resultRemat (iCode *ic)
        return 0;
 }
 
-#if defined(__BORLANDC__) || defined(_MSC_VER)
-#define STRCASECMP stricmp
-#else
-#define STRCASECMP strcasecmp
-#endif
-
 #if 0
 /*-----------------------------------------------------------------*/
 /* inExcludeList - return 1 if the string is in exclude Reg list   */
@@ -2874,8 +2849,18 @@ static void genFunction (iCode *ic)
        pic14_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
        pic14_emitcode(";","-----------------------------------------");
        
+       /* prevent this symbol from being emitted as 'extern' */
+       pic14_stringInSet(sym->rname, &pic14_localFunctions, 1);
+
        pic14_emitcode("","%s:",sym->rname);
        addpCode2pBlock(pb,newpCodeFunction(NULL,sym->rname,!IS_STATIC (sym->etype)));
+
+       /* mark symbol as NOT extern (even if it was declared so previously) */
+       assert(IS_SPEC(sym->etype));
+       SPEC_EXTR(sym->etype) = 0;
+       sym->cdef = 0;
+       if (!SPEC_OCLS(sym->etype)) SPEC_OCLS(sym->etype) = code;
+       addSetIfnotP(&SPEC_OCLS(sym->etype)->syms, sym);
        
        ftype = operandType(IC_LEFT(ic));
        
@@ -2905,74 +2890,28 @@ static void genFunction (iCode *ic)
 #endif
        
        /* if this is an interrupt service routine */
+       pic14_inISR = 0;
        if (IFFUNC_ISISR(sym->type)) {
-       /*  already done in pic14createInterruptVect() - delete me
-       addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
-       emitpcodeNULLop(POC_NOP);
-       emitpcodeNULLop(POC_NOP);
-       emitpcodeNULLop(POC_NOP);
-               */
+               pic14_inISR = 1;
                emitpcode(POC_MOVWF,  popCopyReg(&pc_wsave));
                emitpcode(POC_SWAPFW, popCopyReg(&pc_status));
+               /* XXX: Why? Does this assume that ssave and psave reside
+                * in a shared bank or bank0? We cannot guarantee the
+                * latter...
+                */
                emitpcode(POC_CLRF,   popCopyReg(&pc_status));
                emitpcode(POC_MOVWF,  popCopyReg(&pc_ssave));
+               //emitpcode(POC_MOVWF,  popGetExternal("___sdcc_saved_status",1 ));
                emitpcode(POC_MOVFW,  popCopyReg(&pc_pclath));
+               /* during an interrupt PCLATH must be cleared before a goto or call statement */
+               emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));
                emitpcode(POC_MOVWF,  popCopyReg(&pc_psave));
-               emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
+               //emitpcode(POC_MOVWF,  popGetExternal("___sdcc_saved_pclath", 1));
+               emitpcode(POC_MOVFW,  popCopyReg(&pc_fsr));
+               emitpcode(POC_MOVWF,  popGetExternal("___sdcc_saved_fsr", 1));
                
                pBlockConvert2ISR(pb);
-#if 0  
-               if (!inExcludeList("acc"))              
-                       pic14_emitcode ("push","acc");  
-               if (!inExcludeList("b"))
-                       pic14_emitcode ("push","b");
-               if (!inExcludeList("dpl"))
-                       pic14_emitcode ("push","dpl");
-               if (!inExcludeList("dph"))
-                       pic14_emitcode ("push","dph");
-               if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
-               {
-                       pic14_emitcode ("push", "dpx");
-                       /* Make sure we're using standard DPTR */
-                       pic14_emitcode ("push", "dps");
-                       pic14_emitcode ("mov", "dps, #0x00");
-                       if (options.stack10bit)
-                       { 
-                               /* This ISR could conceivably use DPTR2. Better save it. */
-                               pic14_emitcode ("push", "dpl1");
-                               pic14_emitcode ("push", "dph1");
-                               pic14_emitcode ("push", "dpx1");
-                       }
-               }
-               /* if this isr has no bank i.e. is going to
-               run with bank 0 , then we need to save more
-               registers :-) */
-               if (!FUNC_REGBANK(sym->type)) {
-                       
-               /* if this function does not call any other
-               function then we can be economical and
-                       save only those registers that are used */
-                       if (! IFFUNC_HASFCALL(sym->type)) {
-                               int i;
-                               
-                               /* if any registers used */
-                               if (sym->regsUsed) {
-                                       /* save the registers used */
-                                       for ( i = 0 ; i < sym->regsUsed->size ; i++) {
-                                               if (bitVectBitValue(sym->regsUsed,i) ||
-                                                       (pic14_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
-                                                       pic14_emitcode("push","junk");//"%s",pic14_regWithIdx(i)->dname);               
-                                       }
-                               }
-                               
-                       } else {
-                       /* this function has    a function call cannot
-                       determines register usage so we will have the
-                               entire bank */
-                               saverbank(0,ic,FALSE);
-                       }       
-               }
-#endif
+               pic14_hasInterrupt = 1;
        } else {
        /* if callee-save to be used for this function
                then save the registers being used in this function */
@@ -3117,41 +3056,19 @@ registers :-) */
                                unsaverbank(0,ic,FALSE);
                        }       
                }
-#if 0
-               if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
-               {
-                       if (options.stack10bit)
-                       {
-                               pic14_emitcode ("pop", "dpx1");
-                               pic14_emitcode ("pop", "dph1");
-                               pic14_emitcode ("pop", "dpl1");
-                       } 
-                       pic14_emitcode ("pop", "dps");
-                       pic14_emitcode ("pop", "dpx");
-               }
-               if (!inExcludeList("dph"))
-                       pic14_emitcode ("pop","dph");
-               if (!inExcludeList("dpl"))
-                       pic14_emitcode ("pop","dpl");
-               if (!inExcludeList("b"))
-                       pic14_emitcode ("pop","b");
-               if (!inExcludeList("acc"))
-                       pic14_emitcode ("pop","acc");
-               
-               if (IFFUNC_ISCRITICAL(sym->type))
-                       pic14_emitcode("setb","ea");
-#endif
                
                /* if debug then send end of function */
-               /*      if (options.debug && currFunc) { */
-               if (currFunc) {
+               if (options.debug && debugFile && currFunc) {
                        debugFile->writeEndFunction (currFunc, ic, 1);
                }
                
-               pic14_emitcode ("reti","");
+               emitpcode(POC_MOVFW,  popGetExternal("___sdcc_saved_fsr", 1));
+               emitpcode(POC_MOVWF,  popCopyReg(&pc_fsr));
+               //emitpcode(POC_MOVFW,  popGetExternal("___sdcc_saved_pclath", 1));
                emitpcode(POC_MOVFW,  popCopyReg(&pc_psave));
                emitpcode(POC_MOVWF,  popCopyReg(&pc_pclath));
-               emitpcode(POC_CLRF,   popCopyReg(&pc_status));
+               emitpcode(POC_CLRF,   popCopyReg(&pc_status)); // see genFunction
+               //emitpcode(POC_SWAPFW, popGetExternal("___sdcc_saved_status", 1));
                emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave));
                emitpcode(POC_MOVWF,  popCopyReg(&pc_status));
                emitpcode(POC_SWAPF,  popCopyReg(&pc_wsave));
@@ -3179,7 +3096,7 @@ registers :-) */
                }
                
                /* if debug then send end of function */
-               if (currFunc) {
+               if (options.debug && debugFile && currFunc) {
                        debugFile->writeEndFunction (currFunc, ic, 1);
                }
                
@@ -3417,22 +3334,24 @@ static void genDivOneByte (operand *left,
                                                   operand *result)
 {
        int size;
+       int sign;
        
        FENTRY;
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        
-       assert (AOP_SIZE(result) == 1);
        assert (AOP_SIZE(right) == 1);
        assert (AOP_SIZE(left) == 1);
 
        size = min(AOP_SIZE(result),AOP_SIZE(left));
+       sign = !(SPEC_USIGN(operandType(left))
+               && SPEC_USIGN(operandType(right)));
 
        if (AOP_TYPE(right) == AOP_LIT)
        {
                /* XXX: might add specialized code */
        }
 
-       if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
+       if (!sign)
        {
                /* unsigned division */
        #if 1
@@ -3479,6 +3398,7 @@ static void genDivOneByte (operand *left,
                emitSKPNC;
                emitpcode(POC_GOTO, popGetLabel(lbl->key));
                emitpcode(POC_DECF, popGet(AOP(result),0));
+               popReleaseTempReg(temp);
        #endif
        }
        else
@@ -3492,7 +3412,7 @@ static void genDivOneByte (operand *left,
        }
 
        /* now performed the signed/unsigned division -- extend result */
-       addSign(result, 1, !SPEC_USIGN(operandType(result)));
+       addSign(result, 1, sign);
 }
 
 /*-----------------------------------------------------------------*/
@@ -3534,29 +3454,6 @@ release :
        freeAsmop(result,NULL,ic,TRUE); 
 }
 
-/*-----------------------------------------------------------------*/
-/* genModbits :- modulus of bits                                                                  */
-/*-----------------------------------------------------------------*/
-static void genModbits (operand *left, 
-                                               operand *right, 
-                                               operand *result)
-{
-       
-       char *l;
-       
-       FENTRY;
-       /* the result must be bit */      
-       pic14_emitcode("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE));
-       l = aopGet(AOP(left),0,FALSE,FALSE);
-       
-       MOVA(l);
-       
-       pic14_emitcode("div","ab");
-       pic14_emitcode("mov","a,b");
-       pic14_emitcode("rrc","a");
-       aopPut(AOP(result),"c",0);
-}
-
 /*-----------------------------------------------------------------*/
 /* genModOneByte : 8 bit modulus                                                                  */
 /*-----------------------------------------------------------------*/
@@ -3565,22 +3462,24 @@ static void genModOneByte (operand *left,
                                                   operand *result)
 {
        int size;
+       int sign;
        
        FENTRY;
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        
-       assert (AOP_SIZE(result) == 1);
        assert (AOP_SIZE(right) == 1);
        assert (AOP_SIZE(left) == 1);
 
        size = min(AOP_SIZE(result),AOP_SIZE(left));
+       sign = !(SPEC_USIGN(operandType(left))
+               && SPEC_USIGN(operandType(right)));
 
        if (AOP_TYPE(right) == AOP_LIT)
        {
                /* XXX: might add specialized code */
        }
 
-       if (SPEC_USIGN(operandType(left)) && SPEC_USIGN(operandType(right)))
+       if (!sign)
        {
                /* unsigned division */
        #if 1
@@ -3640,7 +3539,7 @@ static void genModOneByte (operand *left,
        }
 
        /* now we performed the signed/unsigned modulus -- extend result */
-       addSign(result, 1, !SPEC_USIGN(operandType(result)));
+       addSign(result, 1, sign);
 }
 
 /*-----------------------------------------------------------------*/
@@ -3659,14 +3558,6 @@ static void genMod (iCode *ic)
        aopOp (right,ic,FALSE);
        aopOp (result,ic,TRUE);
        
-       /* special cases first */
-       /* both are bits */
-       if (AOP_TYPE(left) == AOP_CRY &&
-               AOP_TYPE(right)== AOP_CRY) {
-               genModbits(left,right,result);
-               goto release ;
-       }
-       
        /* if both are of size == 1 */
        if (AOP_SIZE(left) == 1 &&
                AOP_SIZE(right) == 1 ) {
@@ -5451,7 +5342,11 @@ static void continueIfTrue (iCode *ic)
        FENTRY;
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        if(IC_TRUE(ic))
-               pic14_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
+       {
+               // Why +100?!?
+               emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
+               pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
+       }
        ic->generated = 1;
 }
 
@@ -5463,7 +5358,11 @@ static void jumpIfTrue (iCode *ic)
        FENTRY;
        DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
        if(!IC_TRUE(ic))
+       {
+               // Why +100?!?
+               emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key+100));
                pic14_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
+       }
        ic->generated = 1;
 }
 
@@ -5618,16 +5517,29 @@ static void genAnd (iCode *ic, iCode *ifx)
                                pic14_emitcode("setb","c");
                        while(sizel--){
                                if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
-                                       MOVA( aopGet(AOP(left),offset,FALSE,FALSE));
+                                       mov2w( AOP(left), offset);
                                        // byte ==  2^n ?
-                                       if((posbit = isLiteralBit(bytelit)) != 0)
+                                       if((posbit = isLiteralBit(bytelit)) != 0) {
+                                               emitpcode(rIfx.condition ? POC_BTFSC : POC_BTFSS, // XXX: or the other way round?
+                                                       newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),posbit - 1, 0));
                                                pic14_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
+                                       }
                                        else{
+                                               emitpcode(POC_ANDLW, newpCodeOpLit(bytelit & 0x0ff));
+                                               if (rIfx.condition) emitSKPZ;
+                                               else emitSKPNZ;
+                                               
                                                if(bytelit != 0x0FFL)
+                                               {
                                                        pic14_emitcode("anl","a,%s",
                                                        aopGet(AOP(right),offset,FALSE,TRUE));
+                                               }
                                                pic14_emitcode("jnz","%05d_DS_",tlbl->key+100);
                                        }
+
+                                       emitpcode(POC_GOTO, popGetLabel(rIfx.lbl->key));
+                                       ifx->generated = 1;
+                                               
                                }
                                offset++;
                        }
@@ -8450,6 +8362,7 @@ emitPtrByteGet (operand *src, int p_type, bool alreadyAddressed)
     switch (p_type)
     {
     case POINTER:
+    case FPOINTER:
       if (!alreadyAddressed) setup_fsr (src);
       emitpcode(POC_MOVFW, popCopyReg (&pc_fsr));
       break;
@@ -8491,6 +8404,7 @@ emitPtrByteSet (operand *dst, int p_type, bool alreadyAddressed)
     switch (p_type)
     {
     case POINTER:
+    case FPOINTER:
       if (!alreadyAddressed) setup_fsr (dst);
       emitpcode(POC_MOVWF, popCopyReg (&pc_fsr));
       break;
@@ -8559,6 +8473,7 @@ static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx
         break;
        
       case POINTER:
+      case FPOINTER:
       case GPOINTER:
       case CPOINTER:
         emitPtrByteGet (left, ptype, FALSE);
@@ -8596,6 +8511,7 @@ static void genUnpackBits (operand *result, operand *left, int ptype, iCode *ifx
       break;
       
     case POINTER:
+    case FPOINTER:
     case GPOINTER:
     case CPOINTER:
       emitPtrByteGet (left, ptype, FALSE);
@@ -8692,7 +8608,7 @@ static void genNearPointerGet (operand *left,
        lower 128 bytes of space */
        if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
                !IS_BITVAR(retype)         &&
-               DCL_TYPE(ltype) == POINTER) {
+               PIC_IS_DATA_PTR(ltype)) {
                genDataPointerGet (left,result,ic);
                return ;
        }
@@ -9126,6 +9042,7 @@ static void genPointerGet (iCode *ic)
        switch (p_type) {
                
        case POINTER: 
+       case FPOINTER:
        //case IPOINTER:
                genNearPointerGet (left,result,ic);
                break;
@@ -9192,6 +9109,7 @@ static void genPackBits(sym_link *etype,operand *result,operand *right,int p_typ
          break;
        
        case POINTER:
+       case FPOINTER:
          setup_fsr (result);
          emitpcode(lit?POC_BSF:POC_BCF,newpCodeOpBit(PCOP(&pc_indf)->name,bstr,0));
          break;
@@ -9231,6 +9149,7 @@ static void genPackBits(sym_link *etype,operand *result,operand *right,int p_typ
          break;
        
        case POINTER:
+       case FPOINTER:
        case GPOINTER:
          emitPtrByteGet(result, p_type, FALSE);
          if ((litval|mask) != 0x00ff)
@@ -9267,6 +9186,7 @@ static void genPackBits(sym_link *etype,operand *result,operand *right,int p_typ
          break;
        
        case POINTER:
+       case FPOINTER:
        case GPOINTER:
          emitPtrByteGet (result, p_type, FALSE);
          emitpcode(POC_BTFSS, newpCodeOpBit (aopGet(AOP(right), 0, FALSE, FALSE), bstr, 0));
@@ -9308,6 +9228,7 @@ static void genPackBits(sym_link *etype,operand *result,operand *right,int p_typ
          break;
        
        case POINTER:
+       case FPOINTER:
        case GPOINTER:
          emitPtrByteGet (result, p_type, FALSE);
          emitpcode(POC_ANDLW, popGetLit (mask));
@@ -9333,38 +9254,6 @@ static void genPackBits(sym_link *etype,operand *result,operand *right,int p_typ
   assert( !"bitfields larger than 8 bits or crossing byte boundaries are not yet supported" );
 }
 
-unsigned long
-bitpatternFromVal (value *val)
-{
-  union {
-    float d;
-    unsigned long l;
-  } float_long;
-
-  assert (sizeof (float) == sizeof (long));
-
-  //fprintf (stderr, "%s:%u(%s): val=%lf, type: %d, etype: %d\n", __FILE__, __LINE__, __FUNCTION__, floatFromVal(val), SPEC_NOUN(val->type), SPEC_NOUN(val->etype));
-
-  switch (SPEC_NOUN(val->type))
-  {
-  case V_INT:
-  case V_CHAR:
-    return (unsigned long)floatFromVal (val);
-    
-  case V_FLOAT:
-  case V_DOUBLE:
-    float_long.d = floatFromVal (val);
-    return float_long.l;
-    
-  default:
-    assert( !"unhandled value type" );
-    break;
-  }
-
-  float_long.d = floatFromVal (val);
-  return float_long.l;
-}
-
 /*-----------------------------------------------------------------*/
 /* genDataPointerSet - remat pointer to data space                 */
 /*-----------------------------------------------------------------*/
@@ -9383,7 +9272,10 @@ static void genDataPointerSet(operand *right,
        assert (IS_SYMOP(result));
        assert (IS_PTR(OP_SYM_TYPE(result)));
        
-       size = AOP_SIZE(right);
+       if (AOP_TYPE(right) == AOP_LIT)
+         size = 4;
+       else
+         size = AOP_SIZE(right);
        ressize = getSize(OP_SYM_ETYPE(result));
        if (size > ressize) size = ressize;
        //fprintf (stderr, "%s:%u: size(right): %d, size(result): %d\n", __FUNCTION__,__LINE__, AOP_SIZE(right), ressize);
@@ -9400,23 +9292,21 @@ static void genDataPointerSet(operand *right,
        
        // tsd, was l+1 - the underline `_' prefix was being stripped
        while (size--) {
-               emitpComment ("%s:%u: size=%d/%d, offset=%i", __FILE__,__LINE__, size, ressize, offset);
+               emitpComment ("%s:%u: size=%d/%d, offset=%d, AOP_TYPE(res)=%d", __FILE__,__LINE__, size, ressize, offset, AOP_TYPE(result));
                
                if (AOP_TYPE(right) == AOP_LIT) {
-                       /* XXX: might be float... */
-                       unsigned int lit = bitpatternFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
-                       lit = lit >> (8*offset);
+                       unsigned int lit = pic14aopLiteral(AOP(IC_RIGHT(ic))->aopu.aop_lit, offset);
                        //fprintf (stderr, "%s:%u: lit %d 0x%x\n", __FUNCTION__,__LINE__, lit, lit);
                        if(lit&0xff) {
                                emitpcode(POC_MOVLW, popGetLit(lit&0xff));
-                               emitpcode(POC_MOVWF, popGet(AOP(result),offset));
+                               emitpcode(POC_MOVWF, popGet(AOP(result), offset));
                        } else {
-                               emitpcode(POC_CLRF, popGet(AOP(result),offset));
+                               emitpcode(POC_CLRF, popGet(AOP(result), offset));
                        }
                } else {
                        //fprintf (stderr, "%s:%u: no lit\n", __FUNCTION__,__LINE__);
-                       emitpcode(POC_MOVFW, popGet(AOP(right),offset));
-                       emitpcode(POC_MOVWF, popGet(AOP(result),offset));
+                       emitpcode(POC_MOVFW, popGet(AOP(right), offset));
+                       emitpcode(POC_MOVWF, popGet(AOP(result), offset));
                }
                
                offset++;
@@ -9449,7 +9339,7 @@ static void genNearPointerSet (operand *right,
        in data space & not a bit variable */
        //if (AOP_TYPE(result) == AOP_IMMD &&
        if (AOP_TYPE(result) == AOP_PCODE &&
-               DCL_TYPE(ptype) == POINTER   &&
+               PIC_IS_DATA_PTR(ptype) &&
                !IS_BITVAR (retype) &&
                !IS_BITVAR (letype)) {
                genDataPointerSet (right,result,ic);
@@ -9697,7 +9587,16 @@ static void genGenPointerSet (operand *right, operand *result, iCode *ic)
          int size = AOP_SIZE(right);
          int idx = 0;
 
-         assert (size == getSize(OP_SYM_ETYPE(result)));
+         /* The following assertion fails for
+          *   struct foo { char a; char b; } bar;
+          *   void demo(struct foo *dst, char c) { dst->b = c; }
+          * as size will be 1 (sizeof(c)), whereas dst->b will be accessed
+          * using (((char *)dst)+1), whose OP_SYM_ETYPE still is struct foo
+          * of size 2.
+          * The frontend seems to guarantee that IC_LEFT has the correct size,
+          * it works fine both for larger and smaller types of `char c'.
+          * */
+         //assert (size == getSize(OP_SYM_ETYPE(result)));
          assert (size > 0 && size <= 4);
 
          /* pass arguments */
@@ -9774,6 +9673,7 @@ static void genPointerSet (iCode *ic)
        switch (p_type) {
                
        case POINTER:
+       case FPOINTER:
        //case IPOINTER:
                genNearPointerSet (right,result,ic);
                break;
@@ -9814,8 +9714,6 @@ static void genIfx (iCode *ic, iCode *popIc)
                pic14_toBoolean(cond);
        else
                isbit = 1;
-       /* the result is now in the accumulator */
-       freeAsmop(cond,NULL,ic,TRUE);
        
        /* if there was something to be popped then do it */
        if (popIc)
@@ -9823,11 +9721,32 @@ static void genIfx (iCode *ic, iCode *popIc)
        
        if (isbit)
        {
-               assert (!"genIfx not implemented for bit variables...");
+               /* This assumes that CARRY is set iff cond is true */
+               if (IC_TRUE(ic))
+               {
+                       assert (!IC_FALSE(ic));
+                       emitpcode(POC_BTFSC, popGet(AOP(cond), 0));
+                       //emitSKPNC;
+                       emitpcode(POC_GOTO, popGetLabel(IC_TRUE(ic)->key));
+               } else {
+                       assert (IC_FALSE(ic));
+                       emitpcode(POC_BTFSS, popGet(AOP(cond), 0));
+                       //emitSKPC;
+                       emitpcode(POC_GOTO, popGetLabel(IC_FALSE(ic)->key));
+               }
+               if (0)
+               {
+                       static int hasWarned = 0;
+                       if (!hasWarned)
+                       {
+                               fprintf (stderr, "WARNING: using untested code for %s:%u -- please check the .asm output and report bugs.\n", ic->filename, ic->lineno);
+                               hasWarned = 1;
+                       }
+               }
        }
        else
        {
-               /* now Z if set iff !cond */
+               /* now Z is set iff !cond */
                if (IC_TRUE(ic))
                {
                        assert (!IC_FALSE(ic));
@@ -9841,6 +9760,8 @@ static void genIfx (iCode *ic, iCode *popIc)
        
        ic->generated = 1;
        
+       /* the result is now in the accumulator */
+       freeAsmop(cond,NULL,ic,TRUE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -10045,9 +9966,6 @@ static void genAssign (iCode *ic)
        /* general case */
        size = AOP_SIZE(result);
        offset = 0 ;
-       if(AOP_TYPE(right) == AOP_LIT)
-               lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
-       
        if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
                DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
                if(aopIdx(AOP(result),0) == 4) {
@@ -10061,8 +9979,10 @@ static void genAssign (iCode *ic)
        
        know_W=-1;
        while (size--) {
+       
                DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
                if(AOP_TYPE(right) == AOP_LIT) {
+                       lit = (unsigned long)pic14aopLiteral(AOP(right)->aopu.aop_lit, offset) & 0x0ff;
                        if(lit&0xff) {
                                if(know_W != (int)(lit&0xff))
                                        emitpcode(POC_MOVLW,popGetLit(lit&0xff));
@@ -10071,8 +9991,6 @@ static void genAssign (iCode *ic)
                        } else
                                emitpcode(POC_CLRF, popGet(AOP(result),offset));
                        
-                       lit >>= 8;
-                       
                } else if (AOP_TYPE(right) == AOP_CRY) {
                        emitpcode(POC_CLRF, popGet(AOP(result),offset));
                        if(offset == 0) {
@@ -10550,6 +10468,7 @@ static void genReceive (iCode *ic)
                _G.accInUse++;
                aopOp(IC_RESULT(ic),ic,FALSE);
                _G.accInUse--;
+               GpsuedoStkPtr = ic->parmBytes; // address used arg on stack
                assignResultValue(IC_RESULT(ic));
        }
        
@@ -10594,10 +10513,8 @@ void genpic14Code (iCode *lic)
        addpBlock(pb);
        
        /* if debug information required */
-       if (options.debug && currFunc) { 
-               if (currFunc) {
-                       debugFile->writeFunction (currFunc, lic);
-               }
+       if (options.debug && debugFile && currFunc) { 
+               debugFile->writeFunction (currFunc, lic);
        }
        
        
@@ -10618,7 +10535,9 @@ void genpic14Code (iCode *lic)
                }
                
                if (options.iCodeInAsm) {
+                  char *iLine = printILine(ic);
                  emitpComment ("[ICODE] %s:%d: %s", ic->filename, ic->lineno, printILine (ic));
+                  dbuf_free(iLine);
                }
                /* if the result is marked as
                spilt and rematerializable or code for
@@ -10828,7 +10747,7 @@ void genpic14Code (iCode *lic)
                peepHole (&lineHead);
        }
        /* now do the actual printing */
-       printLine (lineHead,codeOutFile);
+       printLine (lineHead,codeOutBuf);
        
 #ifdef PCODE_DEBUG
        DFPRINTF((stderr,"printing pBlock\n\n"));
@@ -10866,3 +10785,4 @@ op_isLitLike (operand *op)
   if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1;
   return 0;
 }
+