diff options
| author | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
|---|---|---|
| committer | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
| commit | 268a53de823a6750d6256ee1fb1e7707b4b45740 (patch) | |
| tree | 42c1799a9a82b2f7d9790ee9fe181d72a7274751 /src/pic16/pcode.h | |
| download | sdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz | |
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'src/pic16/pcode.h')
| -rw-r--r-- | src/pic16/pcode.h | 1141 |
1 files changed, 1141 insertions, 0 deletions
diff --git a/src/pic16/pcode.h b/src/pic16/pcode.h new file mode 100644 index 0000000..e29bef6 --- /dev/null +++ b/src/pic16/pcode.h @@ -0,0 +1,1141 @@ +/*------------------------------------------------------------------------- + + pcode.h - post code generation + Written By - Scott Dattalo scott@dattalo.com + Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.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. + +-------------------------------------------------------------------------*/ + +//#include "ralloc.h" +struct reg_info; + +/* + Post code generation + + The post code generation is an assembler optimizer. The assembly code + produced by all of the previous steps is fully functional. This step + will attempt to analyze the flow of the assembly code and agressively + optimize it. The peep hole optimizer attempts to do the same thing. + As you may recall, the peep hole optimizer replaces blocks of assembly + with more optimal blocks (e.g. removing redundant register loads). + However, the peep hole optimizer has to be somewhat conservative since + an assembly program has implicit state information that's unavailable + when only a few instructions are examined. + Consider this example: + + example1: + movwf t1 + movf t1,w + + The movf seems redundant since we know that the W register already + contains the same value of t1. So a peep hole optimizer is tempted to + remove the "movf". However, this is dangerous since the movf affects + the flags in the status register (specifically the Z flag) and subsequent + code may depend upon this. Look at these two examples: + + example2: + movwf t1 + movf t1,w ; Can't remove this movf + skpz + return + + example3: + movwf t1 + movf t1,w ; This movf can be removed + xorwf t2,w ; since xorwf will over write Z + skpz + return + +*/ + + +#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 + + +#ifdef WORDS_BIGENDIAN + #define _ENDIAN(x) (3-x) +#else + #define _ENDIAN(x) (x) +#endif + + +#define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff) + + +/*********************************************************************** + * Extended Instruction Set/Indexed Literal Offset Mode * + * Set this macro to enable code generation with the extended * + * instruction set and the new Indexed Literal Offset Mode * + ***********************************************************************/ +#define XINST 1 + +/*********************************************************************** + * 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_OV_BIT 3 +#define PIC_N_BIT 4 +#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 */ + +/*********************************************************************** + * PIC bank definitions + ***********************************************************************/ +#define PIC_BANK_FIRST 0 +#define PIC_BANK_LAST 0xf + + +/*********************************************************************** + * Operand types + ***********************************************************************/ +#define POT_RESULT 0 +#define POT_LEFT 1 +#define POT_RIGHT 2 + + +/*********************************************************************** + * + * PIC_OPTYPE - Operand types that are specific to the PIC architecture + * + * If a PIC assembly instruction has an operand then here is where we + * associate a type to it. For example, + * + * movf reg,W + * + * The movf has two operands: 'reg' and the W register. 'reg' is some + * arbitrary general purpose register, hence it has the type PO_GPR_REGISTER. + * The W register, which is the PIC's accumulator, has the type PO_W. + * + ***********************************************************************/ + + + +typedef enum +{ + PO_NONE=0, // No operand e.g. NOP + PO_W, // The working register (as a destination) + PO_WREG, // The working register (as a file register) + PO_STATUS, // The 'STATUS' register + PO_BSR, // The 'BSR' register + PO_FSR0, // The "file select register" (in PIC18 family it's one + // of three) + PO_INDF0, // 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 + PO_SFR_REGISTER, // A special function register (e.g. PORTA) + PO_PCL, // Program counter Low register + PO_PCLATH, // Program counter Latch high register + PO_PCLATU, // Program counter Latch upper register + PO_PRODL, // Product Register Low + PO_PRODH, // Product Register High + PO_LITERAL, // A constant + PO_REL_ADDR, // A relative address + PO_IMMEDIATE, // (8051 legacy) + PO_DIR, // Direct memory (8051 legacy) + PO_CRY, // bit memory (8051 legacy) + PO_BIT, // bit operand. + PO_STR, // (8051 legacy) + PO_LABEL, + PO_WILD, // Wild card operand in peep optimizer + PO_TWO_OPS // combine two operands +} PIC_OPTYPE; + + +/*********************************************************************** + * + * PIC_OPCODE + * + * This is not a list of the PIC's opcodes per se, but instead + * an enumeration of all of the different types of pic opcodes. + * + ***********************************************************************/ + +typedef enum +{ + POC_WILD=-1, /* Wild card - used in the pCode peep hole optimizer + * to represent ANY pic opcode */ + POC_ADDLW=0, + POC_ADDWF, + POC_ADDFW, + POC_ADDFWC, + POC_ADDWFC, + POC_ANDLW, + POC_ANDWF, + POC_ANDFW, + POC_BC, + POC_BCF, + POC_BN, + POC_BNC, + POC_BNN, + POC_BNOV, + POC_BNZ, + POC_BOV, + POC_BRA, + POC_BSF, + POC_BTFSC, + POC_BTFSS, + POC_BTG, + POC_BZ, + POC_CALL, + POC_CLRF, + POC_CLRWDT, + POC_COMF, + POC_COMFW, + POC_CPFSEQ, + POC_CPFSGT, + POC_CPFSLT, + POC_DAW, + POC_DCFSNZ, + POC_DCFSNZW, + POC_DECF, + POC_DECFW, + POC_DECFSZ, + POC_DECFSZW, + POC_GOTO, + POC_INCF, + POC_INCFW, + POC_INCFSZ, + POC_INCFSZW, + POC_INFSNZ, + POC_INFSNZW, + POC_IORWF, + POC_IORFW, + POC_IORLW, + POC_LFSR, + POC_MOVF, + POC_MOVFW, + POC_MOVFF, + POC_MOVLB, + POC_MOVLW, + POC_MOVWF, + POC_MULLW, + POC_MULWF, + POC_NEGF, + POC_NOP, + POC_POP, + POC_PUSH, + POC_RCALL, + POC_RETFIE, + POC_RETLW, + POC_RETURN, + POC_RLCF, + POC_RLCFW, + POC_RLNCF, + POC_RLNCFW, + POC_RRCF, + POC_RRCFW, + POC_RRNCF, + POC_RRNCFW, + POC_SETF, + POC_SUBLW, + POC_SUBFWB, + POC_SUBWF, + POC_SUBFW, + POC_SUBWFB_D0, + POC_SUBWFB_D1, + POC_SUBFWB_D0, + POC_SUBFWB_D1, + POC_SWAPF, + POC_SWAPFW, + POC_TBLRD, + POC_TBLRD_POSTINC, + POC_TBLRD_POSTDEC, + POC_TBLRD_PREINC, + POC_TBLWT, + POC_TBLWT_POSTINC, + POC_TBLWT_POSTDEC, + POC_TBLWT_PREINC, + POC_TSTFSZ, + POC_XORLW, + POC_XORWF, + POC_XORFW, + + POC_BANKSEL + + /* pseudo-instructions */ +} PIC_OPCODE; + + +/*********************************************************************** + * PC_TYPE - pCode Types + ***********************************************************************/ + +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 + * in the pCode peep hole optimizer */ + PC_CSOURCE, /* C-Source Line */ + PC_ASMDIR, /* Assembler directive */ + PC_BAD, /* Mark the pCode object as being bad */ + PC_INFO /* pCode information node, used primarily in optimizing */ +} PC_TYPE; + + +/*********************************************************************** + * INFO_TYPE - information node types + ***********************************************************************/ + +typedef enum +{ + INF_OPTIMIZATION, /* structure contains optimization information */ + INF_LOCALREGS /* structure contains local register information */ +} INFO_TYPE; + + + +/*********************************************************************** + * OPT_TYPE - optimization node types + ***********************************************************************/ + +typedef enum +{ + OPT_BEGIN, /* mark beginning of optimization block */ + OPT_END, /* mark ending of optimization block */ + OPT_JUMPTABLE_BEGIN, /* mark beginning of a jumptable */ + OPT_JUMPTABLE_END /* mark end of jumptable */ +} OPT_TYPE; + +/*********************************************************************** + * LR_TYPE - optimization node types + ***********************************************************************/ + +typedef enum +{ + LR_ENTRY_BEGIN, /* mark beginning of optimization block */ + LR_ENTRY_END, /* mark ending of optimization block */ + LR_EXIT_BEGIN, + LR_EXIT_END +} LR_TYPE; + + +/************************************************/ +/*************** Structures ********************/ +/************************************************/ +/* These are here as forward references - the + * full definition of these are below */ +struct pCode; +struct pCodeWildBlock; +struct pCodeRegLives; + +/************************************************* + pBranch + + The first step in optimizing pCode is determining + the program flow. This information is stored in + single-linked lists in the for of 'from' and 'to' + objects with in a pcode. For example, most instructions + don't involve any branching. So their from branch + points to the pCode immediately preceding them and + their 'to' branch points to the pcode immediately + following them. A skip instruction is an example of + a pcode that has multiple (in this case two) elements + in the 'to' branch. A 'label' pcode is an where there + may be multiple 'from' branches. + *************************************************/ + +typedef struct pBranch +{ + struct pCode *pc; // Next pCode in a branch + struct pBranch *next; /* If more than one branch + * the next one is here */ + +} pBranch; + +/************************************************* + pCodeOp + + pCode Operand structure. + For those assembly instructions that have arguments, + the pCode will have a pCodeOp in which the argument + can be stored. For example + + movf some_register,w + + 'some_register' will be stored/referenced in a pCodeOp + + *************************************************/ + +typedef struct pCodeOp +{ + PIC_OPTYPE type; + char *name; + +} pCodeOp; + +#if 0 +typedef struct pCodeOpBit +{ + pCodeOp pcop; + int bit; + 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; + pCodeOp *arg2; /* needed as pCodeOpLit and pCodeOpLit2 are not separable via their type (PO_LITERAL) */ +} pCodeOpLit; + +typedef struct pCodeOpLit2 +{ + pCodeOp pcop; + int lit; + pCodeOp *arg2; +} pCodeOpLit2; + + +typedef struct pCodeOpImmd +{ + pCodeOp pcop; + int offset; /* low,high or upper byte of immediate 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 reg_info *r; /* then this is the reg. */ + +} pCodeOpImmd; + +typedef struct pCodeOpLabel +{ + pCodeOp pcop; + int key; +} pCodeOpLabel; + +typedef struct pCodeOpReg +{ + pCodeOp pcop; // Can be either GPR or SFR + int rIdx; // Index into the register table + struct reg_info *r; + int instance; // byte # of Multi-byte registers + struct pBlock *pb; +} pCodeOpReg; + +typedef struct pCodeOp2 +{ + pCodeOp pcop; // describes this pCodeOp + pCodeOp *pcopL; // reference to left pCodeOp (src) + pCodeOp *pcopR; // reference to right pCodeOp (dest) +} pCodeOp2; + +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 */ + + pCodeOp *pcop2; /* second operand if exists */ + +} pCodeOpWild; + + +typedef struct pCodeOpOpt +{ + pCodeOp pcop; + + OPT_TYPE type; /* optimization node type */ + + char *key; /* key by which a block is identified */ +} pCodeOpOpt; + +typedef struct pCodeOpLocalReg +{ + pCodeOp pcop; + + LR_TYPE type; +} pCodeOpLocalReg; + +/************************************************* + pCode + + Here is the basic build block of a PIC instruction. + Each pic instruction will get allocated a pCode. + A linked list of pCodes makes a program. + +**************************************************/ + +typedef struct pCode +{ + PC_TYPE type; + + struct pCode *prev; // The pCode objects are linked together + struct pCode *next; // in doubly linked lists. + + int seq; // sequence number + + struct pBlock *pb; // The pBlock that contains this pCode. + + /* "virtual functions" + * The pCode structure is like a base class + * in C++. The subsequent structures that "inherit" + * the pCode structure will initialize these function + * pointers to something useful */ + // void (*analyze) (struct pCode *_this); + void (*destruct)(struct pCode *_this); + void (*print) (FILE *of,struct pCode *_this); + +} pCode; + + +/************************************************* + pCodeComment +**************************************************/ + +typedef struct pCodeComment +{ + pCode pc; + + char *comment; + +} pCodeComment; + + +/************************************************* + pCodeCSource +**************************************************/ + +typedef struct pCodeCSource +{ + pCode pc; + + int line_number; + char *line; + char *file_name; + +} pCodeCSource; + + +/************************************************* + pCodeAsmDir +**************************************************/ + +/************************************************* + 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. + +**************************************************/ +struct defmap_s; // defined in pcode.c + +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 */ + + struct defmap_s *defmap; /* chronologically ordered list of definitions performed + in this flow (most recent at the front) */ + struct defmap_s *in_vals; /* definitions of all symbols reaching this flow + * symbols with multiple different definitions are stored + * with an assigned value of 0. */ + struct defmap_s *out_vals; /* definitions valid AFTER thie 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 + + Here we describe all the facets of a PIC instruction + (expansion for the 18cxxx is also provided). + +**************************************************/ + +typedef struct pCodeInstruction +{ + pCode pc; + + PIC_OPCODE op; // The opcode of the instruction. + + char const * const mnemonic; // Pointer to mnemonic string + + char isize; // pCode instruction size + + 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; /* 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 */ + unsigned int isAccess: 1; /* True if this instruction has an access RAM operand */ + unsigned int isFastCall: 1; /* True if this instruction has a fast call/return mode select operand */ + unsigned int is2MemOp: 1; /* True is second operand is a memory operand VR - support for MOVFF */ + unsigned int is2LitOp: 1; /* True if instruction takes 2 literal operands VR - support for LFSR */ + + 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 + +#define PCI_MAGIC 0x6e12 + unsigned int pci_magic; // sanity check for pci initialization +} pCodeInstruction; + + + +/************************************************* + pCodeAsmDir +**************************************************/ + +typedef struct pCodeAsmDir +{ + pCodeInstruction pci; + + char *directive; + char *arg; +} pCodeAsmDir; + + +/************************************************* + pCodeLabel +**************************************************/ + +typedef struct pCodeLabel +{ + pCode pc; + + char *label; + int key; + int force; /* label cannot be optimized out */ + +} pCodeLabel; + +/************************************************* + pCodeFunction +**************************************************/ + +typedef struct pCodeFunction +{ + pCode pc; + + char *modname; + char *fname; /* If NULL, then this is the end of + a function. Otherwise, it's the + 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 */ + + int absblock; /* hack to emulate a block pCodes in absolute position + but not inside a function */ + int stackusage; /* stack positions used in function */ + +} pCodeFunction; + + +/************************************************* + pCodeWild +**************************************************/ + +typedef struct pCodeWild +{ + 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 + +} pCodeWild; + + +/************************************************* + pInfo + + Here are stored generic informaton +*************************************************/ +typedef struct pCodeInfo +{ + pCodeInstruction pci; + + INFO_TYPE type; /* info node type */ + + pCodeOp *oper1; /* info node arguments */ +} pCodeInfo; + + +/************************************************* + pBlock + + Here are PIC program snippets. There's a strong + correlation between the eBBlocks and pBlocks. + SDCC subdivides a C program into managable chunks. + Each chunk becomes a eBBlock and ultimately in the + PIC port a pBlock. + +**************************************************/ + +typedef struct pBlock +{ + memmap *cmemmap; /* The snippet is from this memmap */ + char dbName; /* if cmemmap is NULL, then dbName will identify the block */ + pCode *pcHead; /* A pointer to the first pCode in a link list of pCodes */ + pCode *pcTail; /* A pointer to the last pCode in a link list of pCodes */ + + struct pBlock *next; /* The pBlocks will form a doubly linked list */ + struct pBlock *prev; + + set *function_entries; /* dll of functions in this pblock */ + set *function_exits; + set *function_calls; + set *tregisters; + + set *FlowTree; + unsigned visited:1; /* set true if traversed in call tree */ + + unsigned seq; /* sequence number of this pBlock */ + +} pBlock; + +/************************************************* + pFile + + The collection of pBlock program snippets are + placed into a linked list that is implemented + in the pFile structure. + + The pcode optimizer will parse the pFile. + +**************************************************/ + +typedef struct pFile +{ + pBlock *pbHead; /* A pointer to the first pBlock */ + pBlock *pbTail; /* A pointer to the last pBlock */ + + pBranch *functions; /* A SLL of functions in this pFile */ + +} 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 + + The pCodePeep object mimics the peep hole optimizer + in the main SDCC src (e.g. SDCCpeeph.c). Essentially + there is a target pCode chain and a replacement + pCode chain. The target chain is compared to the + pCode that is generated by gen.c. If a match is + found then the pCode is replaced by the replacement + 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; + //pBlock replace; // and this is what we'll optimize it with. + + + + /* (Note: a wildcard register is a place holder. Any register + * can be replaced by the wildcard when the pcode is being + * compared to the target. */ + + /* Post Conditions. A post condition is a condition that + * must be either true or false before the peep rule is + * accepted. For example, a certain rule may be accepted + * if and only if the Z-bit is not used as an input to + * the subsequent instructions in a pCode chain. + */ + unsigned int postFalseCond; + unsigned int postTrueCond; + +} pCodePeep; + +/************************************************* + + 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 PCODE(x) ((pCode *)(x)) +#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 PCAD(x) ((pCodeAsmDir *)(x)) +#define PCINF(x) ((pCodeInfo *)(x)) + +#define PCOP(x) ((pCodeOp *)(x)) +#define PCOP2(x) ((pCodeOp2 *)(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 PCOR2(x) ((pCodeOpReg2 *)(x)) +#define PCORB(x) ((pCodeOpRegBit *)(x)) +#define PCOO(x) ((pCodeOpOpt *)(x)) +#define PCOLR(x) ((pCodeOpLocalReg *)(x)) +#define PCOW(x) ((pCodeOpWild *)(x)) +#define PCOW2(x) (PCOW(PCOW(x)->pcop2)) +#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 isPCAD(x) ((PCODE(x)->type == PC_ASMDIR)) +#define isPCINFO(x) ((PCODE(x)->type == PC_INFO)) + +#define isCALL(x) ((isPCI(x)) && (PCI(x)->op == POC_CALL)) +#define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS) +#define isBSR_REG(r) ((r)->pc_type == PO_BSR) +#define isACCESS_BANK(r) (r->accessBank) + + + +#define isPCOLAB(x) ((PCOP(x)->type) == PO_LABEL) + +/*-----------------------------------------------------------------* + * pCode functions. + *-----------------------------------------------------------------*/ + +pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop); // Create a new pCode given an operand +pCode *pic16_newpCodeCharP(const char *cP); // Create a new pCode given a char * +pCode *pic16_newpCodeInlineP(const char *cP); // Create a new pCode given a char * +pCode *pic16_newpCodeFunction(const char *g, const char *f); // Create a new function +pCode *pic16_newpCodeLabel(const char *name,int key); // Create a new label given a key +pCode *pic16_newpCodeLabelFORCE(const char *name, int key); // Same as newpCodeLabel but label cannot be optimized out +pCode *pic16_newpCodeCSource(int ln, const char *f, const char *l); // Create a new symbol line +pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc); // Create a new pBlock +void pic16_printpBlock(FILE *of, pBlock *pb); // Write a pBlock to a file +void pic16_addpCode2pBlock(pBlock *pb, pCode *pc); // Add a pCode to a pBlock +void pic16_addpBlock(pBlock *pb); // Add a pBlock to a pFile +void pic16_copypCode(FILE *of, char dbName); // Write all pBlocks with dbName to *of +void pic16_movepBlock2Head(char dbName); // move pBlocks around +void pic16_AnalyzepCode(char dbName); +void pic16_OptimizeLocalRegs(void); +void pic16_AssignRegBanks(void); +void pic16_printCallTree(FILE *of); +void pCodePeepInit(void); +void pic16_pBlockConvert2ISR(pBlock *pb); +void pic16_pBlockConvert2Absolute(pBlock *pb); +void pic16_initDB(void); +void pic16_emitDB(int c, char ptype, void *p); // Add DB directives to a pBlock +void pic16_emitDS(const char *s, char ptype, void *p); +void pic16_flushDB(char ptype, void *p); // Add pending DB data to a pBlock + +pCode *pic16_newpCodeAsmDir(const char *asdir, const char *argfmt, ...); + +pCodeOp *pic16_newpCodeOpLabel(const char *name, int key); +pCodeOp *pic16_newpCodeOpImmd(const char *name, int offset, int index, int code_space); +pCodeOp *pic16_newpCodeOpLit(int lit); +pCodeOp *pic16_newpCodeOpLit12(int lit); +pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2); +pCodeOp *pic16_newpCodeOpBit(const char *name, int bit,int inBitSpace, PIC_OPTYPE subt); +pCodeOp *pic16_newpCodeOpBit_simple (struct asmop *op, int offs, int bit); +pCodeOp *pic16_newpCodeOpRegFromStr(const char *name); +pCodeOp *pic16_newpCodeOpReg(int rIdx); +pCodeOp *pic16_newpCodeOp(const char *name, PIC_OPTYPE p); +pCodeOp *pic16_newpCodeOp2(pCodeOp *src, pCodeOp *dst); +pCodeOp *pic16_newpCodeOpRegNotVect(bitVect *bv); +pCodeOp *pic16_pCodeOpCopy(pCodeOp *pcop); + +pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop); +pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, const char *key); +pCodeOp *pic16_newpCodeOpLocalRegs(LR_TYPE type); +pCodeOp *pic16_newpCodeOpReg(int rIdx); + +pCode * pic16_findNextInstruction(pCode *pci); +pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct); +int pic16_isPCinFlow(const pCode *pc, const pCode *pcflow); +struct reg_info * pic16_getRegFromInstruction(pCode *pc); +struct reg_info * pic16_getRegFromInstruction2(pCode *pc); +char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size); +char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size); +const char *dumpPicOptype(PIC_OPTYPE type); + +extern void pic16_pcode_test(void); +extern int pic16_debug_verbose; +extern int pic16_pcode_verbose; + +extern const char *LR_TYPE_STR[]; + + +#ifndef debugf +//#define debugf(frm, rest...) _debugf(__FILE__, __LINE__, frm, rest) +#define debugf(frm, rest) _debugf(__FILE__, __LINE__, frm, rest) +#define debugf2(frm, arg1, arg2) _debugf(__FILE__, __LINE__, frm, arg1, arg2) +#define debugf3(frm, arg1, arg2, arg3) _debugf(__FILE__, __LINE__, frm, arg1, arg2, arg3) + +#endif + +extern void _debugf(char *f, int l, char *frm, ...); + + +/*-----------------------------------------------------------------* + * pCode objects. + *-----------------------------------------------------------------*/ + +extern pCodeOpReg pic16_pc_status; +extern pCodeOpReg pic16_pc_intcon; +extern pCodeOpReg pic16_pc_pcl; +extern pCodeOpReg pic16_pc_pclath; +extern pCodeOpReg pic16_pc_pclatu; +extern pCodeOpReg pic16_pc_wreg; +extern pCodeOpReg pic16_pc_tosl; +extern pCodeOpReg pic16_pc_tosh; +extern pCodeOpReg pic16_pc_tosu; +extern pCodeOpReg pic16_pc_tblptrl; +extern pCodeOpReg pic16_pc_tblptrh; +extern pCodeOpReg pic16_pc_tblptru; +extern pCodeOpReg pic16_pc_tablat; +extern pCodeOpReg pic16_pc_bsr; +extern pCodeOpReg pic16_pc_fsr0; +extern pCodeOpReg pic16_pc_fsr0l; +extern pCodeOpReg pic16_pc_fsr0h; +extern pCodeOpReg pic16_pc_fsr1l; +extern pCodeOpReg pic16_pc_fsr1h; +extern pCodeOpReg pic16_pc_fsr2l; +extern pCodeOpReg pic16_pc_fsr2h; +extern pCodeOpReg pic16_pc_indf0; +extern pCodeOpReg pic16_pc_postinc0; +extern pCodeOpReg pic16_pc_postdec0; +extern pCodeOpReg pic16_pc_preinc0; +extern pCodeOpReg pic16_pc_plusw0; +extern pCodeOpReg pic16_pc_indf1; +extern pCodeOpReg pic16_pc_postinc1; +extern pCodeOpReg pic16_pc_postdec1; +extern pCodeOpReg pic16_pc_preinc1; +extern pCodeOpReg pic16_pc_plusw1; +extern pCodeOpReg pic16_pc_indf2; +extern pCodeOpReg pic16_pc_postinc2; +extern pCodeOpReg pic16_pc_postdec2; +extern pCodeOpReg pic16_pc_preinc2; +extern pCodeOpReg pic16_pc_plusw2; +extern pCodeOpReg pic16_pc_prodl; +extern pCodeOpReg pic16_pc_prodh; + +extern pCodeOpReg pic16_pc_eecon1; +extern pCodeOpReg pic16_pc_eecon2; +extern pCodeOpReg pic16_pc_eedata; +extern pCodeOpReg pic16_pc_eeadr; + +extern pCodeOpReg pic16_pc_kzero; +extern pCodeOpReg pic16_pc_wsave; /* wsave and ssave are used to save W and the Status */ +extern pCodeOpReg pic16_pc_ssave; /* registers during an interrupt */ + +extern pCodeOpReg *pic16_stackpnt_lo; +extern pCodeOpReg *pic16_stackpnt_hi; +extern pCodeOpReg *pic16_stack_postinc; +extern pCodeOpReg *pic16_stack_postdec; +extern pCodeOpReg *pic16_stack_preinc; +extern pCodeOpReg *pic16_stack_plusw; + +extern pCodeOpReg *pic16_framepnt_lo; +extern pCodeOpReg *pic16_framepnt_hi; +extern pCodeOpReg *pic16_frame_postinc; +extern pCodeOpReg *pic16_frame_postdec; +extern pCodeOpReg *pic16_frame_preinc; +extern pCodeOpReg *pic16_frame_plusw; + +extern pCodeOpReg pic16_pc_gpsimio; +extern pCodeOpReg pic16_pc_gpsimio2; + +#endif // __PCODE_H__ |
