pCode - register allocation, flow analysis, and peephole.
authorsdattalo <sdattalo@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sat, 24 Mar 2001 16:00:57 +0000 (16:00 +0000)
committersdattalo <sdattalo@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sat, 24 Mar 2001 16:00:57 +0000 (16:00 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@708 4a8a32a2-be11-0410-ad9d-d568d2c75423

src/pic/gen.c
src/pic/glue.c
src/pic/main.c
src/pic/pcode.c
src/pic/pcode.h
src/pic/ralloc.c
src/pic/ralloc.h
src/regression/Makefile
src/regression/b.c

index 32a45cf081318ba5fe4bc91295d4095957d835ac..0ce2ee34338864828891c5b9279c58e117148390 100644 (file)
@@ -120,7 +120,7 @@ static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
 
 #define FUNCTION_LABEL_INC  20
 static int labelOffset=0;
-static int debug_verbose=1;
+static int debug_verbose=0;
 
 static  pBlock *pb;
 
@@ -207,7 +207,8 @@ static void emitcode (char *inst,char *fmt, ...)
     lineCurr->isInline = _G.inLine;
     lineCurr->isDebug  = _G.debugLine;
 
-    addpCode2pBlock(pb,newpCodeCharP(lb));
+    if(debug_verbose)
+      addpCode2pBlock(pb,newpCodeCharP(lb));
 
     va_end(ap);
 }
@@ -1118,18 +1119,31 @@ static pCodeOp *popGet (asmop *aop, int offset, bool bit16, bool dname)
        return pcop;
        
     case AOP_REG:
-      DEBUGemitcode(";","%d",__LINE__);
-      pcop = Safe_calloc(1,sizeof(pCodeOp) );
-      pcop->type = PO_GPR_REGISTER;
-      if (dname)
-       rs = aop->aopu.aop_reg[offset]->dname;
-      else 
-       rs = aop->aopu.aop_reg[offset]->name;
-
-      DEBUGemitcode(";","%d  %s",__LINE__,rs);
-      pcop->name = Safe_calloc(1,(strlen(rs)+1));
-      strcpy(pcop->name,rs);   
-      return pcop;
+      {
+       int len;
+
+       DEBUGemitcode(";","%d",__LINE__);
+       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
+       pcop->type = PO_GPR_REGISTER;
+       if (dname)
+         rs = aop->aopu.aop_reg[offset]->dname;
+       else 
+         rs = aop->aopu.aop_reg[offset]->name;
+
+       PCOR(pcop)->rIdx = aop->aopu.aop_reg[offset]->rIdx;
+       PCOR(pcop)->r = pic14_regWithIdx(aop->aopu.aop_reg[offset]->rIdx);
+       // Really nasty hack to check for temporary registers
+       len = strlen(rs);
+       if(len >=3 && rs[0]=='r' && rs[1]=='0' && rs[2]=='x')
+         pcop->type = PO_GPR_TEMP;
+       else
+         fprintf(stderr,"popGet - AOP_REG is not a temp: %s\n",rs);
+
+       DEBUGemitcode(";","%d  %s",__LINE__,rs);
+       pcop->name = NULL;// Safe_calloc(1,(strlen(rs)+1));
+       //strcpy(pcop->name,rs);   
+       return pcop;
+      }
 
     case AOP_CRY:
       pcop = newpCodeOpBit(aop->aopu.aop_dir,0);
@@ -8938,7 +8952,7 @@ void genpic14Code (iCode *lic)
 
     lineHead = lineCurr = NULL;
 
-    pb = newpCodeChain(GcurMemmap,newpCodeCharP("; Starting pCode block"));
+    pb = newpCodeChain(GcurMemmap,0,newpCodeCharP("; Starting pCode block"));
     addpBlock(pb);
 
     /* if debug information required */
index 06616818ea0b3e791b7a172310349f8ad92816ee..32f86b4e5ce2b776f7cc41295617e041f8b225f8 100644 (file)
@@ -1001,6 +1001,49 @@ picglue ()
   int i;
 
   addSetHead(&tmpfileSet,ovrFile);
+
+
+  if (mainf && mainf->fbody) {
+
+    pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
+    addpBlock(pb);
+
+    /* entry point @ start of CSEG */
+    addpCode2pBlock(pb,newpCodeLabelStr("__sdcc_program_startup"));
+    /* put in the call to main */
+    addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
+
+    if (options.mainreturn) {
+
+      addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
+      addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
+
+    } else {
+
+      addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
+      addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
+
+    }
+  }
+
+
+  /* At this point we've got all the code in the form of pCode structures */
+  /* Now it needs to be rearranged into the order it should be placed in the */
+  /* code space */
+
+  movepBlock2Head(code->dbName);     // Last
+  movepBlock2Head('X');
+  movepBlock2Head(statsg->dbName);   // First
+
+
+  AnalyzepCode('*'); //code->dbName);
+  printCallTree(stderr);
+
+  pCodePeepInit();
+
+  OptimizepCode(code->dbName);
+
+
   /* print the global struct definitions */
   if (options.debug)
     cdbStructBlock (0,cdbFile);
@@ -1063,14 +1106,13 @@ picglue ()
     
 
   /* Put all variables into a cblock */
-  fprintf (asmFile, "\n\n\tcblock  0x13\n\n");
+  fprintf (asmFile, "\n\n\tcblock  0x0c\n\n");
 
   for(i=0; i<pic14_nRegs; i++) {
     if(regspic14[i].wasUsed && (regspic14[i].offset>=0x0c) )
       fprintf (asmFile, "\t%s\n",regspic14[i].name);
   }
-  //fprintf (asmFile, "\tr0x0C\n");
-  //fprintf (asmFile, "\tr0x0D\n");
+
 
   /* For now, create a "dpl" and a "dph" in the register space */
   /* of the pic so that we can use the same calling mechanism */
@@ -1182,26 +1224,7 @@ picglue ()
              (unsigned int)options.xdata_loc & 0xff);
     }
 
-    /* initialise the stack pointer */
-    /* if the user specified a value then use it */
-    if (options.stack_loc) 
-      fprintf(asmFile,";\tmov\tsp,#%d\n",options.stack_loc);
-    else 
-      /* no: we have to compute it */
-      if (!options.stackOnData && maxRegBank <= 3)
-       fprintf(asmFile,";\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1); 
-      else
-       fprintf(asmFile,";\tmov\tsp,#__start__stack\n"); /* MOF */
-
-    fprintf (asmFile,";\tlcall\t__sdcc_external_startup\n");
-    fprintf (asmFile,";\tmov\ta,dpl\n");
-    fprintf (asmFile,";\tjz\t__sdcc_init_data\n");
-    fprintf (asmFile,";\tljmp\t__sdcc_program_startup\n");
-    fprintf (asmFile,";__sdcc_init_data:\n");
-       
   }
-  //copyFile (asmFile, statsg->oFile);
-  copypCode(asmFile, statsg->dbName);
 
   if (port->general.glue_up_main && mainf && mainf->fbody)
     {
@@ -1218,33 +1241,13 @@ picglue ()
   fprintf (asmFile, "; code\n");
   fprintf (asmFile, "%s", iComments2);
   fprintf (asmFile, ";\t.area %s\n", port->mem.code_name);
-  if (mainf && mainf->fbody) {
-       
-    /* entry point @ start of CSEG */
-    fprintf (asmFile,"__sdcc_program_startup:\n");
-       
-    /* put in the call to main */
-    fprintf(asmFile,"\tcall\t_main\n");
-    if (options.mainreturn) {
-
-      fprintf(asmFile,";\treturn from main ; will return to caller\n");
-      fprintf(asmFile,"\treturn\n");
-
-    } else {
-                  
-      fprintf(asmFile,";\treturn from main will lock up\n");
-      fprintf(asmFile,"\tgoto\t$\n");
-    }
-  }
 
-  AnalyzepCode(code->dbName);
-  pCodePeepInit();
-
-  OptimizepCode(code->dbName);
   //copyFile (asmFile, code->oFile);
+
+  copypCode(asmFile, statsg->dbName);
+  copypCode(asmFile, 'X');
   copypCode(asmFile, code->dbName);
 
-  printCallTree(stderr);
 
   fprintf (asmFile,"\tend\n");
 
index ebc5839bde0d96d6aa83d46938e723937e7f276a..2c0f3154da655250b50024ddbf6ef52b10cbff65 100644 (file)
@@ -83,6 +83,9 @@ _pic14_parseOptions (int *pargc, char **argv, int *i)
 static void
 _pic14_finaliseOptions (void)
 {
+
+      port->mem.default_local_map = data;
+      port->mem.default_globl_map = data;
 #if 0
   /* Hack-o-matic: if we are using the flat24 model,
    * adjust pointer sizes.
index 3c5e1ec18302da58ae08fc4bdc8eab7112e2ce05..3b464c3480bd23c63cc35ebec6625fd01501ffb2 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "common.h"   // Include everything in the SDCC src directory
 #include "newalloc.h"
+#include "ralloc.h"
 
 #include "pcode.h"
 
@@ -65,6 +66,7 @@ static char *scpXORWF = "XORWF";
 
 static pFile *the_pFile = NULL;
 static int peepOptimizing = 1;
+static int GpCodeSequenceNumber = 1;
 
 /****************************************************************/
 /****************************************************************/
@@ -122,6 +124,60 @@ char *Safe_strdup(char *str)
     
 }
 
+char getpBlock_dbName(pBlock *pb)
+{
+  if(!pb)
+    return 0;
+
+  if(pb->cmemmap)
+    return pb->cmemmap->dbName;
+
+  return pb->dbName;
+}
+/*-----------------------------------------------------------------*/
+/* movepBlock2Head - given the dbname of a pBlock, move all        */
+/*                   instances to the front of the doubly linked   */
+/*                   list of pBlocks                               */
+/*-----------------------------------------------------------------*/
+
+void movepBlock2Head(char dbName)
+{
+  pBlock *pb;
+
+  pb = the_pFile->pbHead;
+
+  while(pb) {
+
+    if(getpBlock_dbName(pb) == dbName) {
+      pBlock *pbn = pb->next;
+      pb->next = the_pFile->pbHead;
+      the_pFile->pbHead->prev = pb;
+      the_pFile->pbHead = pb;
+
+      if(pb->prev)
+       pb->prev->next = pbn;
+
+      // If the pBlock that we just moved was the last
+      // one in the link of all of the pBlocks, then we
+      // need to point the tail to the block just before
+      // the one we moved.
+      // Note: if pb->next is NULL, then pb must have 
+      // been the last pBlock in the chain.
+
+      if(pbn)
+       pbn->prev = pb->prev;
+      else
+       the_pFile->pbTail = pb->prev;
+
+      pb = pbn;
+
+    } else
+      pb = pb->next;
+
+  }
+
+}
+
 void copypCode(FILE *of, char dbName)
 {
   pBlock *pb;
@@ -129,10 +185,8 @@ void copypCode(FILE *of, char dbName)
   if(!of || !the_pFile)
     return;
 
-  fprintf(of,";dumping pcode to a file");
-
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
-    if(pb->cmemmap->dbName == dbName)
+    if(getpBlock_dbName(pb) == dbName)
       printpBlock(of,pb);
   }
 
@@ -161,7 +215,12 @@ void pcode_test(void)
 
     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
       fprintf(pFile,"\n\tNew pBlock\n\n");
-      fprintf(pFile,"%s, dbName =%c\n",pb->cmemmap->sname,pb->cmemmap->dbName);
+      if(pb->cmemmap)
+       fprintf(pFile,"%s",pb->cmemmap->sname);
+      else
+       fprintf(pFile,"internal pblock");
+
+      fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
       printpBlock(pFile,pb);
     }
   }
@@ -169,6 +228,24 @@ void pcode_test(void)
 
 /*-----------------------------------------------------------------*/
 /* newpCode - create and return a newly initialized pCode          */
+/*                                                                 */
+/*  fixme - rename this                                            */
+/*                                                                 */
+/* The purpose of this routine is to create a new Instruction      */
+/* pCode. This is called by gen.c while the assembly code is being */
+/* generated.                                                      */
+/*                                                                 */
+/* Inouts:                                                         */
+/*  PIC_OPCODE op - the assembly instruction we wish to create.    */
+/*                  (note that the op is analogous to but not the  */
+/*                  same thing as the opcode of the instruction.)  */
+/*  pCdoeOp *pcop - pointer to the operand of the instruction.     */
+/*                                                                 */
+/* Outputs:                                                        */
+/*  a pointer to the new malloc'd pCode is returned.               */
+/*                                                                 */
+/*                                                                 */
+/*                                                                 */
 /*-----------------------------------------------------------------*/
 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
 {
@@ -176,22 +253,31 @@ pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
     
 
   pci = Safe_calloc(1, sizeof(pCodeInstruction));
-  pci->pc.analyze = genericAnalyze;
-  pci->pc.destruct = genericDestruct;
-  pci->pc.type = PC_OPCODE;
-  pci->op = op;
-  pci->pc.prev = pci->pc.next = NULL;
-  pci->pcop = pcop;
-  pci->dest = 0;
-  pci->bit_inst = 0;
-  pci->num_ops = 2;
-  pci->inCond = pci->outCond = PCC_NONE;
-  pci->pc.print = genericPrint;
-  pci->pc.from = pci->pc.to = pci->pc.label = NULL;
+
+  pci->pc.analyze  = genericAnalyze;       // pointers to the generic functions, it
+  pci->pc.destruct = genericDestruct;      // doesn't hurt to think about C++ virtual
+  pci->pc.print    = genericPrint;         // functions here.
+  pci->pc.type = PC_OPCODE;                // 
+  pci->op = op;                            // the "opcode" for the instruction.
+  pci->pc.prev = pci->pc.next = NULL;      // The pCode gets linked in later
+  pci->pcop = pcop;                        // The operand of the instruction
+  pci->dest = 0;                           // e.g. W or F 
+  pci->bit_inst = 0;                       // e.g. btfxx instructions
+  pci->num_ops = 2;                        // Most instructions have two ops...
+  pci->inCond = pci->outCond = PCC_NONE;   /* input/output conditions. This is used during
+                                           * optimization to ascertain instruction dependencies.
+                                           * For example, if an instruction affects the Z bit,
+                                           * then the output condition for this instruction
+                                           * is "z bit is affected". The "conditions" are bit
+                                           * constants defined in pcode.h. */
+  pci->pc.from = pci->pc.to = NULL;        // Flow linkages are defined later
+  pci->pc.label = NULL;                    // Labels get merged into instructions here.
+  pci->pc.pb = NULL;                       // The pBlock to which this instruction belongs
 
   if(pcop && pcop->name)
     printf("newpCode  operand name %s\n",pcop->name);
 
+  // The most pic dependent portion of the pCode logic:
   switch(op) { 
 
   case POC_ANDLW:
@@ -354,6 +440,19 @@ pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
   return (pCode *)pci;
 }      
 
+/*-----------------------------------------------------------------*/
+/* newpCodeWild - create a "wild" as in wild card pCode            */
+/*                                                                 */
+/* Wild pcodes are used during the peep hole optimizer to serve    */
+/* as place holders for any instruction. When a snippet of code is */
+/* compared to a peep hole rule, the wild card opcode will match   */
+/* any instruction. However, the optional operand and label are    */
+/* additional qualifiers that must also be matched before the      */
+/* line (of assembly code) is declared matched. Note that the      */
+/* operand may be wild too.                                        */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+
 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
 {
 
@@ -364,6 +463,7 @@ pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_la
   pcw->pc.type = PC_WILD;
   pcw->pc.prev = pcw->pc.next = NULL;
   pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
+  pcw->pc.pb = NULL;
 
   pcw->pc.analyze = genericAnalyze;
   pcw->pc.destruct = genericDestruct;
@@ -391,6 +491,7 @@ pCode *newpCodeCharP(char *cP)
   pcc->pc.type = PC_COMMENT;
   pcc->pc.prev = pcc->pc.next = NULL;
   pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
+  pcc->pc.pb = NULL;
 
   pcc->pc.analyze = genericAnalyze;
   pcc->pc.destruct = genericDestruct;
@@ -416,6 +517,7 @@ pCode *newpCodeFunction(char *mod,char *f)
   pcf->pc.type = PC_FUNCTION;
   pcf->pc.prev = pcf->pc.next = NULL;
   pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
+  pcf->pc.pb = NULL;
 
   pcf->pc.analyze = genericAnalyze;
   pcf->pc.destruct = genericDestruct;
@@ -449,6 +551,7 @@ pCode *newpCodeLabel(int key)
   pcl->pc.type = PC_LABEL;
   pcl->pc.prev = pcl->pc.next = NULL;
   pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
+  pcl->pc.pb = NULL;
 
   pcl->pc.analyze = genericAnalyze;
   pcl->pc.destruct = genericDestruct;
@@ -465,6 +568,14 @@ pCode *newpCodeLabel(int key)
   return ( (pCode *)pcl);
 
 }
+pCode *newpCodeLabelStr(char *str)
+{
+  pCode *pc = newpCodeLabel(-1);
+
+  PCL(pc)->label = Safe_strdup(str);
+
+  return pc;
+}
 
 /*-----------------------------------------------------------------*/
 /* newpBlock - create and return a pointer to a new pBlock         */
@@ -477,6 +588,10 @@ pBlock *newpBlock(void)
   _ALLOC(PpB,sizeof(pBlock));
   PpB->next = PpB->prev = NULL;
 
+  PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
+  PpB->registers = NULL;
+  PpB->visited = 0;
+
   return PpB;
 
 }
@@ -490,13 +605,14 @@ pBlock *newpBlock(void)
  *-----------------------------------------------------------------*/
 
 
-pBlock *newpCodeChain(memmap *cm,pCode *pc)
+pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
 {
 
-  pBlock *pB = newpBlock();
+  pBlock *pB  = newpBlock();
 
-  pB->pcHead = pB->pcTail = pc;
+  pB->pcHead  = pB->pcTail = pc;
   pB->cmemmap = cm;
+  pB->dbName  = c;
 
   return pB;
 }
@@ -576,6 +692,7 @@ pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
   PCOW(pcop)->id = id;
   PCOW(pcop)->pcp = pcp;
   PCOW(pcop)->subtype = subtype;
+  PCOW(pcop)->matched = NULL;
 
   return pcop;
 }
@@ -588,7 +705,10 @@ pCodeOp *newpCodeOpBit(char *s, int bit)
   pcop->type = PO_BIT;
   pcop->name = Safe_strdup(s);   
   PCOB(pcop)->bit = bit;
-  PCOB(pcop)->inBitSpace = 1;
+  if(bit>=0)
+    PCOB(pcop)->inBitSpace = 1;
+  else
+    PCOB(pcop)->inBitSpace = 0;
 
   return pcop;
 }
@@ -602,6 +722,7 @@ void addpCode2pBlock(pBlock *pb, pCode *pc)
   pb->pcTail->next = pc;
   pc->prev = pb->pcTail;
   pc->next = NULL;
+  pc->pb = pb;
   pb->pcTail = pc;
 }
 
@@ -673,9 +794,6 @@ void printpBlock(FILE *of, pBlock *pb)
 /*                                                                 */
 /*       pCode processing                                          */
 /*                                                                 */
-/*    The stuff that follows is very PIC specific!                 */
-/*                                                                 */
-/*                                                                 */
 /*                                                                 */
 /*                                                                 */
 /*-----------------------------------------------------------------*/
@@ -696,10 +814,41 @@ static void genericDestruct(pCode *pc)
   free(pc);
 }
 
+
+void pBlockRegs(FILE *of, pBlock *pb)
+{
+
+  regs  *r;
+
+  r = setFirstItem(pb->registers);
+  while (r) {
+    fprintf(of,"   %s\n",r->name);
+    r = setNextItem(pb->registers);
+  }
+}
+
+
 static char *get_op( pCodeInstruction *pcc)
 {
-  if(pcc && pcc->pcop && pcc->pcop->name)
+  if(pcc && pcc->pcop) {
+
+
+
+  if(pcc->pcop->type == PO_GPR_TEMP) {
+    regs *r;
+    r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
+    //pcc->pcop->name = Safe_strdup(r->name);
+    //sprintf(buffer, "R0X%x",PCOR(pcc->pcop)->rIdx);
+    //pcc->pcop->name = Safe_strdup(PCOR(pcc->pcop)->r->name);
+    fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
+    pBlockRegs(stderr,pcc->pc.pb);
+    return r->name;
+  }
+
+  if  (pcc->pcop->name)
     return pcc->pcop->name;
+
+  }
   return "NO operand";
 }
 
@@ -753,10 +902,17 @@ static void genericPrint(FILE *of, pCode *pc)
       } else {
 
        if(PCI(pc)->pcop->type == PO_BIT) {
+         if( PCI(pc)->num_ops == 2)
+           fprintf(of,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
+         else
+           fprintf(of,"(1 << (%s & 7))",get_op(PCI(pc)));
+
+/*
          if( PCI(pc)->num_ops == 2)
            fprintf(of,"(%s >> 3),%c",PCI(pc)->pcop->name,((PCI(pc)->dest) ? 'F':'W'));
          else
            fprintf(of,"(1 << (%s & 7))",PCI(pc)->pcop->name);
+*/
        }else {
          fprintf(of,"%s",get_op(PCI(pc)));
 
@@ -826,7 +982,7 @@ static void pCodePrintFunction(FILE *of, pCode *pc)
       i++;
       exits = exits->next;
     }
-    if(i) i--;
+    //if(i) i--;
     fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
     
   }else {
@@ -1144,9 +1300,36 @@ void AnalyzepBlock(pBlock *pb)
   if(!pb)
     return;
 
-  for(pc = pb->pcHead; pc; pc = pc->next)
-    pc->analyze(pc);
+  /* Find all of the registers used in this pBlock */
+  for(pc = pb->pcHead; pc; pc = pc->next) {
+    if(pc->type == PC_OPCODE) {
+      if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
+
+       /* Loop through all of the registers declared so far in
+          this block and see if we find this new there */
 
+       regs *r = setFirstItem(pb->registers);
+
+       while(r) {
+         if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
+           PCOR(PCI(pc)->pcop)->r = r;
+           break;
+         }
+         r = setNextItem(pb->registers);
+       }
+
+       if(!r) {
+         /* register wasn't found */
+         r = Safe_calloc(1, sizeof(regs));
+         memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
+         addSet(&pb->registers, r);
+         PCOR(PCI(pc)->pcop)->r = r;
+         fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
+       } else 
+         fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
+      }
+    }
+  }
 }
 
 int OptimizepBlock(pBlock *pb)
@@ -1225,7 +1408,7 @@ void OptimizepCode(char dbName)
 
   do {
     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
-      if(pb->cmemmap->dbName == dbName)
+      if('*' == dbName || getpBlock_dbName(pb) == dbName)
        matches += OptimizepBlock(pb);
     }
   }
@@ -1254,37 +1437,70 @@ void AnalyzepCode(char dbName)
 
   /* First, merge the labels with the instructions */
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
-    if(pb->cmemmap->dbName == dbName)
+    if('*' == dbName || getpBlock_dbName(pb) == dbName) {
       pBlockMergeLabels(pb);
+      AnalyzepBlock(pb);
+    }
   }
 
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
-    if(pb->cmemmap->dbName == dbName)
+    if('*' == dbName || getpBlock_dbName(pb) == dbName)
       OptimizepBlock(pb);
   }
 
   /* Now build the call tree.
      First we examine all of the pCodes for functions.
-     
+     Keep in mind that the function boundaries coincide
+     with pBlock boundaries. 
+
+     The algorithm goes something like this:
+     We have two nested loops. The outer loop iterates
+     through all of the pBlocks/functions. The inner
+     loop iterates through all of the pCodes for
+     a given pBlock. When we begin iterating through
+     a pBlock, the variable pc_fstart, pCode of the start
+     of a function, is cleared. We then search for pCodes
+     of type PC_FUNCTION. When one is encountered, we
+     initialize pc_fstart to this and at the same time
+     associate a new pBranch object that signifies a 
+     branch entry. If a return is found, then this signifies
+     a function exit point. We'll link the pCodes of these
+     returns to the matching pc_fstart.
+
+     When we're done, a doubly linked list of pBranches
+     will exist. The head of this list is stored in
+     `the_pFile', which is the meta structure for all
+     of the pCode. Look at the printCallTree function
+     on how the pBranches are linked together.
+
    */
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
-    if(pb->cmemmap->dbName == dbName) {
+    if('*' == dbName || getpBlock_dbName(pb) == dbName) {
       pCode *pc_fstart=NULL;
       for(pc = pb->pcHead; pc; pc = pc->next) {
        if(pc->type == PC_FUNCTION) {
          if (PCF(pc)->fname) {
+           // I'm not liking this....
            // Found the beginning of a function.
            _ALLOC(pbr,sizeof(pBranch));
            pbr->pc = pc_fstart = pc;
            pbr->next = NULL;
 
            the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
+
+           // Here's a better way of doing the same:
+           addSet(&pb->function_entries, pc);
+
          } else {
            // Found an exit point in a function, e.g. return
            // (Note, there may be more than one return per function)
            if(pc_fstart)
              pBranchLink(pc_fstart, pc);
+
+           addSet(&pb->function_exits, pc);
          }
+       } else  if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
+         addSet(&pb->function_calls,pc);
        }
       }
     }
@@ -1304,9 +1520,338 @@ bool ispCodeFunction(pCode *pc)
   return 0;
 }
 
+/*-----------------------------------------------------------------*/
+/* findFunction - Search for a function by name (given the name)   */
+/*                in the set of all functions that are in a pBlock */
+/* (note - I expect this to change because I'm planning to limit   */
+/*  pBlock's to just one function declaration                      */
+/*-----------------------------------------------------------------*/
+pCode *findFunction(char *fname)
+{
+  pBlock *pb;
+  pCode *pc;
+  if(!fname)
+    return NULL;
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+
+    pc = setFirstItem(pb->function_entries);
+    while(pc) {
+    
+      if((pc->type == PC_FUNCTION) &&
+        (PCF(pc)->fname) && 
+        (strcmp(fname, PCF(pc)->fname)==0))
+       return pc;
+
+      pc = setNextItem(pb->function_entries);
+
+    }
+
+  }
+  return NULL;
+}
+
+void MarkUsedRegisters(set *regset)
+{
+
+  regs *r1,*r2;
+
+  for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
+    r2 = pic14_regWithIdx(r1->rIdx);
+    r2->isFree = 0;
+    r2->wasUsed = 1;
+  }
+}
+
+void pBlockStats(FILE *of, pBlock *pb)
+{
+
+  pCode *pc;
+  regs  *r;
+
+  fprintf(of,"***\n  pBlock Stats\n***\n");
+
+  // for now just print the first element of each set
+  pc = setFirstItem(pb->function_entries);
+  if(pc) {
+    fprintf(of,"entry\n");
+    pc->print(of,pc);
+  }
+  pc = setFirstItem(pb->function_exits);
+  if(pc) {
+    fprintf(of,"has an exit\n");
+    pc->print(of,pc);
+  }
+
+  pc = setFirstItem(pb->function_calls);
+  if(pc) {
+    fprintf(of,"functions called\n");
+
+    while(pc) {
+      pc->print(of,pc);
+      pc = setNextItem(pb->function_calls);
+    }
+  }
+
+  r = setFirstItem(pb->registers);
+  if(r) {
+    int n = elementsInSet(pb->registers);
+
+    fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
+
+    while (r) {
+      fprintf(of,"   %s\n",r->name);
+      r = setNextItem(pb->registers);
+    }
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void sequencepCode(void)
+{
+  pBlock *pb;
+  pCode *pc;
+
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+
+    pb->seq = GpCodeSequenceNumber+1;
+
+    for( pc = pb->pcHead; pc; pc = pc->next)
+      pc->seq = ++GpCodeSequenceNumber;
+  }
+
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+set *register_usage(pBlock *pb)
+{
+  pCode *pc,*pcn;
+  set *registers=NULL;
+  set *registersInCallPath = NULL;
+
+  /* check recursion */
+
+  pc = setFirstItem(pb->function_entries);
+
+  if(!pc)
+    return registers;
+
+  pb->visited = 1;
+
+  if(pc->type != PC_FUNCTION)
+    fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
+
+  pc = setFirstItem(pb->function_calls);
+  for( ; pc; pc = setNextItem(pb->function_calls)) {
+
+    if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
+      char *dest = get_op(PCI(pc));
+
+      pcn = findFunction(dest);
+      if(pcn) 
+       registersInCallPath = register_usage(pcn->pb);
+    } else
+      fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
+
+  }
+
+
+  pBlockStats(stderr,pb);  // debug
+  if(registersInCallPath) {
+    /* registers were used in the functions this pBlock has called */
+    /* so now, we need to see if these collide with the ones we are */
+    /* using here */
+
+    regs *r1,*r2, *newreg;
+
+    fprintf(stderr,"comparing registers\n");
+
+    r1 = setFirstItem(registersInCallPath);
+    while(r1) {
+
+      r2 = setFirstItem(pb->registers);
+
+      while(r2) {
+
+       if(r2->rIdx == r1->rIdx) {
+         newreg = pic14_findFreeReg();
+
+
+         if(!newreg) {
+           fprintf(stderr,"Bummer, no more registers.\n");
+           exit(1);
+         }
+
+         fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
+                 r1->rIdx, newreg->rIdx);
+         r2->rIdx = newreg->rIdx;
+         //if(r2->name) free(r2->name);
+         r2->name = Safe_strdup(newreg->name);
+         newreg->isFree = 0;
+         newreg->wasUsed = 1;
+       }
+       r2 = setNextItem(pb->registers);
+      }
+
+      r1 = setNextItem(registersInCallPath);
+    }
+
+    /* Collisions have been resolved. Now free the registers in the call path */
+    r1 = setFirstItem(registersInCallPath);
+    while(r1) {
+      newreg = pic14_regWithIdx(r1->rIdx);
+      newreg->isFree = 1;
+      r1 = setNextItem(registersInCallPath);
+    }
+
+  } else
+    MarkUsedRegisters(pb->registers);
+
+  registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
+
+  if(registers) 
+    fprintf(stderr,"returning regs\n");
+  else
+    fprintf(stderr,"not returning regs\n");
+
+  fprintf(stderr,"pBlock after register optim.\n");
+  pBlockStats(stderr,pb);  // debug
+
+
+  return registers;
+}
+
+/*-----------------------------------------------------------------*/
+/* printCallTree - writes the call tree to a file                  */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+void pct2(FILE *of,pBlock *pb,int indent)
+{
+  pCode *pc,*pcn;
+  int i;
+  //  set *registersInCallPath = NULL;
+
+  if(!of)
+    return;// registers;
+
+  if(indent > 10)
+    return; // registers;   //recursion ?
+
+  pc = setFirstItem(pb->function_entries);
+
+  if(!pc)
+    return;
+
+  pb->visited = 0;
+
+  for(i=0;i<indent;i++)   // Indentation
+    fputc(' ',of);
+
+  if(pc->type == PC_FUNCTION)
+    fprintf(of,"%s\n",PCF(pc)->fname);
+  else
+    return;  // ???
+
+
+  pc = setFirstItem(pb->function_calls);
+  for( ; pc; pc = setNextItem(pb->function_calls)) {
+
+    if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
+      char *dest = get_op(PCI(pc));
+
+      pcn = findFunction(dest);
+      if(pcn) 
+       pct2(of,pcn->pb,indent+1);
+    } else
+      fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
+
+  }
+
+
+}
+
+#if 0
+  fprintf(stderr,"pBlock before register optim.\n");
+  pBlockStats(stderr,pb);  // debug
+
+  if(registersInCallPath) {
+    /* registers were used in the functions this pBlock has called */
+    /* so now, we need to see if these collide with the ones we are using here */
+
+    regs *r1,*r2, *newreg;
+
+    fprintf(stderr,"comparing registers\n");
+
+    r1 = setFirstItem(registersInCallPath);
+    while(r1) {
+
+      r2 = setFirstItem(pb->registers);
+
+      while(r2) {
+
+       if(r2->rIdx == r1->rIdx) {
+         newreg = pic14_findFreeReg();
+
+
+         if(!newreg) {
+           fprintf(stderr,"Bummer, no more registers.\n");
+           exit(1);
+         }
+
+         fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
+                 r1->rIdx, newreg->rIdx);
+         r2->rIdx = newreg->rIdx;
+         //if(r2->name) free(r2->name);
+         r2->name = Safe_strdup(newreg->name);
+         newreg->isFree = 0;
+         newreg->wasUsed = 1;
+       }
+       r2 = setNextItem(pb->registers);
+      }
+
+      r1 = setNextItem(registersInCallPath);
+    }
+
+    /* Collisions have been resolved. Now free the registers in the call path */
+    r1 = setFirstItem(registersInCallPath);
+    while(r1) {
+      newreg = pic14_regWithIdx(r1->rIdx);
+      newreg->isFree = 1;
+      r1 = setNextItem(registersInCallPath);
+    }
+
+  } else
+    MarkUsedRegisters(pb->registers);
+
+  registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
+
+  if(registers) 
+    fprintf(stderr,"returning regs\n");
+  else
+    fprintf(stderr,"not returning regs\n");
+
+  fprintf(stderr,"pBlock after register optim.\n");
+  pBlockStats(stderr,pb);  // debug
+
+
+  return registers;
+
+#endif
+
+
+/*-----------------------------------------------------------------*/
+/* printCallTree - writes the call tree to a file                  */
+/*                                                                 */
+/*-----------------------------------------------------------------*/
+
 void printCallTree(FILE *of)
 {
   pBranch *pbr;
+  pBlock  *pb;
+  pCode   *pc;
 
   if(!the_pFile)
     return;
@@ -1314,12 +1859,17 @@ void printCallTree(FILE *of)
   if(!of)
     of = stderr;
 
-  pbr = the_pFile->functions;
+  fprintf(of, "\npBlock statistics\n");
+  for(pb = the_pFile->pbHead; pb;  pb = pb->next )
+    pBlockStats(stderr,pb);
+
+
 
   fprintf(of,"Call Tree\n");
+  pbr = the_pFile->functions;
   while(pbr) {
     if(pbr->pc) {
-      pCode *pc = pbr->pc;
+      pc = pbr->pc;
       if(!ispCodeFunction(pc))
        fprintf(of,"bug in call tree");
 
@@ -1335,6 +1885,27 @@ void printCallTree(FILE *of)
 
     pbr = pbr->next;
   }
+
+
+  /* Re-allocate the registers so that there are no collisions
+   * between local variables when one function call another */
+
+  pic14_deallocateAllRegs();
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+    if(!pb->visited)
+      register_usage(pb);
+  }
+
+  fprintf(of,"\n**************\n\na better call tree\n");
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+    if(pb->visited)
+      pct2(of,pb,0);
+  }
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next) {
+    fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
+  }
 }
 /*-----------------------------------------------------------------
 
@@ -1431,12 +2002,12 @@ void pCodePeepInit(void)
   peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
 
 
-  pb = newpCodeChain(NULL, newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
+  pb = newpCodeChain(NULL, 'W', newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
   addpCode2pBlock( pb,     newpCode(POC_MOVFW, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
 
   pcp->target = pb;
 
-  pcp->replace = newpCodeChain(NULL, newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
+  pcp->replace = newpCodeChain(NULL, 'W',newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
 
   /* Allocate space to store pointers to the wildcard variables */
   pcp->nvars = 1;
@@ -1460,8 +2031,10 @@ void pCodePeepInit(void)
   {
     pCodeOp *pcl;
     pCodeOp *pcw;
+    pCodeOp *pcwb;
 
-    pb = newpCodeChain(NULL, newpCode(POC_BTFSC, newpCodeOpWild(0,pcp,newpCodeOpBit(NULL,-1))) );
+    pcwb =  newpCodeOpWild(0,pcp,newpCodeOpBit(NULL,-1));
+    pb = newpCodeChain(NULL, 'W',newpCode(POC_BTFSC,pcwb));
 
     pcl = newpCodeOpLabel(-1);
     pcw = newpCodeOpWild(1, pcp, pcl);
@@ -1472,7 +2045,7 @@ void pCodePeepInit(void)
 
     pcp->target = pb;
 
-    pb = newpCodeChain(NULL, newpCode(POC_BTFSS, newpCodeOpWild(0,pcp,newpCodeOpBit(NULL,-1))) );
+    pb = newpCodeChain(NULL, 'W',newpCode(POC_BTFSS, pcwb));
     addpCode2pBlock( pb,     newpCodeWild(0,NULL,NULL));
     addpCode2pBlock( pb,     newpCodeWild(1,NULL,pcw));
 
@@ -1509,12 +2082,12 @@ void pCodePeepInit(void)
 
     pcw = newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER));
 
-    pb = newpCodeChain(NULL, newpCode(POC_MOVWF, pcw));
+    pb = newpCodeChain(NULL, 'W', newpCode(POC_MOVWF, pcw));
     addpCode2pBlock( pb,     newpCode(POC_MOVWF, pcw));
 
     pcp->target = pb;
 
-    pb = newpCodeChain(NULL, newpCode(POC_MOVWF, pcw));
+    pb = newpCodeChain(NULL, 'W',newpCode(POC_MOVWF, pcw));
 
     pcp->replace = pb;
 
@@ -1590,17 +2163,28 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
        if (PCI(pcd)->pcop->type == PO_WILD) {
          index = PCOW(PCI(pcd)->pcop)->id;
 
+         fprintf(stderr,"destination is wild\n");
 #ifdef DEBUG_PCODEPEEP
          if (index > peepBlock->nvars) {
            fprintf(stderr,"%s - variables exceeded\n",__FUNCTION__);
            exit(1);
          }
 #endif
-         if(peepBlock->vars[index])
-           return (strcmp(peepBlock->vars[index],PCI(pcs)->pcop->name) == 0);
-         else {
-           peepBlock->vars[index] = PCI(pcs)->pcop->name;
-           return 1;
+         PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
+         {
+           char *n;
+
+           if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
+             n = PCOR(PCI(pcs)->pcop)->r->name;
+           else
+             n = PCI(pcs)->pcop->name;
+
+           if(peepBlock->vars[index])
+             return  (strcmp(peepBlock->vars[index],n) == 0);
+           else {
+             peepBlock->vars[index] = n; //PCI(pcs)->pcop->name;
+             return 1;
+           }
          }
        }
       } else
@@ -1644,6 +2228,7 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
     }
 
     if(PCW(pcd)->operand) {
+      PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
       if(peepBlock->vars[index]) {
        int i = (strcmp(peepBlock->vars[index],PCI(pcs)->pcop->name) == 0);
        if(i)
@@ -1661,9 +2246,12 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
       }
     }
 
-    pcs = findNextInstruction(pcs->next);
-    fprintf(stderr," (next to match)\n");
-    pcs->print(stderr,pcs);
+    pcs = findNextInstruction(pcs->next); 
+    if(pcs) {
+      fprintf(stderr," (next to match)\n");
+      pcs->print(stderr,pcs);
+    }
+
     return 1; /*  wild card matches */
   }
 
@@ -1721,8 +2309,15 @@ static pCodeOp *pCodeOpCopy(pCodeOp *pcop)
   case PO_WILD:
     /* Here we expand the wild card into the appropriate type: */
     /* By recursively calling pCodeOpCopy */
-    pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
-    pcopnew->name = Safe_strdup(PCOW(pcop)->pcp->vars[PCOW(pcop)->id]);
+    if(PCOW(pcop)->matched)
+      pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
+    else {
+      // Probably a label
+      pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
+      pcopnew->name = Safe_strdup(PCOW(pcop)->pcp->vars[PCOW(pcop)->id]);
+      fprintf(stderr,"copied a wild op named %s\n",pcopnew->name);
+    }
+
     return pcopnew;
     break;
 
@@ -1738,6 +2333,7 @@ static pCodeOp *pCodeOpCopy(pCodeOp *pcop)
     break;
 
   case PO_GPR_REGISTER:
+  case PO_GPR_TEMP:
   case PO_SFR_REGISTER:
   case PO_DIR:
   case PO_STR:
@@ -1817,7 +2413,7 @@ int pCodePeepMatchRule(pCode *pc)
        fprintf(stderr," end of rule\n");
     }
 
-    if(matched) {
+    if(matched && pcin) {
 
       /* So far we matched the rule up to the point of the conditions .
        * In other words, all of the opcodes match. Now we need to see
@@ -1833,7 +2429,7 @@ int pCodePeepMatchRule(pCode *pc)
        matched = 0;
     }
 
-    if(matched) {
+    if(matched && pcin) {
 
       pCode *pcprev;
       pCode *pcr;
@@ -1849,7 +2445,6 @@ int pCodePeepMatchRule(pCode *pc)
       fprintf(stderr,"last thing matched\n");
       pcin->print(stderr,pcin);
 
-
       /* Unlink the original code */
       pcprev = pc->prev;
       pcprev->next = pcin;
@@ -1862,7 +2457,7 @@ int pCodePeepMatchRule(pCode *pc)
       while (pcr) {
        pCodeOp *pcop=NULL;
        /* If the replace pcode is an instruction with an operand, */
-       /* then duplicate the operand (and expand wild cards in the process. */
+       /* then duplicate the operand (and expand wild cards in the process). */
        if(pcr->type == PC_OPCODE) {
          if(PCI(pcr)->pcop)
            pcop = pCodeOpCopy(PCI(pcr)->pcop);
@@ -1872,7 +2467,9 @@ int pCodePeepMatchRule(pCode *pc)
          pCodeInsertAfter(pc,peepBlock->wildpCodes[PCW(pcr)->id]);
        }
 
+
        pc = pc->next;
+       pc->print(stderr,pc);
        pcr = pcr->next;
       }
 
index 0682ea2c857d7833fd96c74b7e0c68a36a05936c..eaf70478f91ca14921f2f0fc689a65b3055ef6ea 100644 (file)
@@ -19,6 +19,8 @@
    
 -------------------------------------------------------------------------*/
 
+#include "ralloc.h"
+
 /*
    Post code generation
 
@@ -102,6 +104,7 @@ typedef enum
   PO_FSR,            // The "file select register" (in 18c it's one of three)
   PO_INDF,           // The Indirect register
   PO_GPR_REGISTER,   // A general purpose register
+  PO_GPR_TEMP,       // A general purpose temporary register
   PO_SFR_REGISTER,   // A special function register (e.g. PORTA)
   PO_LITERAL,        // A constant
   PO_IMMEDIATE,      //  (8051 legacy)
@@ -283,6 +286,14 @@ typedef struct pCodeOpLabel
   int key;
 } pCodeOpLabel;
 
+typedef struct pCodeOpReg
+{
+  pCodeOp pcop;    // Can be either GPR or SFR
+  int rIdx;        // Index into the register table
+  regs *r;
+  struct pBlock *pb;
+} pCodeOpReg;
+
 
 
 /*************************************************
@@ -301,10 +312,14 @@ typedef struct pCode
   struct pCode *prev;  // The pCode objects are linked together
   struct pCode *next;  // in doubly linked lists.
 
+  int seq;             // sequence number
+
   pBranch *from;       // pCodes that execute before this one
   pBranch *to;         // pCodes that execute after
   pBranch *label;      // pCode instructions that have labels
 
+  struct pBlock *pb;   // The pBlock that contains this pCode.
+
   /* "virtual functions"
    *  The pCode structure is like a base class
    * in C++. The subsequent structures that "inherit"
@@ -424,12 +439,22 @@ typedef struct pCodeWild
 typedef struct pBlock
 {
   memmap *cmemmap;   /* The snippet is from this memmap */
+  char   dbName;     /* if cmemmap is NULL, then dbName will identify the block */
   pCode *pcHead;     /* A pointer to the first pCode in a link list of pCodes */
   pCode *pcTail;     /* A pointer to the last pCode in a link list of pCodes */
 
   struct pBlock *next;      /* The pBlocks will form a doubly linked list */
   struct pBlock *prev;
 
+  set *function_entries;    /* dll of functions in this pblock */
+  set *function_exits;
+  set *function_calls;
+  set *registers;
+
+  unsigned visited:1;       /* set true if traversed in call tree */
+
+  unsigned seq;             /* sequence number of this pBlock */
+
 } pBlock;
 
 /*************************************************
@@ -500,6 +525,9 @@ typedef struct pCodeOpWild
                           * the wild card. The array is in *pcp. */
   pCodeOp *subtype;       /* Pointer to the Operand type into which this wild
                           * card will be expanded */
+  pCodeOp *matched;       /* When a wild matches, we'll store a pointer to the
+                          * opcode we matched */
+
 } pCodeOpWild;
 
 /*************************************************
@@ -516,6 +544,7 @@ typedef struct pCodeOpWild
 #define PCOB(x)   ((pCodeOpBit *)(x))
 #define PCOL(x)   ((pCodeOpLit *)(x))
 #define PCOLAB(x) ((pCodeOpLabel *)(x))
+#define PCOR(x)   ((pCodeOpReg *)(x))
 #define PCOW(x)   ((pCodeOpWild *)(x))
 
 #define PBR(x)    ((pBranch *)(x))
@@ -527,13 +556,15 @@ typedef struct pCodeOpWild
 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop); // Create a new pCode given an operand
 pCode *newpCodeCharP(char *cP);              // Create a new pCode given a char *
 pCode *newpCodeFunction(char *g, char *f);   // Create a new function
-pCode *newpCodeLabel(int key);               // Create a new label
-pBlock *newpCodeChain(memmap *cm,pCode *pc); // Create a new pBlock
+pCode *newpCodeLabel(int key);               // Create a new label given a key
+pCode *newpCodeLabelStr(char *str);          // Create a new label given a string
+pBlock *newpCodeChain(memmap *cm,char c, pCode *pc); // Create a new pBlock
 void printpBlock(FILE *of, pBlock *pb);      // Write a pBlock to a file
 void printpCode(FILE *of, pCode *pc);        // Write a pCode to a file
 void addpCode2pBlock(pBlock *pb, pCode *pc); // Add a pCode to a pBlock
 void addpBlock(pBlock *pb);                  // Add a pBlock to a pFile
 void copypCode(FILE *of, char dbName);       // Write all pBlocks with dbName to *of
+void movepBlock2Head(char dbName);           // move pBlocks around
 void AnalyzepCode(char dbName);
 void OptimizepCode(char dbName);
 void printCallTree(FILE *of);
index 3a0ab79c178aab7b25dd9715622ec3f627fbfbe5..9907b9b237d6e7829bbab7493dbdb1edc4406117 100644 (file)
@@ -493,6 +493,19 @@ pic14_regWithIdx (int idx)
   exit (1);
 }
 
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+regs *
+pic14_findFreeReg(void)
+{
+  int i;
+
+  for (i = 0; i < pic14_nRegs; i++)
+    if (regspic14[i].isFree)
+      return &regspic14[i];
+
+  return NULL;
+}
 /*-----------------------------------------------------------------*/
 /* freeReg - frees a register                                      */
 /*-----------------------------------------------------------------*/
@@ -1923,8 +1936,8 @@ regTypeNum ()
 /*-----------------------------------------------------------------*/
 /* freeAllRegs - mark all registers as free                        */
 /*-----------------------------------------------------------------*/
-static void
-freeAllRegs ()
+void
+pic14_freeAllRegs ()
 {
   int i;
 
@@ -1933,6 +1946,21 @@ freeAllRegs ()
     regspic14[i].isFree = 1;
 }
 
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+void
+pic14_deallocateAllRegs ()
+{
+  int i;
+
+  debugLog ("%s\n", __FUNCTION__);
+  for (i = 0; i < pic14_nRegs; i++) {
+    regspic14[i].isFree = 1;
+    regspic14[i].wasUsed = 0;
+  }
+}
+
+
 /*-----------------------------------------------------------------*/
 /* deallocStackSpil - this will set the stack pointer back         */
 /*-----------------------------------------------------------------*/
@@ -3064,7 +3092,7 @@ pic14_assignRegisters (eBBlock ** ebbs, int count)
   setToNull ((void **) &_G.stackSpil);
   setToNull ((void **) &_G.spiltSet);
   /* mark all registers as free */
-  freeAllRegs ();
+  pic14_freeAllRegs ();
 
   debugLog ("leaving\n<><><><><><><><><><><><><><><><><>\n");
   debugLogClose ();
index 1ce9ee8ad65d08e077f1bc18159cc42e4bd3c5da..d0d38f5dee08b2c85d7752dbdfaf250d7a1a0977 100644 (file)
@@ -60,7 +60,9 @@ extern regs regspic14[];
 extern int pic14_nRegs;
 
 regs *pic14_regWithIdx (int);
-
+void  pic14_freeAllRegs ();
+void  pic14_deallocateAllRegs ();
+regs *pic14_findFreeReg(void);
 
 enum PIC_register_types
   {
index 4442d5a33ae4d6d904f5308fd1cc9037d0ae221c..31b090bfb291cc20c9db8b5dd8374f0c5928aee2 100644 (file)
@@ -72,7 +72,7 @@ all:  test
 
 # The asm files are generated by sdcc
 .c.asm:
-       $(CC) -mpic -c $*.c
+       $(CC) -mpic14 -c $*.c
 
 # The .cod files are generated by gpasm
 # these get loaded by gpsim.
index 94d915cb3f09f726271b80a7bb1b571ce2b8b3ba..144f5ae8f16506d24219a7aee444da88d3b19d10 100644 (file)
@@ -16,11 +16,26 @@ void incptr(unsigned char *ucP)
   *ucP = *ucP + 1;
 }
 
+
 void inc(unsigned char k)
 {
   uchar0 = uchar0 + k;
 }
 
+void f1(void)
+{
+
+  uchar2++;
+}
+
+void nested_call(unsigned char u)
+{
+
+  f1();
+  uchar1 = uchar1 + u;
+  inc(uchar1);
+
+}
   //  uchar1 = uchar1 + uchar0;
   //  uchar2 = uchar1 + k;
 
@@ -33,5 +48,13 @@ void main(void)
   if(uchar0 !=2)
     success++;
 
+  uchar0 = 2;
+  uchar1 = 1;
+  uchar2 = 1;
+  nested_call(uchar2);
+
+  if(uchar0 !=4)
+    success++;
+
   done();
 }