pCode live-range analysis algorithms have been added.
authorsdattalo <sdattalo@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 23 Jun 2002 03:51:18 +0000 (03:51 +0000)
committersdattalo <sdattalo@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 23 Jun 2002 03:51:18 +0000 (03:51 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2026 4a8a32a2-be11-0410-ad9d-d568d2c75423

13 files changed:
ChangeLog
src/SDCCset.c
src/SDCCset.h
src/pic/device.c
src/pic/glue.c
src/pic/pcode.c
src/pic/pcode.h
src/pic/pcodepeep.c
src/pic/pcoderegs.c [new file with mode: 0644]
src/pic/pcoderegs.h [new file with mode: 0644]
src/pic/ralloc.c
src/pic/ralloc.h
support/scripts/inc2h.pl [new file with mode: 0755]

index 69d11c3bcb6e69c97a626a7b8a3d9ddf46aa0508..79c96134d38bb6d3bbd232780e37f3809c3d04c2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,14 @@
-2002-05-10  Scott Dattal <scott@dattalo.com>
+2002-06-22  Scott Dattalo <scott@dattalo.com>
+       * src/pic/*: Numerous bug fixes. Flow analysis has been enhanced. 
+       - Rewrote the register banking algorithm. 
+       - Added pCode live-range analysis to registers (for now, only non-used and 
+       singly-used registers optimized away)
+
+       * src/pic/pcoderegs.[ch]: Added new files for pCode live-range analysis
+
+       * support/scripts/inc2h.pl Kevin L. Pauba <klpauba@cox.net> submitted this perl script for converting MicroChip include files into SDCC Pic include files.
+       
+2002-05-10  Scott Dattalo <scott@dattalo.com>
        * src/pic/*: Added support for multiplication. Fixed many,many bugs.
        
 2002-04-22  Michael Hope  <michaelh@vroom>
index 61b68a05931d5364ba28ee3ae7131897fd0edd46..19babd6edbef3f32915d752ac77b8a1f6cc120e0 100644 (file)
@@ -31,7 +31,7 @@
 /* newSet - will allocate & return a new set entry             */
 /*-----------------------------------------------------------------*/
 set *
-newSet ()
+newSet (void)
 {
   set *lp;
 
index e3f1520fddd793f012f9fbea7e6749ab6e83dc74..39328e635f11cc9a5004fa1f1236b3f4b996e6f0 100644 (file)
@@ -54,6 +54,7 @@ set;
 #define V_ARG(type,var) type var = va_arg(ap,type)
 
 /* set related functions */
+set *newSet (void);
 void *addSet (set **, void *);
 void *addSetHead (set **, void *);
 void *getSet (set **);
index bf465f3817ba7024c3d1e621066988f4d4526693..b260f6f4c6c184a44923d75456d47e76ff7a6a18 100644 (file)
@@ -607,9 +607,9 @@ void assignRelocatableRegisters(set *regset, int used)
   for (reg = setFirstItem(regset) ; reg ; 
        reg = setNextItem(regset)) {
 
-    // fprintf(stdout,"assigning %s\n",reg->name);
+    //fprintf(stdout,"assigning %s isFixed=%d, wasUsed=%d\n",reg->name,reg->isFixed,reg->wasUsed);
 
-    if((!reg->isFixed) && ( (used==0) || reg->wasUsed))
+    if((!reg->isFixed) && ( used || reg->wasUsed))
       address = assignRegister(reg,address);
 
   }
@@ -630,7 +630,7 @@ void assignConfigWordValue(int address, int value)
   if(CONFIG_WORD_ADDRESS == address)
     config_word = value;
 
-  fprintf(stderr,"setting config word to 0x%x\n",value);
+  //fprintf(stderr,"setting config word to 0x%x\n",value);
 
 }
 /*-----------------------------------------------------------------*
index c3248fdcdf89329773626340297a980eebd92162..90cc028abacde26fcf6c4b4ac9aa11a1b398d13c 100644 (file)
@@ -866,8 +866,8 @@ picglue ()
     
 
   /* Put all variables into a cblock */
-  writeUsedRegs(asmFile);
   AnalyzeBanking();
+  writeUsedRegs(asmFile);
 
   /* create the overlay segments */
   fprintf (asmFile, "%s", iComments2);
index dce141969717b17f71135c06e06505a114a44b91..bd5be723ac94b4d6d37dfea004bb909b9aeaad16 100644 (file)
@@ -78,26 +78,13 @@ static int functionInlining = 1;      /* inline functions if nonzero */
 static int GpCodeSequenceNumber = 1;
 static int GpcFlowSeq = 1;
 
-#define isPCI(x)        ((PCODE(x)->type == PC_OPCODE))
-#define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isBranch)
-#define isPCI_SKIP(x)   ((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isSkip)
-#define isPCI_BITSKIP(x)((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isSkip && PCI(x)->isBitInst)
-#define isPCFL(x)       ((PCODE(x)->type == PC_FLOW))
-#define isPCF(x)        ((PCODE(x)->type == PC_FUNCTION))
-#define isPCL(x)        ((PCODE(x)->type == PC_LABEL))
-#define isPCW(x)        ((PCODE(x)->type == PC_WILD))
-#define isPCCS(x)       ((PCODE(x)->type == PC_CSOURCE))
-
-#define isCALL(x)       ((isPCI(x)) && (PCI(x)->op == POC_CALL))
-#define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS)
-
-#define isPCOLAB(x)     ((PCOP(x)->type) == PO_LABEL)
+extern void RemoveUnusedRegisters(void);
 
 /****************************************************************/
 /*                      Forward declarations                    */
 /****************************************************************/
 
-static void unlinkPC(pCode *pc);
+void unlinkpCode(pCode *pc);
 #if 0
 static void genericAnalyze(pCode *pc);
 static void AnalyzeGOTO(pCode *pc);
@@ -119,6 +106,12 @@ void pBlockStats(FILE *of, pBlock *pb);
 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
 extern pCodeOp *popCopyReg(pCodeOpReg *pc);
 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
+void pCodeRegMapLiveRanges(pBlock *pb);
+
+
+/****************************************************************/
+/*                    PIC Instructions                          */
+/****************************************************************/
 
 pCodeInstruction pciADDWF = {
   {PC_OPCODE, NULL, NULL, 0, NULL, 
@@ -410,7 +403,7 @@ pCodeInstruction pciCLRF = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_REGISTER, // inCond
+  PCC_NONE, // inCond
   PCC_REGISTER  // outCond
 };
 
@@ -431,7 +424,7 @@ pCodeInstruction pciCLRW = {
   0,0,  // dest, bit instruction
   0,0,  // branch, skip
   POC_NOP,
-  PCC_W, // inCond
+  PCC_NONE, // inCond
   PCC_W  // outCond
 };
 
@@ -1805,6 +1798,9 @@ pCode *newpCodeFlow(void )
   pcflow->ToConflicts = 0;
 
   pcflow->end = NULL;
+
+  pcflow->registers = newSet();
+
   return ( (pCode *)pcflow);
 
 }
@@ -2322,7 +2318,7 @@ void printpBlock(FILE *of, pBlock *pb)
 /*                                                                 */
 /*-----------------------------------------------------------------*/
 
-static void unlinkPC(pCode *pc)
+void unlinkpCode(pCode *pc)
 {
 
 
@@ -2343,7 +2339,7 @@ static void genericDestruct(pCode *pc)
 {
   //fprintf(stderr,"warning, calling default pCode destructor\n");
 
-  unlinkPC(pc);
+  unlinkpCode(pc);
 
   free(pc);
 
@@ -2371,33 +2367,38 @@ char *get_op(pCodeOp *pcop,char *buffer, int size)
   regs *r;
   static char b[50];
   char *s;
-  //  int size;
+  int use_buffer = 1;    // copy the string to the passed buffer pointer
 
   if(!buffer) {
     buffer = b;
     size = sizeof(b);
+    use_buffer = 0;     // Don't bother copying the string to the buffer.
   } 
 
   if(pcop) {
     switch(pcop->type) {
     case PO_INDF:
     case PO_FSR:
-      //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
-      //r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
-      //return r->name;
+      if(use_buffer) {
+       SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
+       return buffer;
+      }
       return PCOR(pcop)->r->name;
       break;
     case PO_GPR_TEMP:
       r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
-      //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
+
+      if(use_buffer) {
+       SAFE_snprintf(&buffer,&size,"%s",r->name);
+       return buffer;
+      }
+
       return r->name;
 
-      //    case PO_GPR_BIT:
-      //      return PCOR(pcc->pcop)->r)->name;
+
     case PO_IMMEDIATE:
       s = buffer;
-      //size = sizeof(buffer);
-      //fprintf(stderr,"PO_IMMEDIATE name = %s  offset = %d\n",pcc->pcop->name,PCOI(pcc->pcop)->offset);
+
       if(PCOI(pcop)->_const) {
 
        if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
@@ -2432,8 +2433,13 @@ char *get_op(pCodeOp *pcop,char *buffer, int size)
       return buffer;
 
     default:
-      if  (pcop->name)
+      if  (pcop->name) {
+       if(use_buffer) {
+         SAFE_snprintf(&buffer,&size,"%s",pcop->name);
+         return buffer;
+       }
        return pcop->name;
+      }
 
     }
   }
@@ -3093,7 +3099,7 @@ regs * getRegFromInstruction(pCode *pc)
   switch(PCI(pc)->pcop->type) {
   case PO_INDF:
   case PO_FSR:
-    return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
+    return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
 
   case PO_BIT:
   case PO_GPR_TEMP:
@@ -3160,10 +3166,11 @@ void AnalyzepBlock(pBlock *pb)
 
        if(!r) {
          /* register wasn't found */
-         r = Safe_calloc(1, sizeof(regs));
-         memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
-         addSet(&pb->tregisters, r);
-         PCOR(PCI(pc)->pcop)->r = r;
+         //r = Safe_calloc(1, sizeof(regs));
+         //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
+         //addSet(&pb->tregisters, r);
+         addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->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);
@@ -3311,7 +3318,7 @@ void unBuildFlow(pBlock *pb)
       PCI(pc)->pcflow = NULL;
       pc = pcn;
     } else if(isPCFL(pc)) {
-      unlinkPC(pc);
+      unlinkpCode(pc);
       pc->destruct(pc);
     } else 
       pc = pcn;
@@ -4202,7 +4209,7 @@ void pBlockRemoveUnusedLabels(pBlock *pb)
 
       DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
       if(pc->type == PC_LABEL) {
-       unlinkPC(pc);
+       unlinkpCode(pc);
        pCodeLabelDestruct(pc);
       } else {
        unlinkpCodeFromBranch(pc, PCODE(pcl));
@@ -4247,7 +4254,7 @@ void pBlockMergeLabels(pBlock *pb)
        pCode *pcn = pc->next;
 
        // Unlink the pCode label from it's pCode chain
-       unlinkPC(pc);
+       unlinkpCode(pc);
        
        //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
        // And link it into the instruction's pBranch labels. (Note, since
@@ -4277,7 +4284,7 @@ void pBlockMergeLabels(pBlock *pb)
        pCode *pcn = pc->next;
 
        // Unlink the pCode label from it's pCode chain
-       unlinkPC(pc);
+       unlinkpCode(pc);
        PCI(pcnext)->cline = PCCS(pc);
        //fprintf(stderr, "merging CSRC\n");
        //genericPrint(stderr,pcnext);
@@ -4560,6 +4567,12 @@ void AnalyzeBanking(void)
   for(pb = the_pFile->pbHead; pb; pb = pb->next)
     FixBankFlow(pb);
 
+
+  for(pb = the_pFile->pbHead; pb; pb = pb->next)
+    pCodeRegMapLiveRanges(pb);
+
+  RemoveUnusedRegisters();
+
 /*
   for(pb = the_pFile->pbHead; pb; pb = pb->next)
     DumpFlow(pb);
@@ -4668,7 +4681,8 @@ void buildCallTree(void    )
   /* Re-allocate the registers so that there are no collisions
    * between local variables when one function call another */
 
-  pic14_deallocateAllRegs();
+  // this is weird...
+  //  pic14_deallocateAllRegs();
 
   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
     if(!pb->visited)
index 8e4dd51acb5c49fc9a77d119074ce43f0a6062d4..9e6f97419e214a88d6043b96ecd9e65d7861a10b 100644 (file)
@@ -241,8 +241,11 @@ typedef enum
 /************************************************/
 /***************  Structures ********************/
 /************************************************/
+/* These are here as forward references - the 
+ * full definition of these are below           */
 struct pCode;
 struct pCodeWildBlock;
+struct pCodeRegLives;
 
 /*************************************************
   pBranch
@@ -423,6 +426,7 @@ typedef struct pCodeCSource
  causes a branch, a Flow object will be inserted into
  the pCode chain to mark the beginning of the next
  contiguous chunk.
+
 **************************************************/
 
 typedef struct pCodeFlow
@@ -451,6 +455,8 @@ typedef struct pCodeFlow
   int FromConflicts;
   int ToConflicts;
 
+  set *registers;/* Registers used in this flow */
+
 } pCodeFlow;
 
 /*************************************************
@@ -710,7 +716,6 @@ typedef struct peepCommand {
   char *cmd;
 } peepCommand;
 
-
 /*************************************************
     pCode Macros
 
@@ -736,6 +741,25 @@ typedef struct peepCommand {
 
 #define PCWB(x)   ((pCodeWildBlock *)(x))
 
+
+/*
+  macros for checking pCode types
+*/
+#define isPCI(x)        ((PCODE(x)->type == PC_OPCODE))
+#define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isBranch)
+#define isPCI_SKIP(x)   ((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isSkip)
+#define isPCI_BITSKIP(x)((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isSkip && PCI(x)->isBitInst)
+#define isPCFL(x)       ((PCODE(x)->type == PC_FLOW))
+#define isPCF(x)        ((PCODE(x)->type == PC_FUNCTION))
+#define isPCL(x)        ((PCODE(x)->type == PC_LABEL))
+#define isPCW(x)        ((PCODE(x)->type == PC_WILD))
+#define isPCCS(x)       ((PCODE(x)->type == PC_CSOURCE))
+
+#define isCALL(x)       ((isPCI(x)) && (PCI(x)->op == POC_CALL))
+#define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS)
+
+#define isPCOLAB(x)     ((PCOP(x)->type) == PO_LABEL)
+
 /*-----------------------------------------------------------------*
  * pCode functions.
  *-----------------------------------------------------------------*/
@@ -767,6 +791,11 @@ pCodeOp *newpCodeOpRegFromStr(char *name);
 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE p);
 pCodeOp *pCodeOpCopy(pCodeOp *pcop);
 
+pCode * findNextInstruction(pCode *pci);
+pCode * findNextpCode(pCode *pc, PC_TYPE pct);
+int isPCinFlow(pCode *pc, pCode *pcflow);
+struct regs * getRegFromInstruction(pCode *pc);
+
 extern void pcode_test(void);
 
 /*-----------------------------------------------------------------*
index 2ba9fd1f56f3054931a4f42b1703673cb3ba30eb..46a6b1d878d3acabfeb531e72a1a6ca7cbf65787 100644 (file)
@@ -1405,7 +1405,8 @@ int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
   }
 
   b[0]=0;
-  get_op(pcops,b,sizeof(b));
+  get_op(pcops,b,50);
+
   n2 = get_op(pcopd,NULL,0);
 
   if( !n2 || strcmp(b,n2)) {
@@ -1424,7 +1425,7 @@ int pCodeOpCompare(pCodeOp *pcops, pCodeOp *pcopd)
     break;
   }
 
-  //  fprintf(stderr,"  - pass\n");
+  //fprintf(stderr,"  - pass\n");
 
   return 1;
 }
diff --git a/src/pic/pcoderegs.c b/src/pic/pcoderegs.c
new file mode 100644 (file)
index 0000000..efbddfa
--- /dev/null
@@ -0,0 +1,302 @@
+/*-------------------------------------------------------------------------
+
+   pcoderegs.c - post code generation register optimizations
+
+   Written By -  Scott Dattalo scott@dattalo.com
+
+   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
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+-------------------------------------------------------------------------*/
+
+/*
+  pcoderegs.c
+
+  The purpose of the code in this file is to optimize the register usage.
+
+*/
+#include <stdio.h>
+
+#include "common.h"   // Include everything in the SDCC src directory
+#include "newalloc.h"
+#include "ralloc.h"
+#include "device.h"
+#include "pcode.h"
+#include "pcoderegs.h"
+#include "pcodeflow.h"
+
+extern void dbg_dumpregusage(void);
+void unlinkpCode(pCode *pc);
+
+/*-----------------------------------------------------------------*
+ * void AddRegToFlow(regs *reg, pCodeFlow *pcfl)
+ *-----------------------------------------------------------------*/
+/*
+void AddRegToFlow(regs *reg, pCodeFlow *pcfl)
+{
+
+  if(!reg || ! pcfl || !isPCFL(pcflow))
+    return;
+
+  if(!pcfl->registers) 
+    pcfl->registers =  newSet();
+
+}
+*/
+
+
+/*-----------------------------------------------------------------*
+ * 
+ *-----------------------------------------------------------------*/
+void dbg_regusage(set *fregs)
+{
+  regs *reg;
+  pCode *pcfl;
+  pCode *pc;
+
+
+  for (reg = setFirstItem(fregs) ; reg ;
+       reg = setNextItem(fregs)) {
+    
+    fprintf (stderr, "%s  addr=0x%03x rIdx=0x%03x",
+            reg->name,
+            reg->address,
+            reg->rIdx);
+
+    pcfl = setFirstItem(reg->reglives.usedpFlows);
+    if(pcfl)
+      fprintf(stderr, "\n   used in seq");
+
+    while(pcfl) {
+      fprintf(stderr," 0x%03x",pcfl->seq);
+      pcfl = setNextItem(reg->reglives.usedpFlows);
+    }
+
+    pcfl = setFirstItem(reg->reglives.assignedpFlows);
+    if(pcfl)
+      fprintf(stderr, "\n   assigned in seq");
+
+    while(pcfl) {
+      fprintf(stderr," 0x%03x",pcfl->seq);
+      pcfl = setNextItem(reg->reglives.assignedpFlows);
+    }
+
+    pc = setFirstItem(reg->reglives.usedpCodes);
+    if(pc)
+      fprintf(stderr, "\n   used in instructions ");
+
+    while(pc) {
+      pcfl = PCODE(PCI(pc)->pcflow);
+      if(pcfl)
+       fprintf(stderr," 0x%03x:",pcfl->seq);
+      fprintf(stderr,"0x%03x",pc->seq);
+
+      pc = setNextItem(reg->reglives.usedpCodes);
+    }
+
+    fprintf(stderr, "\n");
+
+  }
+}
+
+/*-----------------------------------------------------------------*
+ * 
+ *-----------------------------------------------------------------*/
+void dbg_dumpregusage(void)
+{
+
+  fprintf(stderr,"***  Register Usage  ***\n");
+  fprintf(stderr,"InternalRegs:\n");
+  dbg_regusage(dynInternalRegs);
+  fprintf(stderr,"AllocRegs:\n");
+  dbg_regusage(dynAllocRegs);
+  fprintf(stderr,"StackRegs:\n");
+  dbg_regusage(dynStackRegs);
+  fprintf(stderr,"DirectRegs:\n");
+  dbg_regusage(dynDirectRegs);
+  fprintf(stderr,"DirectBitRegs:\n");
+  dbg_regusage(dynDirectBitRegs);
+  fprintf(stderr,"ProcessorRegs:\n");
+  dbg_regusage(dynProcessorRegs);
+
+}
+
+
+/*-----------------------------------------------------------------*
+ * void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
+ *-----------------------------------------------------------------*/
+void pCodeRegMapLiveRangesInFlow(pCodeFlow *pcfl)
+{
+
+  pCode *pc=NULL;
+  pCode *pcprev=NULL;
+
+  regs *reg;
+
+  if(!pcfl)
+    return;
+
+
+  pc = findNextInstruction(pcfl->pc.next);
+
+  while(isPCinFlow(pc,PCODE(pcfl))) {
+
+
+    reg = getRegFromInstruction(pc);
+
+    if(reg) {
+/*
+      fprintf(stderr, "flow seq %d, inst seq %d  %s  ",PCODE(pcfl)->seq,pc->seq,reg->name);
+      fprintf(stderr, "addr = 0x%03x, type = %d  rIdx=0x%03x\n",
+             reg->address,reg->type,reg->rIdx);
+*/
+
+      addSetIfnotP(& (PCFL(pcfl)->registers), reg);
+
+      if(PCC_REGISTER & PCI(pc)->inCond)
+       addSetIfnotP(& (reg->reglives.usedpFlows), pcfl);
+
+      if(PCC_REGISTER & PCI(pc)->outCond)
+       addSetIfnotP(& (reg->reglives.assignedpFlows), pcfl);
+
+      addSetIfnotP(& (reg->reglives.usedpCodes), pc);
+    }
+
+
+    pcprev = pc;
+    pc = findNextInstruction(pc->next);
+
+  }
+
+}
+/*-----------------------------------------------------------------*
+ * void pCodeRegMapLiveRanges(pBlock *pb) 
+ *-----------------------------------------------------------------*/
+void pCodeRegMapLiveRanges(pBlock *pb)
+{
+  pCode *pcflow;
+
+  for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
+       pcflow != NULL;
+       pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
+
+    if(!isPCFL(pcflow)) {
+      fprintf(stderr, "pCodeRegMapLiveRanges - pcflow is not a flow object ");
+      continue;
+    }
+    pCodeRegMapLiveRangesInFlow(PCFL(pcflow));
+  }
+
+
+  for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
+       pcflow != NULL;
+       pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
+
+    regs *r = setFirstItem(PCFL(pcflow)->registers);
+    //fprintf(stderr,"flow seq %d\n", pcflow->seq);
+    while (r) {
+      //fprintf(stderr, "  %s\n",r->name);
+      r = setNextItem(PCFL(pcflow)->registers);
+
+    }
+
+  }
+
+  //  dbg_dumpregusage();
+
+}
+
+
+/*-----------------------------------------------------------------*
+ * void RemoveRegsFromSet(set *regset)
+ *
+ *-----------------------------------------------------------------*/
+void  RemoveRegsFromSet(set *regset)
+{
+  regs *reg;
+  int used;
+  for (reg = setFirstItem(regset) ; reg ;
+       reg = setNextItem(regset)) {
+
+
+    used = elementsInSet(reg->reglives.usedpCodes);
+
+    if(used <= 1) {
+
+      //fprintf(stderr," reg %s isfree=%d, wasused=%d\n",reg->name,reg->isFree,reg->wasUsed);
+
+      if(used == 0) {
+       //fprintf(stderr," getting rid of reg %s\n",reg->name);
+       reg->isFree = 1;
+       reg->wasUsed = 0;
+      } else {
+       pCode *pc;
+
+       //fprintf(stderr," reg %s used only once\n",reg->name);
+
+       pc = setFirstItem(reg->reglives.usedpCodes);
+       if(isPCI(pc)) {
+         if(PCI(pc)->label) {
+           pCode *pcn = findNextInstruction(pc->next);
+
+           if(pcn && PCI(pcn)->label) {
+             fprintf(stderr,"can't delete instruction with label...\n");
+             pc->print(stderr,pc);
+             continue;
+           } 
+           /* Move the label to the next instruction */
+
+           PCI(pcn)->label = PCI(pc)->label;
+
+         }
+
+         if(isPCI_SKIP(pc))
+           fprintf(stderr, "WARNING, a skip instruction is being optimized out\n");
+
+         unlinkpCode(pc);
+         deleteSetItem (&(reg->reglives.usedpCodes),pc);
+         reg->isFree = 1;
+         reg->wasUsed = 0;
+       }
+      }
+    }
+
+  }
+}
+/*-----------------------------------------------------------------*
+ * void RemoveUnusedRegisters(void)
+ *
+ *-----------------------------------------------------------------*/
+void RemoveUnusedRegisters(void)
+{
+
+
+  //fprintf(stderr,"InternalRegs:\n");
+  RemoveRegsFromSet(dynInternalRegs);
+  //fprintf(stderr,"AllocRegs:\n");
+  RemoveRegsFromSet(dynAllocRegs);
+  //fprintf(stderr,"StackRegs:\n");
+  RemoveRegsFromSet(dynStackRegs);
+
+  /*
+    don't do DirectRegs yet - there's a problem with arrays
+  //fprintf(stderr,"DirectRegs:\n");
+  RemoveRegsFromSet(dynDirectRegs);
+  */
+  //fprintf(stderr,"DirectBitRegs:\n");
+  RemoveRegsFromSet(dynDirectBitRegs);
+
+
+
+}
diff --git a/src/pic/pcoderegs.h b/src/pic/pcoderegs.h
new file mode 100644 (file)
index 0000000..c37d72f
--- /dev/null
@@ -0,0 +1,42 @@
+/*-------------------------------------------------------------------------
+
+   pcoderegs.h - post code generation register optimizations
+
+   Written By -  Scott Dattalo scott@dattalo.com
+
+   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
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+-------------------------------------------------------------------------*/
+
+#ifndef __PCODEREGS_H__
+#define __PCODEREGS_H__
+
+/*************************************************
+
+  pCodeRegLives 
+
+  Records the set of registers used in a flow object.
+
+**************************************************/
+
+typedef struct pCodeRegLives {
+  set *usedpFlows;       /* set of pFlow objects that use this register */
+  set *assignedpFlows;   /* set of pFlow objects that assign values to this register */
+  set *usedpCodes;       /* set of all instructions that use this register */
+
+} pCodeRegLives;
+
+
+#endif //  __PCODEREGS_H__
index f417f06481752bce556717ecd8e80da7ca83f7c1..e8394512b41c6bd29a2d4cfb6521f994383aa40f 100644 (file)
@@ -45,6 +45,7 @@
 /*-----------------------------------------------------------------*/
 
 extern void genpic14Code (iCode *);
+extern void assignConfigWordValue(int address, int value);
 
 /* Global data */
 static struct
@@ -64,12 +65,12 @@ _G;
 int pic14_ptrRegReq;           /* one byte pointer register required */
 
 
-static set *dynAllocRegs=NULL;
-static set *dynStackRegs=NULL;
-static set *dynProcessorRegs=NULL;
-static set *dynDirectRegs=NULL;
-static set *dynDirectBitRegs=NULL;
-static set *dynInternalRegs=NULL;
+set *dynAllocRegs=NULL;
+set *dynStackRegs=NULL;
+set *dynProcessorRegs=NULL;
+set *dynDirectRegs=NULL;
+set *dynDirectBitRegs=NULL;
+set *dynInternalRegs=NULL;
 
 static hTab  *dynDirectRegNames= NULL;
 
@@ -440,6 +441,8 @@ static regs* newReg(short type, short pc_type, int rIdx, char *name, int size, i
   dReg->size = size;
   dReg->alias = alias;
   dReg->reg_alias = NULL;
+  dReg->reglives.usedpFlows = newSet();
+  dReg->reglives.assignedpFlows = newSet();
 
   return dReg;
 }
@@ -711,7 +714,7 @@ allocRegByName (char *name, int size)
 /*-----------------------------------------------------------------*/
 /* RegWithIdx - returns pointer to register with index number       */
 /*-----------------------------------------------------------------*/
-static regs *
+regs *
 typeRegWithIdx (int idx, int type, int fixed)
 {
 
@@ -719,6 +722,40 @@ typeRegWithIdx (int idx, int type, int fixed)
 
   debugLog ("%s - requesting index = 0x%x\n", __FUNCTION__,idx);
 
+  switch (type) {
+
+  case REG_GPR:
+    if( (dReg = regWithIdx ( dynAllocRegs, idx, fixed)) != NULL) {
+
+      debugLog ("Found a Dynamic Register!\n");
+      return dReg;
+    }
+    if( (dReg = regWithIdx ( dynDirectRegs, idx, fixed)) != NULL ) {
+      debugLog ("Found a Direct Register!\n");
+      return dReg;
+    }
+
+    break;
+  case REG_STK:
+    if( (dReg = regWithIdx ( dynStackRegs, idx, fixed)) != NULL ) {
+      debugLog ("Found a Stack Register!\n");
+      return dReg;
+    }
+    break;
+  case REG_SFR:
+    if( (dReg = regWithIdx ( dynProcessorRegs, idx, fixed)) != NULL ) {
+      debugLog ("Found a Processor Register!\n");
+      return dReg;
+    }
+
+  case REG_CND:
+  case REG_PTR:
+  default:
+    break;
+  }
+
+#if 0
+
   if( (dReg = regWithIdx ( dynAllocRegs, idx, fixed)) != NULL) {
 
     debugLog ("Found a Dynamic Register!\n");
@@ -739,18 +776,15 @@ typeRegWithIdx (int idx, int type, int fixed)
     debugLog ("Found a Processor Register!\n");
     return dReg;
   }
-/*
-  if( (dReg = regWithIdx ( dynDirectBitRegs, idx, fixed)) != NULL ) {
+#endif
+
+  /*
+    if( (dReg = regWithIdx ( dynDirectBitRegs, idx, fixed)) != NULL ) {
     debugLog ("Found a bit Register!\n");
     return dReg;
-  }
-*/
-/*
-  fprintf(stderr,"%s %d - requested register: 0x%x\n",__FUNCTION__,__LINE__,idx);
-  werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-         "regWithIdx not found");
-  exit (1);
-*/
+    }
+  */
+
   return NULL;
 }
 
@@ -760,8 +794,18 @@ typeRegWithIdx (int idx, int type, int fixed)
 regs *
 pic14_regWithIdx (int idx)
 {
+  regs *dReg;
+
+  if( (dReg = typeRegWithIdx(idx,REG_GPR,0)) != NULL)
+    return dReg;
+
+  if( (dReg = typeRegWithIdx(idx,REG_SFR,0)) != NULL)
+    return dReg;
+
+  if( (dReg = typeRegWithIdx(idx,REG_STK,0)) != NULL)
+    return dReg;
 
-  return typeRegWithIdx(idx,-1,0);
+  return NULL;
 }
 
 /*-----------------------------------------------------------------*/
@@ -1001,7 +1045,7 @@ void aliasEQUs(FILE *of, set *fregs)
   for (reg = setFirstItem(fregs) ; reg ;
        reg = setNextItem(fregs)) {
 
-    if(!reg->isEmitted)
+    if(!reg->isEmitted && reg->wasUsed)
       fprintf (of, "%s\tEQU\t0x%03x\n",
               reg->name,
               reg->address);
@@ -1017,7 +1061,7 @@ void writeUsedRegs(FILE *of)
   assignFixedRegisters(dynStackRegs);
   assignFixedRegisters(dynDirectRegs);
 
-  assignRelocatableRegisters(dynInternalRegs,1);
+  assignRelocatableRegisters(dynInternalRegs,0);
   assignRelocatableRegisters(dynAllocRegs,0);
   assignRelocatableRegisters(dynStackRegs,0);
   assignRelocatableRegisters(dynDirectRegs,0);
@@ -1031,6 +1075,7 @@ void writeUsedRegs(FILE *of)
   aliasEQUs(of,dynStackRegs);
 
 }
+
 #if 0
 /*-----------------------------------------------------------------*/
 /* allDefsOutOfRange - all definitions are out of a range          */
@@ -2467,6 +2512,7 @@ DEFSETFUNC (markRegFree)
 
 DEFSETFUNC (deallocReg)
 {
+  fprintf(stderr,"deallocting register %s\n",((regs *)item)->name);
   ((regs *)item)->isFree = 1;
   ((regs *)item)->wasUsed = 0;
 
@@ -3765,7 +3811,7 @@ pic14_assignRegisters (eBBlock ** ebbs, int count)
   setToNull ((void **) &_G.stackSpil);
   setToNull ((void **) &_G.spiltSet);
   /* mark all registers as free */
-  pic14_freeAllRegs ();
+  //pic14_freeAllRegs ();
 
   debugLog ("leaving\n<><><><><><><><><><><><><><><><><>\n");
   debugLogClose ();
index f8af1de24e12e4794873f5653ef3360ac989c565..4e49651b5aa58e00fe96bfeed9bcf9a35362a3ec 100644 (file)
@@ -28,6 +28,7 @@
 #ifndef SDCCRALLOC_H
 #define SDCCRALLOC_H 1
 
+#include "pcoderegs.h"
 
 
 enum
@@ -68,18 +69,34 @@ typedef struct regs
     unsigned alias;             /* Alias mask if register appears in multiple banks */
     struct regs *reg_alias;     /* If more than one register share the same address 
                                 * then they'll point to each other. (primarily for bits)*/
+    pCodeRegLives reglives; /* live range mapping */
   }
 regs;
 extern regs regspic14[];
 extern int pic14_nRegs;
 extern int Gstack_base_addr;
 
+/*
+  As registers are created, they're added to a set (based on the
+  register type). Here are the sets of registers that are supported
+  in the PIC port:
+*/
+extern set *dynAllocRegs;
+extern set *dynStackRegs;
+extern set *dynProcessorRegs;
+extern set *dynDirectRegs;
+extern set *dynDirectBitRegs;
+extern set *dynInternalRegs;
+
+
 regs *pic14_regWithIdx (int);
 regs *dirregWithName (char *name );
 void  pic14_freeAllRegs ();
 void  pic14_deallocateAllRegs ();
 regs *pic14_findFreeReg(short type);
 regs *pic14_allocWithIdx (int idx);
+regs *typeRegWithIdx (int idx, int type, int fixed);
+
 regs *allocDirReg (operand *op );
 regs *allocRegByName (char *name, int size );
 
diff --git a/support/scripts/inc2h.pl b/support/scripts/inc2h.pl
new file mode 100755 (executable)
index 0000000..d586ed9
--- /dev/null
@@ -0,0 +1,209 @@
+#!/usr/bin/perl
+
+# Copyright (c) 2002 Kevin L. Pauba
+
+
+# License:
+#
+# SDCC is licensed under the GNU Public license (GPL) v2.  Note that
+# this license covers the code to the compiler and other executables,
+# but explicitly does not cover any code or objects generated by sdcc.
+# We have not yet decided on a license for the run time libraries, but
+# it will not put any requirements on code linked against it. See:
+# 
+# http://www.gnu.org/copyleft/gpl.html
+#
+# See http://sdcc.sourceforge.net/ for the latest information on sdcc.
+
+
+$rcsid = q~$Id$~;
+($junk, $file, $version, $date, $time, $programmer, $status)
+  = split(/\s+/, $rcsid);
+($programName) = ($file =~ /(\S+),v/);
+
+if ($#ARGV != 0) {
+       Usage();
+}
+
+#
+# Read the symbols at the end of this file.
+#
+while (<DATA>) {
+       next if /^\s*#/;
+
+       if (/^alias\s+(\S+)\s+(\S+)/) {
+               #
+               # Set an alias for a special function register.
+               # Some MPASM include files are not entirely consistent
+               # with sfr names.
+               #
+               $alias{$2} = $1;
+       } elsif (/^address\s+(\S+)\s+(\S+)/) {
+               #
+               # Set a default address for a special function register.
+               # Some MPASM include files don't specify the address
+               # of all registers.
+               # 
+               $addr{"$1"} = $2;
+       } elsif (/^(\S+)/) {
+               $type = $1;
+       } else {
+               foreach $key (split) {
+                       eval "\$type{'$key'} = $type;";
+               }
+       }
+}
+
+#
+# Print the header.
+#
+print <<EOT;
+//
+// This header file was automatically generated by:
+//
+//\t$programName V$version
+//
+// 
+
+#ifndef BIT_AT
+#define BIT_AT(base,bitno) bit at ((base<<3)+bitno)
+#endif
+
+
+EOT
+
+#
+# Convert the file.
+#
+$defaultType = 'other';
+while (<>) {
+       if (/^;-* (\S+) Bits/i) {
+               if (defined($alias{$1})) {
+                       $defaultType = "bits $alias{$1}";
+               } else {
+                       $defaultType = "bits $1";
+               }
+               s/;/\/\//;
+               print "$_";
+       } elsif (/^;-* Register Files/i) {
+               $defaultType = 'sfr';
+               s/;/\/\//;
+               print "$_";
+       } elsif (/^;=*/i) {
+               $defaultType = '';
+               s/;/\/\//;
+               print "$_";
+       } elsif (/^\s*;/) {
+               #
+               # Convert ASM comments to C style.
+               #
+               print "//$'";
+       } elsif (/^\s*IFNDEF __(\S+)/) {
+               #
+               # Processor type.
+               #
+               $processor = $1;
+               print "//$_";
+       } elsif (/^\s*(\S+)\s+EQU\s+H'(.+)'/) {
+               #
+               # Useful bit of information.
+               #
+               $name = $1;
+               $value = $2;
+               $rest = $';
+               $rest =~ s/;/\/\//;
+               chomp($rest);
+
+               if (defined($type{"$name"})) {
+                       $type = $type{"$name"};
+               } else {
+                       $type = $defaultType;
+               }
+
+               if ($type eq 'sfr') {
+                       #
+                       # A special function register.
+                       #
+                       printf("sfr at 0x%s %s;$rest\n", $value, $name);
+                       $addr{"$name"} = "0x$value";
+               } elsif ($type eq 'volatile') {
+                       #
+                       # A location that can change without 
+                       # direct program manipulation.
+                       #
+                       printf("data at 0x%s volatile char %s;$rest\n", $value, $name);
+               } elsif ($type =~ /^bits/) {
+                       ($junk, $register) = split(/\s/, $type);
+                       $bit = hex($value);
+                       $addr = $addr{"$register"};
+                       printf("BIT_AT($addr,$bit) $name;$rest\n");
+               } else {
+                       #
+                       # Other registers, bits and/or configurations.
+                       #
+                       if ($type eq 'other') {
+                               #
+                               # A known symbol.
+                               #
+                               printf("#define %-20s 0x%s$rest\n", $name, $value);
+                       } else {
+                               #
+                               # A symbol that isn't defined in the data
+                               # section at the end of the file.  Let's 
+                               # add a comment so that we can add it later.
+                               #
+                               printf("#define %-20s 0x%s$rest\n",
+                                      $name, $value);
+                       }
+               }
+       } elsif (/^\s*$/) {
+               #
+               # Blank line.
+               #
+               print;
+       } else {
+               #
+               # Anything else we'll just comment out.
+               #
+               print "// $_";
+       }
+}
+
+sub Usage {
+       print STDERR <<EOT;
+
+inc2h.pl - A utility to convert MPASM include files to header files
+           suitable for the SDCC compiler.
+
+License: Copyright (c) 2002 Kevin L. Pauba
+
+        SDCC is licensed under the GNU Public license (GPL) v2; see
+        http://www.gnu.org/copyleft/gpl.html See http://sdcc.sourceforge.net/
+        for the latest information on sdcc.
+
+Usage:   $programName [file]
+
+        where:
+
+        file   A MPASM include file name.  If none is supplied, the
+               standard input will be used.
+
+        The header file will be written to the standard output.
+
+
+EOT
+       exit;
+}
+
+__END__
+
+alias OPTION_REG OPTION
+address OPTION_REG 0x0081
+
+sfr
+
+volatile
+       INDF PCL
+
+bit
+