* use dynamic memory buffers instead temporary files
[fw/sdcc] / src / pic / gen.c
index 9bd3fc3f12aa7c84053f36ac514aebb04a5557e4..c3328398b62f66cf939cf7913ceb496276854e41 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 */
@@ -59,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 
@@ -67,10 +69,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)
@@ -114,7 +116,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;
@@ -189,7 +191,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;
@@ -273,8 +275,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)
@@ -292,7 +301,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);   
        
@@ -313,6 +322,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));
@@ -941,9 +951,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",
@@ -952,6 +965,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), 
@@ -1200,9 +1218,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:
@@ -1427,10 +1444,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) {
@@ -2595,7 +2617,7 @@ static void genCall (iCode *ic)
 {
        sym_link *dtype;         
        symbol *sym;
-       unsigned char *name;
+       char *name;
        int isExtern;
        
        FENTRY;
@@ -2670,13 +2692,18 @@ 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);
+       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 */
@@ -2766,7 +2793,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);
        
@@ -2878,6 +2905,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)));
        
@@ -2909,7 +2939,9 @@ static void genFunction (iCode *ic)
 #endif
        
        /* if this is an interrupt service routine */
+       pic14_inISR = 0;
        if (IFFUNC_ISISR(sym->type)) {
+               pic14_inISR = 1;
        /*  already done in pic14createInterruptVect() - delete me
        addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR)));
        emitpcodeNULLop(POC_NOP);
@@ -2925,6 +2957,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");  
@@ -5455,7 +5488,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;
 }
 
@@ -5467,7 +5504,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;
 }
 
@@ -5622,16 +5663,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++;
                        }
@@ -9346,38 +9400,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                 */
 /*-----------------------------------------------------------------*/
@@ -9396,7 +9418,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);
@@ -9413,23 +9438,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++;
@@ -10080,9 +10103,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) {
@@ -10096,8 +10116,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));
@@ -10106,8 +10128,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) {
@@ -10585,6 +10605,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));
        }
        
@@ -10653,7 +10674,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
@@ -10863,7 +10886,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"));