1 /*-------------------------------------------------------------------------
3 pcode.h - post code generation
4 Written By - Scott Dattalo scott@dattalo.com
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 -------------------------------------------------------------------------*/
25 The post code generation is an assembler optimizer. The assembly code
26 produced by all of the previous steps is fully functional. This step
27 will attempt to analyze the flow of the assembly code and agressively
28 optimize it. The peep hole optimizer attempts to do the same thing.
29 As you may recall, the peep hole optimizer replaces blocks of assembly
30 with more optimal blocks (e.g. removing redundant register loads).
31 However, the peep hole optimizer has to be somewhat conservative since
32 an assembly program has implicit state information that's unavailable
33 when only a few instructions are examined.
34 Consider this example:
40 The movf seems redundant since we know that the W register already
41 contains the same value of t1. So a peep hole optimizer is tempted to
42 remove the "movf". However, this is dangerous since the movf affects
43 the flags in the status register (specifically the Z flag) and subsequent
44 code may depend upon this. Look at these two examples:
48 movf t1,w ; Can't remove this movf
54 movf t1,w ; This movf can be removed
55 xorwf t2,w ; since xorwf will over write Z
65 /***********************************************************************
66 * PIC status bits - this will move into device dependent headers
67 ***********************************************************************/
72 /***********************************************************************
74 ***********************************************************************/
80 /***********************************************************************
82 * PIC_OPTYPE - Operand types that are specific to the PIC architecture
84 * If a PIC assembly instruction has an operand then here is where we
85 * associate a type to it. For example,
89 * The movf has two operands: 'reg' and the W register. 'reg' is some
90 * arbitrary general purpose register, hence it has the type PO_GPR_REGISTER.
91 * The W register, which is the PIC's accumulator, has the type PO_W.
93 ***********************************************************************/
99 PO_NONE=0, // No operand e.g. NOP
100 PO_W, // The 'W' register
101 PO_STATUS, // The 'STATUS' register
102 PO_FSR, // The "file select register" (in 18c it's one of three)
103 PO_INDF, // The Indirect register
104 PO_GPR_REGISTER, // A general purpose register
105 PO_SFR_REGISTER, // A special function register (e.g. PORTA)
106 PO_LITERAL, // A constant
107 PO_IMMEDIATE, // (8051 legacy)
108 PO_DIR, // Direct memory (8051 legacy)
109 PO_CRY, // bit memory (8051 legacy)
110 PO_BIT, // bit operand.
111 PO_STR, // (8051 legacy)
113 PO_WILD // Wild card operand in peep optimizer
117 /***********************************************************************
121 * This is not a list of the PIC's opcodes per se, but instead
122 * an enumeration of all of the different types of pic opcodes.
124 ***********************************************************************/
128 POC_WILD=-1, /* Wild card - used in the pCode peep hole optimizer
129 * to represent ANY pic opcode */
173 /***********************************************************************
174 * PC_TYPE - pCode Types
175 ***********************************************************************/
179 PC_COMMENT=0, // pCode is a comment
180 PC_OPCODE, // PORT dependent opcode
181 PC_LABEL, // assembly label
182 PC_FUNCTION, // Function start or end
183 PC_WILD // wildcard - an opcode place holder
186 /************************************************/
187 /*************** Structures ********************/
188 /************************************************/
191 /*************************************************
194 The first step in optimizing pCode is determining
195 the program flow. This information is stored in
196 single-linked lists in the for of 'from' and 'to'
197 objects with in a pcode. For example, most instructions
198 don't involve any branching. So their from branch
199 points to the pCode immediately preceding them and
200 their 'to' branch points to the pcode immediately
201 following them. A skip instruction is an example of
202 a pcode that has multiple (in this case two) elements
203 in the 'to' branch. A 'label' pcode is an where there
204 may be multiple 'from' branches.
205 *************************************************/
207 typedef struct pBranch
209 struct pCode *pc; // Next pCode in a branch
210 struct pBranch *next; /* If more than one branch
211 * the next one is here */
215 /*************************************************
218 pCode Operand structure.
219 For those assembly instructions that have arguments,
220 the pCode will have a pCodeOp in which the argument
221 can be stored. For example
225 'some_register' will be stored/referenced in a pCodeOp
227 *************************************************/
229 typedef struct pCodeOp
236 typedef struct pCodeOpBit
240 unsigned int inBitSpace: 1; /* True if in bit space, else
241 just a bit of a register */
244 typedef struct pCodeOpLit
250 typedef struct pCodeOpLabel
256 typedef struct pCodeOpWild
263 /*************************************************
266 Here the basic build block of a PIC instruction.
267 Each pic instruction will get allocated a pCode.
268 A linked list of pCodes makes a program.
270 **************************************************/
276 struct pCode *prev; // The pCode objects are linked together
277 struct pCode *next; // in doubly linked lists.
279 pBranch *from; // pCodes that execute before this one
280 pBranch *to; // pCodes that execute after
281 pBranch *label; // pCode instructions that have labels
283 /* "virtual functions"
284 * The pCode structure is like a base class
285 * in C++. The subsequent structures that "inherit"
286 * the pCode structure will initialize these function
287 * pointers to something useful */
288 void (*analyze) (struct pCode *_this);
289 void (*destruct)(struct pCode *_this);
290 void (*print) (FILE *of,struct pCode *_this);
295 /*************************************************
297 **************************************************/
299 typedef struct pCodeComment
308 /*************************************************
311 Here we describe all the facets of a PIC instruction
312 (expansion for the 18cxxx is also provided).
314 **************************************************/
316 typedef struct pCodeInstruction
321 PIC_OPCODE op; // The opcode of the instruction.
323 char *mnemonic; // Pointer to mnemonic string
325 pCodeOp *pcop; // Operand
327 unsigned int num_ops;
328 unsigned int dest: 1; // If destination is W or F, then 1==F
329 unsigned int bit_inst: 1;
334 /*************************************************
336 **************************************************/
338 typedef struct pCodeLabel
346 /*************************************************
348 **************************************************/
350 typedef struct pCodeFunction
356 char *fname; /* If NULL, then this is the end of
357 a function. Otherwise, it's the
358 start and the name is contained
364 /*************************************************
367 Here are PIC program snippets. There's a strong
368 correlation between the eBBlocks and pBlocks.
369 SDCC subdivides a C program into managable chunks.
370 Each chunk becomes a eBBlock and ultimately in the
373 **************************************************/
375 typedef struct pBlock
377 memmap *cmemmap; /* The snippet is from this memmap */
378 pCode *pcHead; /* A pointer to the first pCode in a link list of pCodes */
379 pCode *pcTail; /* A pointer to the last pCode in a link list of pCodes */
381 struct pBlock *next; /* The pBlocks will form a doubly linked list */
386 /*************************************************
389 The collection of pBlock program snippets are
390 placed into a linked list that is implemented
391 in the pFile structure.
393 The pcode optimizer will parse the pFile.
395 **************************************************/
399 pBlock *pbHead; /* A pointer to the first pBlock */
400 pBlock *pbTail; /* A pointer to the last pBlock */
402 pBranch *functions; /* A SLL of functions in this pFile */
407 /*************************************************
410 The pCodePeep object mimics the peep hole optimizer
411 in the main SDCC src (e.g. SDCCpeeph.c). Essentially
412 there is a target pCode chain and a replacement
413 pCode chain. The target chain is compared to the
414 pCode that is generated by gen.c. If a match is
415 found then the pCode is replaced by the replacement
417 **************************************************/
418 typedef struct pCodePeep {
420 pBlock *target; // code we'd like to optimize
421 pBlock *replace; // and this is what we'll optimize it with.
425 /*************************************************
428 **************************************************/
429 #define PCI(x) ((pCodeInstruction *)(x))
430 #define PCL(x) ((pCodeLabel *)(x))
431 #define PCF(x) ((pCodeFunction *)(x))
433 /*-----------------------------------------------------------------*
435 *-----------------------------------------------------------------*/
437 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop); // Create a new pCode given an operand
438 pCode *newpCodeCharP(char *cP); // Create a new pCode given a char *
439 pCode *newpCodeFunction(char *g, char *f); // Create a new function
440 pCode *newpCodeLabel(int key); // Create a new label
441 pBlock *newpCodeChain(memmap *cm,pCode *pc); // Create a new pBlock
442 void printpBlock(FILE *of, pBlock *pb); // Write a pBlock to a file
443 void printpCode(FILE *of, pCode *pc); // Write a pCode to a file
444 void addpCode2pBlock(pBlock *pb, pCode *pc); // Add a pCode to a pBlock
445 void addpBlock(pBlock *pb); // Add a pBlock to a pFile
446 void copypCode(FILE *of, char dbName); // Write all pBlocks with dbName to *of
447 void AnalyzepCode(char dbName);
448 void printCallTree(FILE *of);
450 pCodeOp *newpCodeOpLabel(int key);
451 pCodeOp *newpCodeOpLit(int lit);
452 pCodeOp *newpCodeOpBit(char *name, int bit);
453 pCodeOp *newpCodeOp(char *name);
454 extern void pcode_test(void);
456 /*-----------------------------------------------------------------*
458 *-----------------------------------------------------------------*/
460 extern pCodeOp pc_status;
461 extern pCodeOp pc_indf;
462 extern pCodeOp pc_fsr;
465 //////////////////// DELETE THIS ///////////////////
466 /*-----------------------------------------------------------------*/
467 /* Allocation macros that replace those in SDCCalloc.h */
468 /* Why? I dunno. I ran across a bug with those macros that */
469 /* I couldn't fix, but I could work around... */
470 /*-----------------------------------------------------------------*/
471 # define GC_malloc(x) calloc((x), 1)
473 #define _ALLOC(x,sz) if (!(x = calloc((sz),1) )) \
475 werror(E_OUT_OF_MEM,__FILE__,(long) sz);\
479 #define _ALLOC_ATOMIC(x,y) if (!((x) = malloc(y))) \
481 werror(E_OUT_OF_MEM,__FILE__,(long) y); \
485 #endif // __PCODE_H__