PO_GPR_REGISTER, // A general purpose register
PO_GPR_BIT, // A bit of a general purpose register
PO_GPR_TEMP, // A general purpose temporary register
+ PO_GPR_POINTER, // A general purpose pointer
PO_SFR_REGISTER, // A special function register (e.g. PORTA)
PO_PCL, // Program counter Low register
PO_PCLATH, // Program counter Latch high register
POC_COMFW,
POC_CLRF,
POC_CLRW,
+ POC_CLRWDT,
POC_DECF,
POC_DECFW,
POC_DECFSZ,
typedef enum
{
PC_COMMENT=0, /* pCode is a comment */
+ PC_INLINE, /* user's inline code */
PC_OPCODE, /* PORT dependent opcode */
PC_LABEL, /* assembly label */
PC_FLOW, /* flow analysis */
PC_FUNCTION, /* Function start or end */
- PC_WILD /* wildcard - an opcode place holder used
+ PC_WILD, /* wildcard - an opcode place holder used
* in the pCode peep hole optimizer */
+ PC_CSOURCE, /* C-Source Line */
+ PC_BAD /* Mark the pCode object as being bad */
} PC_TYPE;
/************************************************/
/*************** Structures ********************/
/************************************************/
+/* These are here as forward references - the
+ * full definition of these are below */
struct pCode;
+struct pCodeWildBlock;
+struct pCodeRegLives;
/*************************************************
pBranch
typedef struct pCodeOpImmd
{
pCodeOp pcop;
- int offset;
+ int offset; /* low,med, or high byte of immediate value */
+ int index; /* add this to the immediate value */
+ unsigned _const:1; /* is in code space */
+ unsigned _function:1; /* is a (pointer to a) function */
+
+ int rIdx; /* If this immd points to a register */
+ struct regs *r; /* then this is the reg. */
+
} pCodeOpImmd;
typedef struct pCodeOpLabel
{
pCodeOp pcop;
int key;
+ int offset; /* low or high byte of label */
} pCodeOpLabel;
typedef struct pCodeOpReg
} pCodeOpRegBit;
+typedef struct pCodeOpRegPtr
+{
+ pCodeOpReg pcor; // The Register containing this bit
+
+ // PIC_OPTYPE subtype; // The type of this register.
+ // unsigned int inBitSpace: 1; /* True if in bit space, else
+
+} pCodeOpRegPtr;
+
+typedef struct pCodeOpWild
+{
+ pCodeOp pcop;
+
+ struct pCodeWildBlock *pcwb;
+
+ int id; /* index into an array of char *'s that will match
+ * 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;
+
+
/*************************************************
pCode
} pCodeComment;
+/*************************************************
+ pCodeComment
+**************************************************/
+
+typedef struct pCodeCSource
+{
+
+ pCode pc;
+
+ int line_number;
+ char *line;
+ char *file_name;
+
+} pCodeCSource;
+
+
/*************************************************
pCodeFlow
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
pCode *end; /* Last pCode in this flow. Note that
the first pCode is pc.next */
- set **uses; /* map the pCode instruction inCond and outCond conditions
+ /* set **uses; * map the pCode instruction inCond and outCond conditions
* in this array of set's. The reason we allocate an
* array of pointers instead of declaring each type of
* usage is because there are port dependent usage definitions */
- int nuses; /* number of uses sets */
+ //int nuses; /* number of uses sets */
set *from; /* flow blocks that can send control to this flow block */
set *to; /* flow blocks to which this one can send control */
+ struct pCodeFlow *ancestor; /* The most immediate "single" pCodeFlow object that
+ * executes prior to this one. In many cases, this
+ * will be just the previous */
int inCond; /* Input conditions - stuff assumed defined at entry */
int outCond; /* Output conditions - stuff modified by flow block */
+ int firstBank; /* The first and last bank flags are the first and last */
+ int lastBank; /* register banks used within one flow object */
+
+ int FromConflicts;
+ int ToConflicts;
+
+ set *registers;/* Registers used in this flow */
+
} pCodeFlow;
+/*************************************************
+ pCodeFlowLink
+
+ The Flow Link object is used to record information
+ about how consecutive excutive Flow objects are related.
+ The pCodeFlow objects demarcate the pCodeInstructions
+ into contiguous chunks. The FlowLink records conflicts
+ in the discontinuities. For example, if one Flow object
+ references a register in bank 0 and the next Flow object
+ references a register in bank 1, then there is a discontinuity
+ in the banking registers.
+
+*/
+typedef struct pCodeFlowLink
+{
+ pCodeFlow *pcflow; /* pointer to linked pCodeFlow object */
+
+ int bank_conflict; /* records bank conflicts */
+
+} pCodeFlowLink;
+
/*************************************************
pCodeInstruction
pBranch *to; // pCodes that execute after
pBranch *label; // pCode instructions that have labels
- pCodeOp *pcop; /* Operand, if this instruction has one */
-
- pCodeFlow *pcflow; /* flow block to which this instruction belongs */
+ pCodeOp *pcop; /* Operand, if this instruction has one */
+ pCodeFlow *pcflow; /* flow block to which this instruction belongs */
+ pCodeCSource *cline; /* C Source from which this instruction was derived */
unsigned int num_ops; /* Number of operands (0,1,2 for mid range pics) */
unsigned int isModReg: 1; /* If destination is W or F, then 1==F */
unsigned int isBitInst: 1; /* e.g. BCF */
unsigned int isBranch: 1; /* True if this is a branching instruction */
unsigned int isSkip: 1; /* True if this is a skip instruction */
+ unsigned int isLit: 1; /* True if this instruction has an literal operand */
+ PIC_OPCODE inverted_op; /* Opcode of instruction that's the opposite of this one */
unsigned int inCond; // Input conditions for this instruction
unsigned int outCond; // Output conditions for this instruction
pBranch *to; // pCodes that execute after
pBranch *label; // pCode instructions that have labels
+ int ncalled; /* Number of times function is called */
+
} pCodeFunction;
* - this wild card will get expanded into that pCode
* that is stored at this index */
+ /* Conditions on wild pcode instruction */
+ int mustBeBitSkipInst:1;
+ int mustNotBeBitSkipInst:1;
+ int invertBitSkipInst:1;
pCodeOp *operand; // Optional operand
pCodeOp *label; // Optional label
set *function_calls;
set *tregisters;
+ set *FlowTree;
unsigned visited:1; /* set true if traversed in call tree */
unsigned seq; /* sequence number of this pBlock */
+/*************************************************
+ pCodeWildBlock
+
+ The pCodeWildBlock object keeps track of the wild
+ variables, operands, and opcodes that exist in
+ a pBlock.
+**************************************************/
+typedef struct pCodeWildBlock {
+ pBlock *pb;
+ struct pCodePeep *pcp; // pointer back to ... I don't like this...
+
+ int nvars; // Number of wildcard registers in target.
+ char **vars; // array of pointers to them
+
+ int nops; // Number of wildcard operands in target.
+ pCodeOp **wildpCodeOps; // array of pointers to the pCodeOp's.
+
+ int nwildpCodes; // Number of wildcard pCodes in target/replace
+ pCode **wildpCodes; // array of pointers to the pCode's.
+
+} pCodeWildBlock;
+
/*************************************************
pCodePeep
pCode chain.
**************************************************/
typedef struct pCodePeep {
+ pCodeWildBlock target; // code we'd like to optimize
+ pCodeWildBlock replace; // and this is what we'll optimize it with.
- pBlock *target; // code we'd like to optimize
- pBlock *replace; // and this is what we'll optimize it with.
+ //pBlock *target;
+ //pBlock replace; // and this is what we'll optimize it with.
- int nvars; // Number of wildcard registers in target.
- char **vars; // array of pointers to them
- int nops; // Number of wildcard operands in target.
- pCodeOp **wildpCodeOps; // array of pointers to the pCodeOp's.
-
- int nwildpCodes; // Number of wildcard pCodes in target/replace
- pCode **wildpCodes; // array of pointers to the pCode's.
/* (Note: a wildcard register is a place holder. Any register
} pCodePeep;
-typedef struct pCodeOpWild
-{
- pCodeOp pcop;
- //PIC_OPTYPE subtype; Wild get's expanded to this by the optimizer
- pCodePeep *pcp; // pointer to the parent peep block
- int id; /* index into an array of char *'s that will match
- * 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;
+ pCode peep command definitions
+
+ Here are some special commands that control the
+way the peep hole optimizer behaves
+
+**************************************************/
+
+enum peepCommandTypes{
+ NOTBITSKIP = 0,
+ BITSKIP,
+ INVERTBITSKIP,
+ _LAST_PEEP_COMMAND_
+};
+
+/*************************************************
+ peepCommand structure stores the peep commands.
+
+**************************************************/
+
+typedef struct peepCommand {
+ int id;
+ char *cmd;
+} peepCommand;
/*************************************************
pCode Macros
#define PCI(x) ((pCodeInstruction *)(x))
#define PCL(x) ((pCodeLabel *)(x))
#define PCF(x) ((pCodeFunction *)(x))
-#define PCFL(x) ((pCodeFlow *)(x))
+#define PCFL(x) ((pCodeFlow *)(x))
+#define PCFLINK(x)((pCodeFlowLink *)(x))
#define PCW(x) ((pCodeWild *)(x))
+#define PCCS(x) ((pCodeCSource *)(x))
#define PCOP(x) ((pCodeOp *)(x))
//#define PCOB(x) ((pCodeOpBit *)(x))
#define PBR(x) ((pBranch *)(x))
+#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_LIT(x) ((PCODE(x)->type == PC_OPCODE) && PCI(x)->isLit)
+#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.
*-----------------------------------------------------------------*/
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 *newpCodeInlineP(char *cP); // Create a new pCode given a char *
pCode *newpCodeFunction(char *g, char *f); // Create a new function
pCode *newpCodeLabel(char *name,int key); // Create a new label given a key
+pCode *newpCodeCSource(int ln, char *f, char *l); // Create a new symbol line
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 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);
+int OptimizepCode(char dbName);
void printCallTree(FILE *of);
void pCodePeepInit(void);
void pBlockConvert2ISR(pBlock *pb);
pCodeOp *newpCodeOpLabel(char *name, int key);
-pCodeOp *newpCodeOpImmd(char *name, int offset);
+pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space,int is_func);
pCodeOp *newpCodeOpLit(int lit);
pCodeOp *newpCodeOpBit(char *name, int bit,int inBitSpace);
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);
/*-----------------------------------------------------------------*
extern pCodeOpReg pc_pcl;
extern pCodeOpReg pc_pclath;
extern pCodeOpReg pc_kzero;
-extern pCodeOpReg pc_wsave; /* wsave and ssave are used to save W and the Status */
+extern pCodeOpReg pc_wsave; /* wsave, ssave and psave are used to save W, the Status and PCLATH*/
extern pCodeOpReg pc_ssave; /* registers during an interrupt */
+extern pCodeOpReg pc_psave; /* registers during an interrupt */
#endif // __PCODE_H__