* src/pic16/glue.c (pic16emitMaps),
[fw/sdcc] / src / pic / gen.c
index 9a221d2572e7dc313a9e59175548df408d33b20b..652e84880a26e1e5d655a1fc54aa4ee85928f5fb 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 *);
 void genMult8X8_8 (operand *, operand *,operand *);
@@ -55,6 +60,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 
@@ -66,7 +72,6 @@ static int GpsuedoStkPtr=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)
@@ -185,7 +190,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 +274,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 +300,7 @@ void pic14_emitcode (char *inst,char *fmt, ...)
 {
        va_list ap;
        char lb[INITIAL_INLINEASM];  
-       unsigned char *lbp = lb;
+       unsigned char *lbp = (unsigned char *)lb;
        
        va_start(ap,fmt);   
        
@@ -937,9 +949,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 +963,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), 
@@ -1196,9 +1216,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:
@@ -1423,10 +1442,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) {
@@ -2591,7 +2615,7 @@ static void genCall (iCode *ic)
 {
        sym_link *dtype;         
        symbol *sym;
-       unsigned char *name;
+       char *name;
        int isExtern;
        
        FENTRY;
@@ -2762,7 +2786,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);
        
@@ -2874,6 +2898,9 @@ 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)));
        
@@ -2921,6 +2948,7 @@ static void genFunction (iCode *ic)
                emitpcode(POC_CLRF,   popCopyReg(&pc_pclath));/* during an interrupt PCLATH must be cleared before a goto or call statement */
                
                pBlockConvert2ISR(pb);
+               pic14_hasInterrupt = 1;
 #if 0  
                if (!inExcludeList("acc"))              
                        pic14_emitcode ("push","acc");  
@@ -8450,6 +8478,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 +8520,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 +8589,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 +8627,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 +8724,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 +9158,7 @@ static void genPointerGet (iCode *ic)
        switch (p_type) {
                
        case POINTER: 
+       case FPOINTER:
        //case IPOINTER:
                genNearPointerGet (left,result,ic);
                break;
@@ -9192,6 +9225,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 +9265,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 +9302,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 +9344,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 +9370,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 +9388,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 +9408,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 +9455,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);
@@ -9774,6 +9780,7 @@ static void genPointerSet (iCode *ic)
        switch (p_type) {
                
        case POINTER:
+       case FPOINTER:
        //case IPOINTER:
                genNearPointerSet (right,result,ic);
                break;
@@ -9814,8 +9821,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 +9828,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 +9867,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 +10073,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 +10086,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 +10098,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 +10575,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));
        }