(genPlus): added special handling for 256 byte aligned xdata arrays. Erik helped...
[fw/sdcc] / src / pic / pcode.h
index c0a8bee399914a06996926f88bb28f1a164cdb73..1c3a024f7ee18b67f7a068c4dfe60b585ed9d5b9 100644 (file)
@@ -143,6 +143,7 @@ typedef enum
   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
@@ -185,6 +186,7 @@ typedef enum
   POC_COMFW,
   POC_CLRF,
   POC_CLRW,
+  POC_CLRWDT,
   POC_DECF,
   POC_DECFW,
   POC_DECFSZ,
@@ -228,18 +230,25 @@ typedef enum
 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
@@ -303,13 +312,21 @@ typedef struct pCodeOpLit
 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
@@ -331,6 +348,31 @@ typedef struct pCodeOpRegBit
 } 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
 
@@ -376,6 +418,22 @@ typedef struct pCodeComment
 
 } pCodeComment;
 
+/*************************************************
+    pCodeComment
+**************************************************/
+
+typedef struct pCodeCSource
+{
+
+  pCode  pc;
+
+  int  line_number;
+  char *line;
+  char *file_name;
+
+} pCodeCSource;
+
+
 /*************************************************
     pCodeFlow
 
@@ -385,6 +443,7 @@ typedef struct pCodeComment
  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
@@ -395,20 +454,52 @@ 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
 
@@ -430,16 +521,18 @@ typedef struct 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
 
@@ -479,6 +572,8 @@ typedef struct pCodeFunction
   pBranch *to;         // pCodes that execute after
   pBranch *label;      // pCode instructions that have labels
 
+  int  ncalled;    /* Number of times function is called */
+
 } pCodeFunction;
 
 
@@ -495,6 +590,10 @@ typedef struct pCodeWild
                  * - 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
@@ -527,6 +626,7 @@ typedef struct pBlock
   set *function_calls;
   set *tregisters;
 
+  set *FlowTree;
   unsigned visited:1;       /* set true if traversed in call tree */
 
   unsigned seq;             /* sequence number of this pBlock */
@@ -555,6 +655,28 @@ typedef struct pFile
 
 
 
+/*************************************************
+  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
 
@@ -567,17 +689,12 @@ typedef struct pFile
   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
@@ -595,19 +712,31 @@ typedef struct pCodePeep {
 
 } 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
@@ -617,8 +746,10 @@ typedef struct pCodeOpWild
 #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))
@@ -631,14 +762,38 @@ typedef struct pCodeOpWild
 
 #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
@@ -647,17 +802,24 @@ 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);
+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);
 
 /*-----------------------------------------------------------------*
@@ -671,8 +833,9 @@ extern pCodeOpReg pc_fsr;
 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__