-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>
/* newSet - will allocate & return a new set entry */
/*-----------------------------------------------------------------*/
set *
-newSet ()
+newSet (void)
{
set *lp;
#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 **);
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);
}
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);
}
/*-----------------------------------------------------------------*
/* Put all variables into a cblock */
- writeUsedRegs(asmFile);
AnalyzeBanking();
+ writeUsedRegs(asmFile);
/* create the overlay segments */
fprintf (asmFile, "%s", iComments2);
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);
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,
0,0, // dest, bit instruction
0,0, // branch, skip
POC_NOP,
- PCC_REGISTER, // inCond
+ PCC_NONE, // inCond
PCC_REGISTER // outCond
};
0,0, // dest, bit instruction
0,0, // branch, skip
POC_NOP,
- PCC_W, // inCond
+ PCC_NONE, // inCond
PCC_W // outCond
};
pcflow->ToConflicts = 0;
pcflow->end = NULL;
+
+ pcflow->registers = newSet();
+
return ( (pCode *)pcflow);
}
/* */
/*-----------------------------------------------------------------*/
-static void unlinkPC(pCode *pc)
+void unlinkpCode(pCode *pc)
{
{
//fprintf(stderr,"warning, calling default pCode destructor\n");
- unlinkPC(pc);
+ unlinkpCode(pc);
free(pc);
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) {
return buffer;
default:
- if (pcop->name)
+ if (pcop->name) {
+ if(use_buffer) {
+ SAFE_snprintf(&buffer,&size,"%s",pcop->name);
+ return buffer;
+ }
return pcop->name;
+ }
}
}
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:
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);
PCI(pc)->pcflow = NULL;
pc = pcn;
} else if(isPCFL(pc)) {
- unlinkPC(pc);
+ unlinkpCode(pc);
pc->destruct(pc);
} else
pc = pcn;
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));
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
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);
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);
/* 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)
/************************************************/
/*************** Structures ********************/
/************************************************/
+/* These are here as forward references - the
+ * full definition of these are below */
struct pCode;
struct pCodeWildBlock;
+struct pCodeRegLives;
/*************************************************
pBranch
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
int FromConflicts;
int ToConflicts;
+ set *registers;/* Registers used in this flow */
+
} pCodeFlow;
/*************************************************
char *cmd;
} peepCommand;
-
/*************************************************
pCode Macros
#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.
*-----------------------------------------------------------------*/
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);
/*-----------------------------------------------------------------*
}
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)) {
break;
}
- // fprintf(stderr," - pass\n");
+ //fprintf(stderr," - pass\n");
return 1;
}
--- /dev/null
+/*-------------------------------------------------------------------------
+
+ 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);
+
+
+
+}
--- /dev/null
+/*-------------------------------------------------------------------------
+
+ 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__
/*-----------------------------------------------------------------*/
extern void genpic14Code (iCode *);
+extern void assignConfigWordValue(int address, int value);
/* Global data */
static struct
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;
dReg->size = size;
dReg->alias = alias;
dReg->reg_alias = NULL;
+ dReg->reglives.usedpFlows = newSet();
+ dReg->reglives.assignedpFlows = newSet();
return dReg;
}
/*-----------------------------------------------------------------*/
/* RegWithIdx - returns pointer to register with index number */
/*-----------------------------------------------------------------*/
-static regs *
+regs *
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");
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;
}
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;
}
/*-----------------------------------------------------------------*/
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);
assignFixedRegisters(dynStackRegs);
assignFixedRegisters(dynDirectRegs);
- assignRelocatableRegisters(dynInternalRegs,1);
+ assignRelocatableRegisters(dynInternalRegs,0);
assignRelocatableRegisters(dynAllocRegs,0);
assignRelocatableRegisters(dynStackRegs,0);
assignRelocatableRegisters(dynDirectRegs,0);
aliasEQUs(of,dynStackRegs);
}
+
#if 0
/*-----------------------------------------------------------------*/
/* allDefsOutOfRange - all definitions are out of a range */
DEFSETFUNC (deallocReg)
{
+ fprintf(stderr,"deallocting register %s\n",((regs *)item)->name);
((regs *)item)->isFree = 1;
((regs *)item)->wasUsed = 0;
setToNull ((void **) &_G.stackSpil);
setToNull ((void **) &_G.spiltSet);
/* mark all registers as free */
- pic14_freeAllRegs ();
+ //pic14_freeAllRegs ();
debugLog ("leaving\n<><><><><><><><><><><><><><><><><>\n");
debugLogClose ();
#ifndef SDCCRALLOC_H
#define SDCCRALLOC_H 1
+#include "pcoderegs.h"
enum
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 );
--- /dev/null
+#!/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
+