]> git.gag.com Git - fw/sdcc/blob - src/pic/pcode.h
a6eae9408f2d79749fa2b8a97ed93a463af6be03
[fw/sdcc] / src / pic / pcode.h
1 /*-------------------------------------------------------------------------
2
3    pcode.h - post code generation
4    Written By -  Scott Dattalo scott@dattalo.com
5
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
9    later version.
10    
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.
15    
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.
19    
20 -------------------------------------------------------------------------*/
21
22 /*
23    Post code generation
24
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:
35
36    example1:
37      movwf  t1
38      movf   t1,w
39
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:
45
46    example2:
47      movwf  t1
48      movf   t1,w     ; Can't remove this movf
49      skpz
50       return
51
52    example3:
53      movwf  t1
54      movf   t1,w     ; This  movf can be removed
55      xorwf  t2,w     ; since xorwf will over write Z 
56      skpz
57       return
58
59 */
60
61
62 #ifndef __PCODE_H__
63 #define __PCODE_H__
64
65 /***********************************************************************
66  *  PIC status bits - this will move into device dependent headers
67  ***********************************************************************/
68 #define PIC_C_BIT    0
69 #define PIC_DC_BIT   1
70 #define PIC_Z_BIT    2
71
72 /***********************************************************************
73  *  Operand types 
74  ***********************************************************************/
75 #define POT_RESULT  0
76 #define POT_LEFT    1
77 #define POT_RIGHT   2
78
79
80 /***********************************************************************
81  *
82  *  PIC_OPTYPE - Operand types that are specific to the PIC architecture
83  *
84  *  If a PIC assembly instruction has an operand then here is where we
85  *  associate a type to it. For example,
86  *
87  *     movf    reg,W
88  *
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.
92  *
93  ***********************************************************************/
94
95
96
97 typedef enum 
98 {
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)
112   PO_LABEL,
113   PO_WILD            // Wild card operand in peep optimizer
114 } PIC_OPTYPE;
115
116
117 /***********************************************************************
118  *
119  *  PIC_OPCODE
120  *
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. 
123  *
124  ***********************************************************************/
125
126 typedef enum
127 {
128   POC_WILD=-1,   /* Wild card - used in the pCode peep hole optimizer
129                   * to represent ANY pic opcode */
130   POC_ADDLW=0,
131   POC_ADDWF,
132   POC_ADDFW,
133   POC_ANDLW,
134   POC_ANDWF,
135   POC_ANDFW,
136   POC_BCF,
137   POC_BSF,
138   POC_BTFSC,
139   POC_BTFSS,
140   POC_CALL,
141   POC_COMF,
142   POC_CLRF,
143   POC_CLRW,
144   POC_DECF,
145   POC_DECFW,
146   POC_DECFSZ,
147   POC_DECFSZW,
148   POC_GOTO,
149   POC_INCF,
150   POC_INCFW,
151   POC_INCFSZ,
152   POC_INCFSZW,
153   POC_IORLW,
154   POC_IORWF,
155   POC_IORFW,
156   POC_MOVF,
157   POC_MOVFW,
158   POC_MOVLW,
159   POC_MOVWF,
160   POC_NEGF,
161   POC_RETLW,
162   POC_RETURN,
163   POC_SUBLW,
164   POC_SUBWF,
165   POC_SUBFW,
166   POC_TRIS,
167   POC_XORLW,
168   POC_XORWF,
169   POC_XORFW
170 } PIC_OPCODE;
171
172
173 /***********************************************************************
174  *  PC_TYPE  - pCode Types
175  ***********************************************************************/
176
177 typedef enum
178 {
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
184 } PC_TYPE;
185
186 /************************************************/
187 /***************  Structures ********************/
188 /************************************************/
189 struct pCode;
190
191 /*************************************************
192   pBranch
193
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  *************************************************/
206
207 typedef struct pBranch
208 {
209   struct pCode   *pc;    // Next pCode in a branch
210   struct pBranch *next;  /* If more than one branch
211                           * the next one is here */
212
213 } pBranch;
214
215 /*************************************************
216   pCodeOp
217
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
222
223     movf   some_register,w
224
225   'some_register' will be stored/referenced in a pCodeOp
226
227  *************************************************/
228
229 typedef struct pCodeOp
230 {
231   PIC_OPTYPE type;
232   char *name;
233   
234 } pCodeOp;
235
236 typedef struct pCodeOpBit
237 {
238   pCodeOp pcop;
239   int bit;
240   unsigned int inBitSpace: 1; /* True if in bit space, else
241                                  just a bit of a register */
242 } pCodeOpBit;
243
244 typedef struct pCodeOpLit
245 {
246   pCodeOp pcop;
247   int lit;
248 } pCodeOpLit;
249
250 typedef struct pCodeOpLabel
251 {
252   pCodeOp pcop;
253   int key;
254 } pCodeOpLabel;
255
256 typedef struct pCodeOpWild
257 {
258   pCodeOp pcop;
259   int id;
260 } pCodeOpWild;
261
262
263 /*************************************************
264     pCode
265
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.
269
270 **************************************************/
271
272 typedef struct pCode
273 {
274   PC_TYPE    type;
275
276   struct pCode *prev;  // The pCode objects are linked together
277   struct pCode *next;  // in doubly linked lists.
278
279   pBranch *from;       // pCodes that execute before this one
280   pBranch *to;         // pCodes that execute after
281   pBranch *label;      // pCode instructions that have labels
282
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);
291
292 } pCode;
293
294
295 /*************************************************
296     pCodeComment
297 **************************************************/
298
299 typedef struct pCodeComment
300 {
301
302   pCode  pc;
303
304   char *comment;
305
306 } pCodeComment;
307
308 /*************************************************
309     pCodeInstruction
310
311     Here we describe all the facets of a PIC instruction
312     (expansion for the 18cxxx is also provided).
313
314 **************************************************/
315
316 typedef struct pCodeInstruction
317 {
318
319   pCode  pc;
320
321   PIC_OPCODE op;        // The opcode of the instruction.
322
323   char *mnemonic;       // Pointer to mnemonic string
324
325   pCodeOp *pcop;        // Operand
326
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;
330
331 } pCodeInstruction;
332
333
334 /*************************************************
335     pCodeLabel
336 **************************************************/
337
338 typedef struct pCodeLabel
339 {
340
341   pCode  pc;
342
343   int key;
344 } pCodeLabel;
345
346 /*************************************************
347     pCodeFunction
348 **************************************************/
349
350 typedef struct pCodeFunction
351 {
352
353   pCode  pc;
354
355   char *modname;
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
359                       here */
360
361 } pCodeFunction;
362
363
364 /*************************************************
365     pBlock
366
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
371     PIC port a pBlock.
372
373 **************************************************/
374
375 typedef struct pBlock
376 {
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 */
380
381   struct pBlock *next;      /* The pBlocks will form a doubly linked list */
382   struct pBlock *prev;
383
384 } pBlock;
385
386 /*************************************************
387     pFile
388
389     The collection of pBlock program snippets are
390     placed into a linked list that is implemented
391     in the pFile structure.
392
393     The pcode optimizer will parse the pFile.
394
395 **************************************************/
396
397 typedef struct pFile
398 {
399   pBlock *pbHead;     /* A pointer to the first pBlock */
400   pBlock *pbTail;     /* A pointer to the last pBlock */
401
402   pBranch *functions; /* A SLL of functions in this pFile */
403
404 } pFile;
405
406
407 /*************************************************
408   pCodePeep
409
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
416   pCode chain.
417 **************************************************/
418 typedef struct pCodePeep {
419
420   pBlock *target;    // code we'd like to optimize
421   pBlock *replace;   // and this is what we'll optimize it with.
422
423 } pCodePeep;
424
425 /*************************************************
426     pCode Macros
427
428 **************************************************/
429 #define PCI(x)  ((pCodeInstruction *)(x))
430 #define PCL(x)  ((pCodeLabel *)(x))
431 #define PCF(x)  ((pCodeFunction *)(x))
432
433 /*-----------------------------------------------------------------*
434  * pCode functions.
435  *-----------------------------------------------------------------*/
436
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);
449
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);
455
456 /*-----------------------------------------------------------------*
457  * pCode objects.
458  *-----------------------------------------------------------------*/
459
460 extern pCodeOp pc_status;
461 extern pCodeOp pc_indf;
462 extern pCodeOp pc_fsr;
463
464
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)
472
473 #define  _ALLOC(x,sz) if (!(x = calloc((sz),1) ))      \
474          {                                          \
475             werror(E_OUT_OF_MEM,__FILE__,(long) sz);\
476             exit (1);                               \
477          }
478
479 #define _ALLOC_ATOMIC(x,y) if (!((x) = malloc(y)))   \
480          {                                               \
481             werror(E_OUT_OF_MEM,__FILE__,(long) y);     \
482             exit (1);                                    \
483          }
484
485 #endif // __PCODE_H__