X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic%2Fpcode.h;h=86c245081b4f4b41219eb0ce67273108d52fd1bf;hb=7acf410d97f954d4aa6f2a728e2faa39b555ba13;hp=1d5961ebc5c219abcc9cdb9233e8c223e3478e9a;hpb=d29d3bd3d0ba71cced0f534b9c08c41d042a5a38;p=fw%2Fsdcc diff --git a/src/pic/pcode.h b/src/pic/pcode.h index 1d5961eb..86c24508 100644 --- a/src/pic/pcode.h +++ b/src/pic/pcode.h @@ -65,12 +65,47 @@ struct regs; #ifndef __PCODE_H__ #define __PCODE_H__ +/*********************************************************************** + * debug stuff + * + * The DFPRINTF macro will call fprintf if PCODE_DEBUG is defined. + * The macro is used like: + * + * DPRINTF(("%s #%d\n","test", 1)); + * + * The double parenthesis (()) are necessary + * + ***********************************************************************/ +//#define PCODE_DEBUG + +#ifdef PCODE_DEBUG +#define DFPRINTF(args) (fprintf args) +#else +#define DFPRINTF(args) ; +#endif + + /*********************************************************************** * PIC status bits - this will move into device dependent headers ***********************************************************************/ #define PIC_C_BIT 0 #define PIC_DC_BIT 1 #define PIC_Z_BIT 2 +#define PIC_RP0_BIT 5 /* Register Bank select bits RP1:0 : */ +#define PIC_RP1_BIT 6 /* 00 - bank 0, 01 - bank 1, 10 - bank 2, 11 - bank 3 */ +#define PIC_IRP_BIT 7 /* Indirect register page select */ + +/*********************************************************************** + * PIC INTCON bits - this will move into device dependent headers + ***********************************************************************/ +#define PIC_RBIF_BIT 0 /* Port B level has changed flag */ +#define PIC_INTF_BIT 1 /* Port B bit 0 interrupt on edge flag */ +#define PIC_T0IF_BIT 2 /* TMR0 has overflowed flag */ +#define PIC_RBIE_BIT 3 /* Port B level has changed - Interrupt Enable */ +#define PIC_INTE_BIT 4 /* Port B bit 0 interrupt on edge - Int Enable */ +#define PIC_T0IE_BIT 5 /* TMR0 overflow Interrupt Enable */ +#define PIC_PIE_BIT 6 /* Peripheral Interrupt Enable */ +#define PIC_GIE_BIT 7 /* Global Interrupt Enable */ /*********************************************************************** * Operand types @@ -104,6 +139,7 @@ typedef enum PO_STATUS, // The 'STATUS' register PO_FSR, // The "file select register" (in 18c it's one of three) PO_INDF, // The Indirect register + PO_INTCON, // Interrupt Control register 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 @@ -121,37 +157,6 @@ typedef enum } PIC_OPTYPE; -/************************************************* - * pCode conditions: - * - * The "conditions" are bit-mapped flags that describe - * input and/or output conditions that are affected by - * the instructions. For example: - * - * MOVF SOME_REG,W - * - * This instruction depends upon 'SOME_REG'. Consequently - * it has the input condition PCC_REGISTER set to true. - * - * In addition, this instruction affects the Z bit in the - * status register and affects W. Thus the output conditions - * are the logical or: - * PCC_ZERO_BIT | PCC_W - * - * The conditions are intialized when the pCode for an - * instruction is created. They're subsequently used - * by the pCode optimizer determine state information - * in the program flow. - *************************************************/ - -#define PCC_NONE 0 -#define PCC_REGISTER (1<<0) -#define PCC_C (1<<1) -#define PCC_Z (1<<2) -#define PCC_DC (1<<3) -#define PCC_W (1<<4) -#define PCC_EXAMINE_PCOP (1<<5) - /*********************************************************************** * * PIC_OPCODE @@ -180,6 +185,7 @@ typedef enum POC_COMFW, POC_CLRF, POC_CLRW, + POC_CLRWDT, POC_DECF, POC_DECFW, POC_DECFSZ, @@ -196,9 +202,10 @@ typedef enum POC_MOVFW, POC_MOVLW, POC_MOVWF, - POC_NEGF, + POC_NOP, POC_RETLW, POC_RETURN, + POC_RETFIE, POC_RLF, POC_RLFW, POC_RRF, @@ -221,17 +228,26 @@ typedef enum typedef enum { - PC_COMMENT=0, // pCode is a comment - PC_OPCODE, // PORT dependent opcode - PC_LABEL, // assembly label - PC_FUNCTION, // Function start or end - PC_WILD // wildcard - an opcode place holder + 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 + * 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 @@ -277,7 +293,7 @@ typedef struct pCodeOp char *name; } pCodeOp; - +#if 0 typedef struct pCodeOpBit { pCodeOp pcop; @@ -285,13 +301,25 @@ typedef struct pCodeOpBit unsigned int inBitSpace: 1; /* True if in bit space, else just a bit of a register */ } pCodeOpBit; - +#endif typedef struct pCodeOpLit { pCodeOp pcop; int lit; } pCodeOpLit; +typedef struct pCodeOpImmd +{ + pCodeOp pcop; + int offset; /* low,med, or high byte of immediat value */ + int index; /* add this to the immediate value */ + unsigned _const:1; /* is in code space */ + + int rIdx; /* If this immd points to a register */ + struct regs *r; /* then this is the reg. */ + +} pCodeOpImmd; + typedef struct pCodeOpLabel { pCodeOp pcop; @@ -303,6 +331,7 @@ typedef struct pCodeOpReg pCodeOp pcop; // Can be either GPR or SFR int rIdx; // Index into the register table struct regs *r; + int instance; // byte # of Multi-byte registers struct pBlock *pb; } pCodeOpReg; @@ -311,9 +340,27 @@ typedef struct pCodeOpRegBit pCodeOpReg pcor; // The Register containing this bit int bit; // 0-7 bit number. PIC_OPTYPE subtype; // The type of this register. + unsigned int inBitSpace: 1; /* True if in bit space, else + just a bit of a register */ } pCodeOpRegBit; +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 @@ -332,10 +379,6 @@ typedef struct pCode int seq; // sequence number - pBranch *from; // pCodes that execute before this one - pBranch *to; // pCodes that execute after - pBranch *label; // pCode instructions that have labels - struct pBlock *pb; // The pBlock that contains this pCode. /* "virtual functions" @@ -343,7 +386,7 @@ typedef struct pCode * in C++. The subsequent structures that "inherit" * the pCode structure will initialize these function * pointers to something useful */ - void (*analyze) (struct pCode *_this); + // void (*analyze) (struct pCode *_this); void (*destruct)(struct pCode *_this); void (*print) (FILE *of,struct pCode *_this); @@ -363,6 +406,88 @@ typedef struct pCodeComment } pCodeComment; +/************************************************* + pCodeComment +**************************************************/ + +typedef struct pCodeCSource +{ + + pCode pc; + + int line_number; + char *line; + char *file_name; + +} pCodeCSource; + + +/************************************************* + pCodeFlow + + The Flow object is used as marker to separate + the assembly code into contiguous chunks. In other + words, everytime an instruction cause or potentially + 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 pc; + + 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 + * 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 */ + + 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 @@ -380,12 +505,22 @@ typedef struct pCodeInstruction char const * const mnemonic; // Pointer to mnemonic string - pCodeOp *pcop; // Operand + pBranch *from; // pCodes that execute before this one + 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 */ + pCodeCSource *cline; /* C Source from which this instruction was derived */ - unsigned int num_ops; - unsigned int dest: 1; // If destination is W or F, then 1==F - unsigned int bit_inst: 1; + 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 @@ -421,6 +556,12 @@ typedef struct pCodeFunction start and the name is contained here */ + pBranch *from; // pCodes that execute before this one + pBranch *to; // pCodes that execute after + pBranch *label; // pCode instructions that have labels + + int ncalled; /* Number of times function is called */ + } pCodeFunction; @@ -431,12 +572,16 @@ typedef struct pCodeFunction typedef struct pCodeWild { - pCode pc; + pCodeInstruction pci; int id; /* Index into the wild card array of a peepBlock * - 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 @@ -467,8 +612,9 @@ typedef struct pBlock set *function_entries; /* dll of functions in this pblock */ set *function_exits; set *function_calls; - set *registers; + set *tregisters; + set *FlowTree; unsigned visited:1; /* set true if traversed in call tree */ unsigned seq; /* sequence number of this pBlock */ @@ -497,6 +643,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 @@ -509,17 +677,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. - - 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. + //pBlock *target; + //pBlock replace; // and this is what we'll optimize it with. - 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 @@ -537,19 +700,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 @@ -559,11 +734,15 @@ typedef struct pCodeOpWild #define PCI(x) ((pCodeInstruction *)(x)) #define PCL(x) ((pCodeLabel *)(x)) #define PCF(x) ((pCodeFunction *)(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 PCOB(x) ((pCodeOpBit *)(x)) #define PCOL(x) ((pCodeOpLit *)(x)) +#define PCOI(x) ((pCodeOpImmd *)(x)) #define PCOLAB(x) ((pCodeOpLabel *)(x)) #define PCOR(x) ((pCodeOpReg *)(x)) #define PCORB(x) ((pCodeOpRegBit *)(x)) @@ -571,15 +750,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(int key); // Create a new label given a key -pCode *newpCodeLabelStr(char *str); // Create a new label given a string +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 @@ -588,14 +790,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(int key); +pCodeOp *newpCodeOpLabel(char *name, int key); +pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space); 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); /*-----------------------------------------------------------------* @@ -603,30 +815,14 @@ extern void pcode_test(void); *-----------------------------------------------------------------*/ extern pCodeOpReg pc_status; +extern pCodeOpReg pc_intcon; extern pCodeOpReg pc_indf; 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_ssave; /* registers during an interrupt */ -//////////////////// DELETE THIS /////////////////// -/*-----------------------------------------------------------------*/ -/* Allocation macros that replace those in SDCCalloc.h */ -/* Why? I dunno. I ran across a bug with those macros that */ -/* I couldn't fix, but I could work around... */ -/*-----------------------------------------------------------------*/ -# define GC_malloc(x) calloc((x), 1) - -#define _ALLOC(x,sz) if (!(x = calloc((sz),1) )) \ - { \ - werror(E_OUT_OF_MEM,__FILE__,(long) sz);\ - exit (1); \ - } - -#define _ALLOC_ATOMIC(x,y) if (!((x) = malloc(y))) \ - { \ - werror(E_OUT_OF_MEM,__FILE__,(long) y); \ - exit (1); \ - } - #endif // __PCODE_H__