pCode - register allocation, flow analysis, and peephole.
[fw/sdcc] / src / pic / pcode.c
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 #include <stdio.h>
22
23 #include "common.h"   // Include everything in the SDCC src directory
24 #include "newalloc.h"
25 #include "ralloc.h"
26
27 #include "pcode.h"
28
29 // Eventually this will go into device dependent files:
30 pCodeOp pc_status    = {PO_STATUS,  "STATUS"};
31 pCodeOp pc_indf      = {PO_INDF,    "INDF"};
32 pCodeOp pc_fsr       = {PO_FSR,     "FSR"};
33
34 //static char *PIC_mnemonics[] = {
35 static char *scpADDLW = "ADDLW";
36 static char *scpADDWF = "ADDWF";
37 static char *scpANDLW = "ANDLW";
38 static char *scpANDWF = "ANDWF";
39 static char *scpBCF = "BCF";
40 static char *scpBSF = "BSF";
41 static char *scpBTFSC = "BTFSC";
42 static char *scpBTFSS = "BTFSS";
43 static char *scpCALL = "CALL";
44 static char *scpCOMF = "COMF";
45 static char *scpCLRF = "CLRF";
46 static char *scpCLRW = "CLRW";
47 static char *scpDECF = "DECF";
48 static char *scpDECFSZ = "DECFSZ";
49 static char *scpGOTO = "GOTO";
50 static char *scpINCF = "INCF";
51 static char *scpINCFSZ = "INCFSZ";
52 static char *scpIORLW = "IORLW";
53 static char *scpIORWF = "IORWF";
54 static char *scpMOVF = "MOVF";
55 static char *scpMOVLW = "MOVLW";
56 static char *scpMOVWF = "MOVWF";
57 static char *scpNEGF = "NEGF";
58 static char *scpRETLW = "RETLW";
59 static char *scpRETURN = "RETURN";
60 static char *scpSUBLW = "SUBLW";
61 static char *scpSUBWF = "SUBWF";
62 static char *scpTRIS = "TRIS";
63 static char *scpXORLW = "XORLW";
64 static char *scpXORWF = "XORWF";
65
66
67 static pFile *the_pFile = NULL;
68 static int peepOptimizing = 1;
69 static int GpCodeSequenceNumber = 1;
70
71 /****************************************************************/
72 /****************************************************************/
73 typedef struct _DLL {
74   struct _DLL *prev;
75   struct _DLL *next;
76   //  void *data;
77 } _DLL;
78
79
80 typedef struct pCodePeepSnippets
81 {
82   _DLL dll;
83   pCodePeep *peep;
84 } pCodePeepSnippets;
85
86
87 static pCodePeepSnippets  *peepSnippets=NULL;
88
89 /****************************************************************/
90 /*                      Forward declarations                    */
91 /****************************************************************/
92
93 static void unlink(pCode *pc);
94 static void genericAnalyze(pCode *pc);
95 static void AnalyzeGOTO(pCode *pc);
96 static void AnalyzeSKIP(pCode *pc);
97 static void AnalyzeRETURN(pCode *pc);
98
99 static void genericDestruct(pCode *pc);
100 static void genericPrint(FILE *of,pCode *pc);
101
102 static void pCodePrintLabel(FILE *of, pCode *pc);
103 static void pCodePrintFunction(FILE *of, pCode *pc);
104 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
105 static char *get_op( pCodeInstruction *pcc);
106 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
107 int pCodePeepMatchRule(pCode *pc);
108
109
110 char *Safe_strdup(char *str)
111 {
112   char *copy;
113
114   if(!str)
115     return NULL;
116
117   copy = strdup(str);
118   if(!copy) {
119     fprintf(stderr, "out of memory %s,%d\n",__FUNCTION__,__LINE__);
120     exit(1);
121   }
122
123   return copy;
124     
125 }
126
127 char getpBlock_dbName(pBlock *pb)
128 {
129   if(!pb)
130     return 0;
131
132   if(pb->cmemmap)
133     return pb->cmemmap->dbName;
134
135   return pb->dbName;
136 }
137 /*-----------------------------------------------------------------*/
138 /* movepBlock2Head - given the dbname of a pBlock, move all        */
139 /*                   instances to the front of the doubly linked   */
140 /*                   list of pBlocks                               */
141 /*-----------------------------------------------------------------*/
142
143 void movepBlock2Head(char dbName)
144 {
145   pBlock *pb;
146
147   pb = the_pFile->pbHead;
148
149   while(pb) {
150
151     if(getpBlock_dbName(pb) == dbName) {
152       pBlock *pbn = pb->next;
153       pb->next = the_pFile->pbHead;
154       the_pFile->pbHead->prev = pb;
155       the_pFile->pbHead = pb;
156
157       if(pb->prev)
158         pb->prev->next = pbn;
159
160       // If the pBlock that we just moved was the last
161       // one in the link of all of the pBlocks, then we
162       // need to point the tail to the block just before
163       // the one we moved.
164       // Note: if pb->next is NULL, then pb must have 
165       // been the last pBlock in the chain.
166
167       if(pbn)
168         pbn->prev = pb->prev;
169       else
170         the_pFile->pbTail = pb->prev;
171
172       pb = pbn;
173
174     } else
175       pb = pb->next;
176
177   }
178
179 }
180
181 void copypCode(FILE *of, char dbName)
182 {
183   pBlock *pb;
184
185   if(!of || !the_pFile)
186     return;
187
188   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
189     if(getpBlock_dbName(pb) == dbName)
190       printpBlock(of,pb);
191   }
192
193 }
194 void pcode_test(void)
195 {
196
197   printf("pcode is alive!\n");
198
199   if(the_pFile) {
200
201     pBlock *pb;
202     FILE *pFile;
203     char buffer[100];
204
205     /* create the file name */
206     strcpy(buffer,srcFileName);
207     strcat(buffer,".p");
208
209     if( !(pFile = fopen(buffer, "w" ))) {
210       werror(E_FILE_OPEN_ERR,buffer);
211       exit(1);
212     }
213
214     fprintf(pFile,"pcode dump\n\n");
215
216     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
217       fprintf(pFile,"\n\tNew pBlock\n\n");
218       if(pb->cmemmap)
219         fprintf(pFile,"%s",pb->cmemmap->sname);
220       else
221         fprintf(pFile,"internal pblock");
222
223       fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
224       printpBlock(pFile,pb);
225     }
226   }
227 }
228
229 /*-----------------------------------------------------------------*/
230 /* newpCode - create and return a newly initialized pCode          */
231 /*                                                                 */
232 /*  fixme - rename this                                            */
233 /*                                                                 */
234 /* The purpose of this routine is to create a new Instruction      */
235 /* pCode. This is called by gen.c while the assembly code is being */
236 /* generated.                                                      */
237 /*                                                                 */
238 /* Inouts:                                                         */
239 /*  PIC_OPCODE op - the assembly instruction we wish to create.    */
240 /*                  (note that the op is analogous to but not the  */
241 /*                  same thing as the opcode of the instruction.)  */
242 /*  pCdoeOp *pcop - pointer to the operand of the instruction.     */
243 /*                                                                 */
244 /* Outputs:                                                        */
245 /*  a pointer to the new malloc'd pCode is returned.               */
246 /*                                                                 */
247 /*                                                                 */
248 /*                                                                 */
249 /*-----------------------------------------------------------------*/
250 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
251 {
252   pCodeInstruction *pci ;
253     
254
255   pci = Safe_calloc(1, sizeof(pCodeInstruction));
256
257   pci->pc.analyze  = genericAnalyze;       // pointers to the generic functions, it
258   pci->pc.destruct = genericDestruct;      // doesn't hurt to think about C++ virtual
259   pci->pc.print    = genericPrint;         // functions here.
260   pci->pc.type = PC_OPCODE;                // 
261   pci->op = op;                            // the "opcode" for the instruction.
262   pci->pc.prev = pci->pc.next = NULL;      // The pCode gets linked in later
263   pci->pcop = pcop;                        // The operand of the instruction
264   pci->dest = 0;                           // e.g. W or F 
265   pci->bit_inst = 0;                       // e.g. btfxx instructions
266   pci->num_ops = 2;                        // Most instructions have two ops...
267   pci->inCond = pci->outCond = PCC_NONE;   /* input/output conditions. This is used during
268                                             * optimization to ascertain instruction dependencies.
269                                             * For example, if an instruction affects the Z bit,
270                                             * then the output condition for this instruction
271                                             * is "z bit is affected". The "conditions" are bit
272                                             * constants defined in pcode.h. */
273   pci->pc.from = pci->pc.to = NULL;        // Flow linkages are defined later
274   pci->pc.label = NULL;                    // Labels get merged into instructions here.
275   pci->pc.pb = NULL;                       // The pBlock to which this instruction belongs
276
277   if(pcop && pcop->name)
278     printf("newpCode  operand name %s\n",pcop->name);
279
280   // The most pic dependent portion of the pCode logic:
281   switch(op) { 
282
283   case POC_ANDLW:
284     pci->inCond   = PCC_W;
285     pci->outCond  = PCC_W | PCC_Z;
286     pci->mnemonic = scpANDLW;
287     pci->num_ops  = 1;
288     break;
289   case POC_ANDWF:
290     pci->dest = 1;
291     pci->inCond   = PCC_W | PCC_REGISTER;
292     pci->outCond  = PCC_REGISTER | PCC_Z;
293     pci->mnemonic = scpANDWF;
294     break;
295   case POC_ANDFW:
296     pci->inCond   = PCC_W | PCC_REGISTER;
297     pci->outCond  = PCC_W | PCC_Z;
298     pci->mnemonic = scpANDWF;
299     break;
300
301   case POC_ADDLW:
302     pci->inCond   = PCC_W;
303     pci->outCond  = PCC_W | PCC_Z | PCC_C | PCC_DC;
304     pci->mnemonic = scpADDLW;
305     pci->num_ops = 1;
306     break;
307   case POC_ADDWF:
308     pci->dest     = 1;
309     pci->inCond   = PCC_W | PCC_REGISTER;
310     pci->outCond  = PCC_REGISTER | PCC_Z | PCC_C | PCC_DC;
311     pci->mnemonic = scpADDWF;
312     break;
313   case POC_ADDFW:
314     pci->inCond   = PCC_W | PCC_REGISTER;
315     pci->outCond  = PCC_W | PCC_Z | PCC_C | PCC_DC;
316     pci->mnemonic = scpADDWF;
317     break;
318
319   case POC_BCF:
320     pci->bit_inst = 1;
321     pci->mnemonic = scpBCF;
322     break;
323   case POC_BSF:
324     pci->bit_inst = 1;
325     pci->mnemonic = scpBSF;
326     break;
327   case POC_BTFSC:
328     pci->bit_inst = 1;
329     pci->mnemonic = scpBTFSC;
330     pci->pc.analyze = AnalyzeSKIP;
331     break;
332   case POC_BTFSS:
333     pci->bit_inst = 1;
334     pci->mnemonic = scpBTFSS;
335     pci->pc.analyze = AnalyzeSKIP;
336     break;
337   case POC_CALL:
338     pci->num_ops = 1;
339     pci->mnemonic = scpCALL;
340     break;
341   case POC_COMF:
342     pci->mnemonic = scpCOMF;
343     break;
344   case POC_CLRF:
345     pci->num_ops = 1;
346     pci->mnemonic = scpCLRF;
347     break;
348   case POC_CLRW:
349     pci->num_ops = 0;
350     pci->mnemonic = scpCLRW;
351     break;
352   case POC_DECF:
353     pci->dest = 1;
354   case POC_DECFW:
355     pci->mnemonic = scpDECF;
356     break;
357   case POC_DECFSZ:
358     pci->dest = 1;
359   case POC_DECFSZW:
360     pci->mnemonic = scpDECFSZ;
361     pci->pc.analyze = AnalyzeSKIP;
362     break;
363   case POC_GOTO:
364     pci->num_ops = 1;
365     pci->mnemonic = scpGOTO;
366     pci->pc.analyze = AnalyzeGOTO;
367     break;
368   case POC_INCF:
369     pci->dest = 1;
370   case POC_INCFW:
371     pci->mnemonic = scpINCF;
372     break;
373   case POC_INCFSZ:
374     pci->dest = 1;
375   case POC_INCFSZW:
376     pci->mnemonic = scpINCFSZ;
377     pci->pc.analyze = AnalyzeSKIP;
378     break;
379   case POC_IORLW:
380     pci->num_ops = 1;
381     pci->mnemonic = scpIORLW;
382     break;
383   case POC_IORWF:
384     pci->dest = 1;
385   case POC_IORFW:
386     pci->mnemonic = scpIORWF;
387     break;
388   case POC_MOVF:
389     pci->dest = 1;
390   case POC_MOVFW:
391     pci->mnemonic = scpMOVF;
392     break;
393   case POC_MOVLW:
394     pci->num_ops = 1;
395     pci->mnemonic = scpMOVLW;
396     break;
397   case POC_MOVWF:
398     pci->num_ops = 1;
399     pci->mnemonic = scpMOVWF;
400     break;
401   case POC_NEGF:
402     pci->mnemonic = scpNEGF;
403     break;
404   case POC_RETLW:
405     pci->num_ops = 1;
406     pci->mnemonic = scpRETLW;
407     pci->pc.analyze = AnalyzeRETURN;
408     break;
409   case POC_RETURN:
410     pci->num_ops = 0;
411     pci->mnemonic = scpRETURN;
412     pci->pc.analyze = AnalyzeRETURN;
413     break;
414   case POC_SUBLW:
415     pci->mnemonic = scpSUBLW;
416     pci->num_ops = 1;
417     break;
418   case POC_SUBWF:
419     pci->dest = 1;
420   case POC_SUBFW:
421     pci->mnemonic = scpSUBWF;
422     break;
423   case POC_TRIS:
424     pci->mnemonic = scpTRIS;
425     break;
426   case POC_XORLW:
427     pci->num_ops = 1;
428     pci->mnemonic = scpXORLW;
429     break;
430   case POC_XORWF:
431     pci->dest = 1;
432   case POC_XORFW:
433     pci->mnemonic = scpXORWF;
434     break;
435
436   default:
437     pci->pc.print = genericPrint;
438   }
439    
440   return (pCode *)pci;
441 }       
442
443 /*-----------------------------------------------------------------*/
444 /* newpCodeWild - create a "wild" as in wild card pCode            */
445 /*                                                                 */
446 /* Wild pcodes are used during the peep hole optimizer to serve    */
447 /* as place holders for any instruction. When a snippet of code is */
448 /* compared to a peep hole rule, the wild card opcode will match   */
449 /* any instruction. However, the optional operand and label are    */
450 /* additional qualifiers that must also be matched before the      */
451 /* line (of assembly code) is declared matched. Note that the      */
452 /* operand may be wild too.                                        */
453 /*                                                                 */
454 /*-----------------------------------------------------------------*/
455
456 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
457 {
458
459   pCodeWild *pcw;
460     
461   pcw = Safe_calloc(1,sizeof(pCodeWild));
462
463   pcw->pc.type = PC_WILD;
464   pcw->pc.prev = pcw->pc.next = NULL;
465   pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
466   pcw->pc.pb = NULL;
467
468   pcw->pc.analyze = genericAnalyze;
469   pcw->pc.destruct = genericDestruct;
470   pcw->pc.print = genericPrint;
471
472   pcw->id = pCodeID;
473   pcw->operand = optional_operand;
474   pcw->label   = optional_label;
475
476   return ( (pCode *)pcw);
477   
478 }
479
480 /*-----------------------------------------------------------------*/
481 /* newPcodeCharP - create a new pCode from a char string           */
482 /*-----------------------------------------------------------------*/
483
484 pCode *newpCodeCharP(char *cP)
485 {
486
487   pCodeComment *pcc ;
488     
489   pcc = Safe_calloc(1,sizeof(pCodeComment));
490
491   pcc->pc.type = PC_COMMENT;
492   pcc->pc.prev = pcc->pc.next = NULL;
493   pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
494   pcc->pc.pb = NULL;
495
496   pcc->pc.analyze = genericAnalyze;
497   pcc->pc.destruct = genericDestruct;
498   pcc->pc.print = genericPrint;
499
500   pcc->comment = Safe_strdup(cP);
501
502   return ( (pCode *)pcc);
503
504 }
505
506 /*-----------------------------------------------------------------*/
507 /* newpCodeGLabel - create a new global label                      */
508 /*-----------------------------------------------------------------*/
509
510
511 pCode *newpCodeFunction(char *mod,char *f)
512 {
513   pCodeFunction *pcf;
514
515   _ALLOC(pcf,sizeof(pCodeFunction));
516
517   pcf->pc.type = PC_FUNCTION;
518   pcf->pc.prev = pcf->pc.next = NULL;
519   pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
520   pcf->pc.pb = NULL;
521
522   pcf->pc.analyze = genericAnalyze;
523   pcf->pc.destruct = genericDestruct;
524   pcf->pc.print = pCodePrintFunction;
525
526   if(mod) {
527     _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
528     strcpy(pcf->modname,mod);
529   } else
530     pcf->modname = NULL;
531
532   if(f) {
533     _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
534     strcpy(pcf->fname,f);
535   } else
536     pcf->fname = NULL;
537
538   return ( (pCode *)pcf);
539
540 }
541
542
543 pCode *newpCodeLabel(int key)
544 {
545
546   char *s = buffer;
547   pCodeLabel *pcl;
548     
549   pcl = Safe_calloc(1,sizeof(pCodeLabel) );
550
551   pcl->pc.type = PC_LABEL;
552   pcl->pc.prev = pcl->pc.next = NULL;
553   pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
554   pcl->pc.pb = NULL;
555
556   pcl->pc.analyze = genericAnalyze;
557   pcl->pc.destruct = genericDestruct;
558   pcl->pc.print = pCodePrintLabel;
559
560   pcl->key = key;
561
562   if(key>0) {
563     sprintf(s,"_%05d_DS_",key);
564     pcl->label = Safe_strdup(s);
565   } else
566     pcl->label = NULL;
567
568   return ( (pCode *)pcl);
569
570 }
571 pCode *newpCodeLabelStr(char *str)
572 {
573   pCode *pc = newpCodeLabel(-1);
574
575   PCL(pc)->label = Safe_strdup(str);
576
577   return pc;
578 }
579
580 /*-----------------------------------------------------------------*/
581 /* newpBlock - create and return a pointer to a new pBlock         */
582 /*-----------------------------------------------------------------*/
583 pBlock *newpBlock(void)
584 {
585
586   pBlock *PpB;
587
588   _ALLOC(PpB,sizeof(pBlock));
589   PpB->next = PpB->prev = NULL;
590
591   PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
592   PpB->registers = NULL;
593   PpB->visited = 0;
594
595   return PpB;
596
597 }
598
599 /*-----------------------------------------------------------------*/
600 /* newpCodeChain - create a new chain of pCodes                    */
601 /*-----------------------------------------------------------------*
602  *
603  *  This function will create a new pBlock and the pointer to the
604  *  pCode that is passed in will be the first pCode in the block.
605  *-----------------------------------------------------------------*/
606
607
608 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
609 {
610
611   pBlock *pB  = newpBlock();
612
613   pB->pcHead  = pB->pcTail = pc;
614   pB->cmemmap = cm;
615   pB->dbName  = c;
616
617   return pB;
618 }
619
620 /*-----------------------------------------------------------------*/
621 /*-----------------------------------------------------------------*/
622
623 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
624 {
625   pCodeOp *pcop;
626
627   pcop = Safe_calloc(1,sizeof(pCodeOp) );
628   pcop->type = type;
629   pcop->name = Safe_strdup(name);   
630
631   return pcop;
632 }
633
634 /*-----------------------------------------------------------------*/
635 /* newpCodeOpLabel - Create a new label given the key              */
636 /*  Note, a negative key means that the label is part of wild card */
637 /*  (and hence a wild card label) used in the pCodePeep            */
638 /*   optimizations).                                               */
639 /*-----------------------------------------------------------------*/
640
641 pCodeOp *newpCodeOpLabel(int key)
642 {
643   char *s = buffer;
644   pCodeOp *pcop;
645
646   pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
647   pcop->type = PO_LABEL;
648
649   if(key>0) {
650     sprintf(s,"_%05d_DS_",key);
651     pcop->name = Safe_strdup(s);
652   } else
653     pcop->name = NULL;
654
655   ((pCodeOpLabel *)pcop)->key = key;
656
657   return pcop;
658 }
659
660 pCodeOp *newpCodeOpLit(int lit)
661 {
662   char *s = buffer;
663   pCodeOp *pcop;
664
665
666   _ALLOC(pcop,sizeof(pCodeOpLit) );
667   pcop->type = PO_LITERAL;
668   sprintf(s,"0x%02x",lit);
669   _ALLOC_ATOMIC(pcop->name,strlen(s)+1);
670   strcpy(pcop->name,s);
671   ((pCodeOpLit *)pcop)->lit = lit;
672
673   return pcop;
674 }
675
676 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
677 {
678   char *s = buffer;
679   pCodeOp *pcop;
680
681
682   if(!pcp || !subtype) {
683     fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
684     exit(1);
685   }
686
687   pcop = Safe_calloc(1,sizeof(pCodeOpWild));
688   pcop->type = PO_WILD;
689   sprintf(s,"%%%d",id);
690   pcop->name = Safe_strdup(s);
691
692   PCOW(pcop)->id = id;
693   PCOW(pcop)->pcp = pcp;
694   PCOW(pcop)->subtype = subtype;
695   PCOW(pcop)->matched = NULL;
696
697   return pcop;
698 }
699
700 pCodeOp *newpCodeOpBit(char *s, int bit)
701 {
702   pCodeOp *pcop;
703
704   _ALLOC(pcop,sizeof(pCodeOpBit) );
705   pcop->type = PO_BIT;
706   pcop->name = Safe_strdup(s);   
707   PCOB(pcop)->bit = bit;
708   if(bit>=0)
709     PCOB(pcop)->inBitSpace = 1;
710   else
711     PCOB(pcop)->inBitSpace = 0;
712
713   return pcop;
714 }
715
716 /*-----------------------------------------------------------------*/
717 /* addpCode2pBlock - place the pCode into the pBlock linked list   */
718 /*-----------------------------------------------------------------*/
719 void addpCode2pBlock(pBlock *pb, pCode *pc)
720 {
721
722   pb->pcTail->next = pc;
723   pc->prev = pb->pcTail;
724   pc->next = NULL;
725   pc->pb = pb;
726   pb->pcTail = pc;
727 }
728
729 /*-----------------------------------------------------------------*/
730 /* addpBlock - place a pBlock into the pFile                       */
731 /*-----------------------------------------------------------------*/
732 void addpBlock(pBlock *pb)
733 {
734
735   if(!the_pFile) {
736     /* First time called, we'll pass through here. */
737     _ALLOC(the_pFile,sizeof(the_pFile));
738     the_pFile->pbHead = the_pFile->pbTail = pb;
739     the_pFile->functions = NULL;
740     return;
741   }
742
743   the_pFile->pbTail->next = pb;
744   pb->prev = the_pFile->pbTail;
745   pb->next = NULL;
746   the_pFile->pbTail = pb;
747 }
748
749 void printpCodeString(FILE *of, pCode *pc, int max)
750 {
751   int i=0;
752
753   while(pc && (i++<max)) {
754     pc->print(of,pc);
755     pc = pc->next;
756   }
757 }
758 /*-----------------------------------------------------------------*/
759 /* printpCode - write the contents of a pCode to a file            */
760 /*-----------------------------------------------------------------*/
761 void printpCode(FILE *of, pCode *pc)
762 {
763
764   if(!pc || !of)
765     return;
766
767   if(pc->print) {
768     pc->print(of,pc);
769     return;
770   }
771
772   fprintf(of,"warning - unable to print pCode\n");
773 }
774
775 /*-----------------------------------------------------------------*/
776 /* printpBlock - write the contents of a pBlock to a file          */
777 /*-----------------------------------------------------------------*/
778 void printpBlock(FILE *of, pBlock *pb)
779 {
780   pCode *pc;
781
782   if(!pb)
783     return;
784
785   if(!of)
786     of = stderr;
787
788   for(pc = pb->pcHead; pc; pc = pc->next)
789     printpCode(of,pc);
790
791 }
792
793 /*-----------------------------------------------------------------*/
794 /*                                                                 */
795 /*       pCode processing                                          */
796 /*                                                                 */
797 /*                                                                 */
798 /*                                                                 */
799 /*-----------------------------------------------------------------*/
800
801 static void unlink(pCode *pc)
802 {
803   if(pc  && pc->prev && pc->next) {
804
805     pc->prev->next = pc->next;
806     pc->next->prev = pc->prev;
807   }
808 }
809 static void genericDestruct(pCode *pc)
810 {
811   unlink(pc);
812
813   fprintf(stderr,"warning, calling default pCode destructor\n");
814   free(pc);
815 }
816
817
818 void pBlockRegs(FILE *of, pBlock *pb)
819 {
820
821   regs  *r;
822
823   r = setFirstItem(pb->registers);
824   while (r) {
825     fprintf(of,"   %s\n",r->name);
826     r = setNextItem(pb->registers);
827   }
828 }
829
830
831 static char *get_op( pCodeInstruction *pcc)
832 {
833   if(pcc && pcc->pcop) {
834
835
836
837   if(pcc->pcop->type == PO_GPR_TEMP) {
838     regs *r;
839     r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
840     //pcc->pcop->name = Safe_strdup(r->name);
841     //sprintf(buffer, "R0X%x",PCOR(pcc->pcop)->rIdx);
842     //pcc->pcop->name = Safe_strdup(PCOR(pcc->pcop)->r->name);
843     fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
844     pBlockRegs(stderr,pcc->pc.pb);
845     return r->name;
846   }
847
848   if  (pcc->pcop->name)
849     return pcc->pcop->name;
850
851   }
852   return "NO operand";
853 }
854
855 /*-----------------------------------------------------------------*/
856 /*-----------------------------------------------------------------*/
857 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
858 {
859
860   fprintf(of,"pcodeopprint\n");
861 }
862
863 /*-----------------------------------------------------------------*/
864 /* genericPrint - the contents of a pCode to a file                */
865 /*-----------------------------------------------------------------*/
866 static void genericPrint(FILE *of, pCode *pc)
867 {
868
869   if(!pc || !of)
870     return;
871
872   switch(pc->type) {
873   case PC_COMMENT:
874     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
875     break;
876
877   case PC_OPCODE:
878     // If the opcode has a label, print that first
879     {
880       pBranch *pbl = pc->label;
881       while(pbl) {
882         if(pbl->pc->type == PC_LABEL)
883           pCodePrintLabel(of, pbl->pc);
884         pbl = pbl->next;
885       }
886     }
887
888     fprintf(of, "\t%s\t", PCI(pc)->mnemonic);
889     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
890
891       if(PCI(pc)->bit_inst) {
892         if(PCI(pc)->pcop->type == PO_BIT) {
893           if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
894             fprintf(of,"(%s >> 3), (%s & 7)", 
895                     PCI(pc)->pcop->name ,
896                     PCI(pc)->pcop->name );
897           else
898             fprintf(of,"%s,%d", get_op(PCI(pc)), (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
899         } else
900           fprintf(of,"%s,0 ; ?bug", get_op(PCI(pc)));
901         //PCI(pc)->pcop->t.bit );
902       } else {
903
904         if(PCI(pc)->pcop->type == PO_BIT) {
905           if( PCI(pc)->num_ops == 2)
906             fprintf(of,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
907           else
908             fprintf(of,"(1 << (%s & 7))",get_op(PCI(pc)));
909
910 /*
911           if( PCI(pc)->num_ops == 2)
912             fprintf(of,"(%s >> 3),%c",PCI(pc)->pcop->name,((PCI(pc)->dest) ? 'F':'W'));
913           else
914             fprintf(of,"(1 << (%s & 7))",PCI(pc)->pcop->name);
915 */
916         }else {
917           fprintf(of,"%s",get_op(PCI(pc)));
918
919           if( PCI(pc)->num_ops == 2)
920             fprintf(of,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
921         }
922       }
923     }
924
925     {
926       pBranch *dpb = pc->to;   // debug
927       while(dpb) {
928         switch ( dpb->pc->type) {
929         case PC_OPCODE:
930           fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
931           break;
932         case PC_LABEL:
933           fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
934           break;
935         case PC_FUNCTION:
936           fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
937           break;
938         case PC_COMMENT:
939         case PC_WILD:
940           break;
941         }
942         dpb = dpb->next;
943       }
944       fprintf(of,"\n");
945     }
946
947     break;
948
949   case PC_WILD:
950     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
951     if(PCW(pc)->operand) {
952       fprintf(of,";\toperand  ");
953       pCodeOpPrint(of,PCW(pc)->operand );
954     }
955     break;
956
957   case PC_LABEL:
958   default:
959     fprintf(of,"unknown pCode type %d\n",pc->type);
960   }
961
962 }
963
964 /*-----------------------------------------------------------------*/
965 /* pCodePrintFunction - prints function begin/end                  */
966 /*-----------------------------------------------------------------*/
967
968 static void pCodePrintFunction(FILE *of, pCode *pc)
969 {
970
971   if(!pc || !of)
972     return;
973
974   if( ((pCodeFunction *)pc)->modname) 
975     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
976
977   if(PCF(pc)->fname) {
978     pBranch *exits = pc->to;
979     int i=0;
980     fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
981     while(exits) {
982       i++;
983       exits = exits->next;
984     }
985     //if(i) i--;
986     fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
987     
988   }else {
989     if(pc->from && 
990        pc->from->pc->type == PC_FUNCTION &&
991        PCF(pc->from->pc)->fname) 
992       fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
993     else
994       fprintf(of,"; exit point [can't find entry point]\n");
995   }
996 }
997 /*-----------------------------------------------------------------*/
998 /* pCodePrintLabel - prints label                                  */
999 /*-----------------------------------------------------------------*/
1000
1001 static void pCodePrintLabel(FILE *of, pCode *pc)
1002 {
1003
1004   if(!pc || !of)
1005     return;
1006
1007   if(PCL(pc)->label) 
1008     fprintf(of,"%s\n",PCL(pc)->label);
1009   else if (PCL(pc)->key >=0) 
1010     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1011   else
1012     fprintf(of,";wild card label\n");
1013
1014 }
1015
1016 /*-----------------------------------------------------------------*/
1017 /* _DLL * DLL_append                                               */
1018 /*                                                                 */ 
1019 /*  Append a _DLL object to the end of a _DLL (doubly linked list) */ 
1020 /* If The list to which we want to append is non-existant then one */ 
1021 /* is created. Other wise, the end of the list is sought out and   */ 
1022 /* a new DLL object is appended to it. In either case, the void    */
1023 /* *data is added to the newly created DLL object.                 */
1024 /*-----------------------------------------------------------------*/
1025
1026 static void * DLL_append(_DLL *list, _DLL *next)
1027 {
1028   _DLL *b;
1029
1030
1031   /* If there's no list, then create one: */
1032   if(!list) {
1033     next->next = next->prev = NULL;
1034     return next;
1035   }
1036
1037
1038   /* Search for the end of the list. */
1039   b = list;
1040   while(b->next)
1041     b = b->next;
1042
1043   /* Now append the new DLL object */
1044   b->next = next;
1045   b->next->prev = b;
1046   b = b->next; 
1047   b->next = NULL;
1048
1049   return list;
1050   
1051 }  
1052 /*-----------------------------------------------------------------*/
1053
1054 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1055 {
1056   pBranch *b;
1057
1058   if(!h)
1059     return n;
1060
1061   b = h;
1062   while(b->next)
1063     b = b->next;
1064
1065   b->next = n;
1066
1067   return h;
1068   
1069 }  
1070 /*-----------------------------------------------------------------*/
1071 /* pBranchLink - given two pcodes, this function will link them    */
1072 /*               together through their pBranches                  */
1073 /*-----------------------------------------------------------------*/
1074 static void pBranchLink(pCode *f, pCode *t)
1075 {
1076   pBranch *b;
1077
1078   // Declare a new branch object for the 'from' pCode.
1079
1080   _ALLOC(b,sizeof(pBranch));
1081   b->pc = t;                    // The link to the 'to' pCode.
1082   b->next = NULL;
1083
1084   f->to = pBranchAppend(f->to,b);
1085
1086   // Now do the same for the 'to' pCode.
1087
1088   _ALLOC(b,sizeof(pBranch));
1089   b->pc = f;
1090   b->next = NULL;
1091
1092   t->from = pBranchAppend(t->from,b);
1093   
1094 }
1095
1096 #if 0
1097 /*-----------------------------------------------------------------*/
1098 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1099 /*               a pCode                                           */
1100 /*-----------------------------------------------------------------*/
1101 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1102 {
1103   while(pb) {
1104
1105     if(pb->pc == pc)
1106       return pb;
1107
1108     pb = pb->next;
1109   }
1110
1111   return NULL;
1112 }
1113
1114 /*-----------------------------------------------------------------*/
1115 /* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
1116 /*-----------------------------------------------------------------*/
1117 static void pCodeUnlink(pCode *pc)
1118 {
1119   pBranch *pb1,*pb2;
1120   pCode *pc1;
1121
1122   if(!pc->prev || !pc->next) {
1123     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1124     exit(1);
1125   }
1126
1127   /* first remove the pCode from the chain */
1128   pc->prev->next = pc->next;
1129   pc->next->prev = pc->prev;
1130
1131   /* Now for the hard part... */
1132
1133   /* Remove the branches */
1134
1135   pb1 = pc->from;
1136   while(pb1) {
1137     pc1 = pb1->pc;    /* Get the pCode that branches to the
1138                        * one we're unlinking */
1139
1140     /* search for the link back to this pCode (the one we're
1141      * unlinking) */
1142     if(pb2 = pBranchFind(pc1->to,pc)) {
1143       pb2->pc = pc->to->pc;  // make the replacement
1144
1145       /* if the pCode we're unlinking contains multiple 'to'
1146        * branches (e.g. this a skip instruction) then we need
1147        * to copy these extra branches to the chain. */
1148       if(pc->to->next)
1149         pBranchAppend(pb2, pc->to->next);
1150     }
1151     
1152     pb1 = pb1->next;
1153   }
1154
1155
1156 }
1157 #endif
1158 /*-----------------------------------------------------------------*/
1159 /*-----------------------------------------------------------------*/
1160 static void genericAnalyze(pCode *pc)
1161 {
1162   switch(pc->type) {
1163   case PC_WILD:
1164   case PC_COMMENT:
1165     return;
1166   case PC_LABEL:
1167   case PC_FUNCTION:
1168   case PC_OPCODE:
1169     {
1170       // Go through the pCodes that are in pCode chain and link
1171       // them together through the pBranches. Note, the pCodes
1172       // are linked together as a contiguous stream like the 
1173       // assembly source code lines. The linking here mimics this
1174       // except that comments are not linked in.
1175       // 
1176       pCode *npc = pc->next;
1177       while(npc) {
1178         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1179           pBranchLink(pc,npc);
1180           return;
1181         } else
1182           npc = npc->next;
1183       }
1184     }
1185   }
1186 }
1187
1188 /*-----------------------------------------------------------------*/
1189 /* findLabel - Search the pCode for a particular label             */
1190 /*-----------------------------------------------------------------*/
1191 pCode * findLabel(pCodeOpLabel *pcop_label)
1192 {
1193   pBlock *pb;
1194   pCode  *pc;
1195   pBranch *pbr;
1196
1197   if(!the_pFile)
1198     return NULL;
1199
1200   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1201     for(pc = pb->pcHead; pc; pc = pc->next) {
1202       if(pc->type == PC_LABEL) {
1203         if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
1204           return pc;
1205       }
1206       if(pc->type == PC_OPCODE) {
1207         pbr = pc->label;
1208         while(pbr) {
1209           if(pbr->pc->type == PC_LABEL) {
1210             if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
1211               return pc;
1212           }
1213           pbr = pbr->next;
1214         }
1215       }
1216
1217     }
1218   }
1219
1220   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1221   return NULL;
1222 }
1223
1224 /*-----------------------------------------------------------------*/
1225 /* findNextInstruction - given a pCode, find the next instruction  */
1226 /*                       in the linked list                        */
1227 /*-----------------------------------------------------------------*/
1228 pCode * findNextInstruction(pCode *pc)
1229 {
1230
1231   while(pc) {
1232     if(pc->type == PC_OPCODE)
1233       return pc;
1234
1235     pc = pc->next;
1236   }
1237
1238   fprintf(stderr,"Couldn't find instruction\n");
1239   return NULL;
1240 }
1241
1242 /*-----------------------------------------------------------------*/
1243 /* findFunctionEnd - given a pCode find the end of the function    */
1244 /*                   that contains it     t                        */
1245 /*-----------------------------------------------------------------*/
1246 pCode * findFunctionEnd(pCode *pc)
1247 {
1248
1249   while(pc) {
1250     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
1251       return pc;
1252
1253     pc = pc->next;
1254   }
1255
1256   fprintf(stderr,"Couldn't find function end\n");
1257   return NULL;
1258 }
1259
1260 #if 0
1261 /*-----------------------------------------------------------------*/
1262 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
1263 /*                instruction with which it is associated.         */
1264 /*-----------------------------------------------------------------*/
1265 static void AnalyzeLabel(pCode *pc)
1266 {
1267
1268   pCodeUnlink(pc);
1269
1270 }
1271 #endif
1272
1273 static void AnalyzeGOTO(pCode *pc)
1274 {
1275
1276   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
1277
1278 }
1279
1280 static void AnalyzeSKIP(pCode *pc)
1281 {
1282
1283   pBranchLink(pc,findNextInstruction(pc->next));
1284   pBranchLink(pc,findNextInstruction(pc->next->next));
1285
1286 }
1287
1288 static void AnalyzeRETURN(pCode *pc)
1289 {
1290
1291   //  branch_link(pc,findFunctionEnd(pc->next));
1292
1293 }
1294
1295
1296 void AnalyzepBlock(pBlock *pb)
1297 {
1298   pCode *pc;
1299
1300   if(!pb)
1301     return;
1302
1303   /* Find all of the registers used in this pBlock */
1304   for(pc = pb->pcHead; pc; pc = pc->next) {
1305     if(pc->type == PC_OPCODE) {
1306       if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
1307
1308         /* Loop through all of the registers declared so far in
1309            this block and see if we find this new there */
1310
1311         regs *r = setFirstItem(pb->registers);
1312
1313         while(r) {
1314           if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
1315             PCOR(PCI(pc)->pcop)->r = r;
1316             break;
1317           }
1318           r = setNextItem(pb->registers);
1319         }
1320
1321         if(!r) {
1322           /* register wasn't found */
1323           r = Safe_calloc(1, sizeof(regs));
1324           memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
1325           addSet(&pb->registers, r);
1326           PCOR(PCI(pc)->pcop)->r = r;
1327           fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
1328         } else 
1329           fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
1330       }
1331     }
1332   }
1333 }
1334
1335 int OptimizepBlock(pBlock *pb)
1336 {
1337   pCode *pc;
1338   int matches =0;
1339
1340   if(!pb || !peepOptimizing)
1341     return 0;
1342
1343   fprintf(stderr," Optimizing pBlock\n");
1344
1345   for(pc = pb->pcHead; pc; pc = pc->next)
1346     matches += pCodePeepMatchRule(pc);
1347
1348   return matches;
1349
1350 }
1351 /*-----------------------------------------------------------------*/
1352 /* pBlockMergeLabels - remove the pCode labels from the pCode      */
1353 /*                     chain and put them into pBranches that are  */
1354 /*                     associated with the appropriate pCode       */
1355 /*                     instructions.                               */
1356 /*-----------------------------------------------------------------*/
1357 void pBlockMergeLabels(pBlock *pb)
1358 {
1359   pBranch *pbr;
1360   pCode *pc, *pcnext=NULL;
1361
1362   if(!pb)
1363     return;
1364
1365   for(pc = pb->pcHead; pc; pc = pc->next) {
1366
1367     if(pc->type == PC_LABEL) {
1368       if( !(pcnext = findNextInstruction(pc)) ) 
1369         return;  // Couldn't find an instruction associated with this label
1370
1371       // Unlink the pCode label from it's pCode chain
1372       if(pc->prev) 
1373         pc->prev->next = pc->next;
1374       if(pc->next)
1375         pc->next->prev = pc->prev;
1376
1377       // And link it into the instruction's pBranch labels. (Note, since
1378       // it's possible to have multiple labels associated with one instruction
1379       // we must provide a means to accomodate the additional labels. Thus
1380       // the labels are placed into the singly-linked list "label" as 
1381       // opposed to being a single member of the pCodeInstruction.)
1382
1383       _ALLOC(pbr,sizeof(pBranch));
1384       pbr->pc = pc;
1385       pbr->next = NULL;
1386
1387       pcnext->label = pBranchAppend(pcnext->label,pbr);
1388     }
1389
1390   }
1391
1392 }
1393
1394 /*-----------------------------------------------------------------*/
1395 /*-----------------------------------------------------------------*/
1396 void OptimizepCode(char dbName)
1397 {
1398 #define MAX_PASSES 4
1399
1400   int matches = 0;
1401   int passes = 0;
1402   pBlock *pb;
1403
1404   if(!the_pFile)
1405     return;
1406
1407   fprintf(stderr," Optimizing pCode\n");
1408
1409   do {
1410     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1411       if('*' == dbName || getpBlock_dbName(pb) == dbName)
1412         matches += OptimizepBlock(pb);
1413     }
1414   }
1415   while(matches && ++passes < MAX_PASSES);
1416
1417 }
1418
1419 /*-----------------------------------------------------------------*/
1420 /* AnalyzepCode - parse the pCode that has been generated and form */
1421 /*                all of the logical connections.                  */
1422 /*                                                                 */
1423 /* Essentially what's done here is that the pCode flow is          */
1424 /* determined.                                                     */
1425 /*-----------------------------------------------------------------*/
1426
1427 void AnalyzepCode(char dbName)
1428 {
1429   pBlock *pb;
1430   pCode *pc;
1431   pBranch *pbr;
1432
1433   if(!the_pFile)
1434     return;
1435
1436   fprintf(stderr," Analyzing pCode");
1437
1438   /* First, merge the labels with the instructions */
1439   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1440     if('*' == dbName || getpBlock_dbName(pb) == dbName) {
1441       pBlockMergeLabels(pb);
1442       AnalyzepBlock(pb);
1443     }
1444   }
1445
1446   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1447     if('*' == dbName || getpBlock_dbName(pb) == dbName)
1448       OptimizepBlock(pb);
1449   }
1450
1451   /* Now build the call tree.
1452      First we examine all of the pCodes for functions.
1453      Keep in mind that the function boundaries coincide
1454      with pBlock boundaries. 
1455
1456      The algorithm goes something like this:
1457      We have two nested loops. The outer loop iterates
1458      through all of the pBlocks/functions. The inner
1459      loop iterates through all of the pCodes for
1460      a given pBlock. When we begin iterating through
1461      a pBlock, the variable pc_fstart, pCode of the start
1462      of a function, is cleared. We then search for pCodes
1463      of type PC_FUNCTION. When one is encountered, we
1464      initialize pc_fstart to this and at the same time
1465      associate a new pBranch object that signifies a 
1466      branch entry. If a return is found, then this signifies
1467      a function exit point. We'll link the pCodes of these
1468      returns to the matching pc_fstart.
1469
1470      When we're done, a doubly linked list of pBranches
1471      will exist. The head of this list is stored in
1472      `the_pFile', which is the meta structure for all
1473      of the pCode. Look at the printCallTree function
1474      on how the pBranches are linked together.
1475
1476    */
1477   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1478     if('*' == dbName || getpBlock_dbName(pb) == dbName) {
1479       pCode *pc_fstart=NULL;
1480       for(pc = pb->pcHead; pc; pc = pc->next) {
1481         if(pc->type == PC_FUNCTION) {
1482           if (PCF(pc)->fname) {
1483             // I'm not liking this....
1484             // Found the beginning of a function.
1485             _ALLOC(pbr,sizeof(pBranch));
1486             pbr->pc = pc_fstart = pc;
1487             pbr->next = NULL;
1488
1489             the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
1490
1491             // Here's a better way of doing the same:
1492             addSet(&pb->function_entries, pc);
1493
1494           } else {
1495             // Found an exit point in a function, e.g. return
1496             // (Note, there may be more than one return per function)
1497             if(pc_fstart)
1498               pBranchLink(pc_fstart, pc);
1499
1500             addSet(&pb->function_exits, pc);
1501           }
1502         } else  if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
1503           addSet(&pb->function_calls,pc);
1504         }
1505       }
1506     }
1507   }
1508 }
1509
1510 /*-----------------------------------------------------------------*/
1511 /* ispCodeFunction - returns true if *pc is the pCode of a         */
1512 /*                   function                                      */
1513 /*-----------------------------------------------------------------*/
1514 bool ispCodeFunction(pCode *pc)
1515 {
1516
1517   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
1518     return 1;
1519
1520   return 0;
1521 }
1522
1523 /*-----------------------------------------------------------------*/
1524 /* findFunction - Search for a function by name (given the name)   */
1525 /*                in the set of all functions that are in a pBlock */
1526 /* (note - I expect this to change because I'm planning to limit   */
1527 /*  pBlock's to just one function declaration                      */
1528 /*-----------------------------------------------------------------*/
1529 pCode *findFunction(char *fname)
1530 {
1531   pBlock *pb;
1532   pCode *pc;
1533   if(!fname)
1534     return NULL;
1535
1536   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1537
1538     pc = setFirstItem(pb->function_entries);
1539     while(pc) {
1540     
1541       if((pc->type == PC_FUNCTION) &&
1542          (PCF(pc)->fname) && 
1543          (strcmp(fname, PCF(pc)->fname)==0))
1544         return pc;
1545
1546       pc = setNextItem(pb->function_entries);
1547
1548     }
1549
1550   }
1551   return NULL;
1552 }
1553
1554 void MarkUsedRegisters(set *regset)
1555 {
1556
1557   regs *r1,*r2;
1558
1559   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
1560     r2 = pic14_regWithIdx(r1->rIdx);
1561     r2->isFree = 0;
1562     r2->wasUsed = 1;
1563   }
1564 }
1565
1566 void pBlockStats(FILE *of, pBlock *pb)
1567 {
1568
1569   pCode *pc;
1570   regs  *r;
1571
1572   fprintf(of,"***\n  pBlock Stats\n***\n");
1573
1574   // for now just print the first element of each set
1575   pc = setFirstItem(pb->function_entries);
1576   if(pc) {
1577     fprintf(of,"entry\n");
1578     pc->print(of,pc);
1579   }
1580   pc = setFirstItem(pb->function_exits);
1581   if(pc) {
1582     fprintf(of,"has an exit\n");
1583     pc->print(of,pc);
1584   }
1585
1586   pc = setFirstItem(pb->function_calls);
1587   if(pc) {
1588     fprintf(of,"functions called\n");
1589
1590     while(pc) {
1591       pc->print(of,pc);
1592       pc = setNextItem(pb->function_calls);
1593     }
1594   }
1595
1596   r = setFirstItem(pb->registers);
1597   if(r) {
1598     int n = elementsInSet(pb->registers);
1599
1600     fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
1601
1602     while (r) {
1603       fprintf(of,"   %s\n",r->name);
1604       r = setNextItem(pb->registers);
1605     }
1606   }
1607 }
1608
1609 /*-----------------------------------------------------------------*/
1610 /*-----------------------------------------------------------------*/
1611 void sequencepCode(void)
1612 {
1613   pBlock *pb;
1614   pCode *pc;
1615
1616
1617   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1618
1619     pb->seq = GpCodeSequenceNumber+1;
1620
1621     for( pc = pb->pcHead; pc; pc = pc->next)
1622       pc->seq = ++GpCodeSequenceNumber;
1623   }
1624
1625 }
1626
1627 /*-----------------------------------------------------------------*/
1628 /*-----------------------------------------------------------------*/
1629 set *register_usage(pBlock *pb)
1630 {
1631   pCode *pc,*pcn;
1632   set *registers=NULL;
1633   set *registersInCallPath = NULL;
1634
1635   /* check recursion */
1636
1637   pc = setFirstItem(pb->function_entries);
1638
1639   if(!pc)
1640     return registers;
1641
1642   pb->visited = 1;
1643
1644   if(pc->type != PC_FUNCTION)
1645     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
1646
1647   pc = setFirstItem(pb->function_calls);
1648   for( ; pc; pc = setNextItem(pb->function_calls)) {
1649
1650     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
1651       char *dest = get_op(PCI(pc));
1652
1653       pcn = findFunction(dest);
1654       if(pcn) 
1655         registersInCallPath = register_usage(pcn->pb);
1656     } else
1657       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
1658
1659   }
1660
1661
1662   pBlockStats(stderr,pb);  // debug
1663   if(registersInCallPath) {
1664     /* registers were used in the functions this pBlock has called */
1665     /* so now, we need to see if these collide with the ones we are */
1666     /* using here */
1667
1668     regs *r1,*r2, *newreg;
1669
1670     fprintf(stderr,"comparing registers\n");
1671
1672     r1 = setFirstItem(registersInCallPath);
1673     while(r1) {
1674
1675       r2 = setFirstItem(pb->registers);
1676
1677       while(r2) {
1678
1679         if(r2->rIdx == r1->rIdx) {
1680           newreg = pic14_findFreeReg();
1681
1682
1683           if(!newreg) {
1684             fprintf(stderr,"Bummer, no more registers.\n");
1685             exit(1);
1686           }
1687
1688           fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
1689                   r1->rIdx, newreg->rIdx);
1690           r2->rIdx = newreg->rIdx;
1691           //if(r2->name) free(r2->name);
1692           r2->name = Safe_strdup(newreg->name);
1693           newreg->isFree = 0;
1694           newreg->wasUsed = 1;
1695         }
1696         r2 = setNextItem(pb->registers);
1697       }
1698
1699       r1 = setNextItem(registersInCallPath);
1700     }
1701
1702     /* Collisions have been resolved. Now free the registers in the call path */
1703     r1 = setFirstItem(registersInCallPath);
1704     while(r1) {
1705       newreg = pic14_regWithIdx(r1->rIdx);
1706       newreg->isFree = 1;
1707       r1 = setNextItem(registersInCallPath);
1708     }
1709
1710   } else
1711     MarkUsedRegisters(pb->registers);
1712
1713   registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
1714
1715   if(registers) 
1716     fprintf(stderr,"returning regs\n");
1717   else
1718     fprintf(stderr,"not returning regs\n");
1719
1720   fprintf(stderr,"pBlock after register optim.\n");
1721   pBlockStats(stderr,pb);  // debug
1722
1723
1724   return registers;
1725 }
1726
1727 /*-----------------------------------------------------------------*/
1728 /* printCallTree - writes the call tree to a file                  */
1729 /*                                                                 */
1730 /*-----------------------------------------------------------------*/
1731 void pct2(FILE *of,pBlock *pb,int indent)
1732 {
1733   pCode *pc,*pcn;
1734   int i;
1735   //  set *registersInCallPath = NULL;
1736
1737   if(!of)
1738     return;// registers;
1739
1740   if(indent > 10)
1741     return; // registers;   //recursion ?
1742
1743   pc = setFirstItem(pb->function_entries);
1744
1745   if(!pc)
1746     return;
1747
1748   pb->visited = 0;
1749
1750   for(i=0;i<indent;i++)   // Indentation
1751     fputc(' ',of);
1752
1753   if(pc->type == PC_FUNCTION)
1754     fprintf(of,"%s\n",PCF(pc)->fname);
1755   else
1756     return;  // ???
1757
1758
1759   pc = setFirstItem(pb->function_calls);
1760   for( ; pc; pc = setNextItem(pb->function_calls)) {
1761
1762     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
1763       char *dest = get_op(PCI(pc));
1764
1765       pcn = findFunction(dest);
1766       if(pcn) 
1767         pct2(of,pcn->pb,indent+1);
1768     } else
1769       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
1770
1771   }
1772
1773
1774 }
1775
1776 #if 0
1777   fprintf(stderr,"pBlock before register optim.\n");
1778   pBlockStats(stderr,pb);  // debug
1779
1780   if(registersInCallPath) {
1781     /* registers were used in the functions this pBlock has called */
1782     /* so now, we need to see if these collide with the ones we are using here */
1783
1784     regs *r1,*r2, *newreg;
1785
1786     fprintf(stderr,"comparing registers\n");
1787
1788     r1 = setFirstItem(registersInCallPath);
1789     while(r1) {
1790
1791       r2 = setFirstItem(pb->registers);
1792
1793       while(r2) {
1794
1795         if(r2->rIdx == r1->rIdx) {
1796           newreg = pic14_findFreeReg();
1797
1798
1799           if(!newreg) {
1800             fprintf(stderr,"Bummer, no more registers.\n");
1801             exit(1);
1802           }
1803
1804           fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
1805                   r1->rIdx, newreg->rIdx);
1806           r2->rIdx = newreg->rIdx;
1807           //if(r2->name) free(r2->name);
1808           r2->name = Safe_strdup(newreg->name);
1809           newreg->isFree = 0;
1810           newreg->wasUsed = 1;
1811         }
1812         r2 = setNextItem(pb->registers);
1813       }
1814
1815       r1 = setNextItem(registersInCallPath);
1816     }
1817
1818     /* Collisions have been resolved. Now free the registers in the call path */
1819     r1 = setFirstItem(registersInCallPath);
1820     while(r1) {
1821       newreg = pic14_regWithIdx(r1->rIdx);
1822       newreg->isFree = 1;
1823       r1 = setNextItem(registersInCallPath);
1824     }
1825
1826   } else
1827     MarkUsedRegisters(pb->registers);
1828
1829   registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
1830
1831   if(registers) 
1832     fprintf(stderr,"returning regs\n");
1833   else
1834     fprintf(stderr,"not returning regs\n");
1835
1836   fprintf(stderr,"pBlock after register optim.\n");
1837   pBlockStats(stderr,pb);  // debug
1838
1839
1840   return registers;
1841
1842 #endif
1843
1844
1845 /*-----------------------------------------------------------------*/
1846 /* printCallTree - writes the call tree to a file                  */
1847 /*                                                                 */
1848 /*-----------------------------------------------------------------*/
1849
1850 void printCallTree(FILE *of)
1851 {
1852   pBranch *pbr;
1853   pBlock  *pb;
1854   pCode   *pc;
1855
1856   if(!the_pFile)
1857     return;
1858
1859   if(!of)
1860     of = stderr;
1861
1862   fprintf(of, "\npBlock statistics\n");
1863   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
1864     pBlockStats(stderr,pb);
1865
1866
1867
1868   fprintf(of,"Call Tree\n");
1869   pbr = the_pFile->functions;
1870   while(pbr) {
1871     if(pbr->pc) {
1872       pc = pbr->pc;
1873       if(!ispCodeFunction(pc))
1874         fprintf(of,"bug in call tree");
1875
1876
1877       fprintf(of,"Function: %s\n", PCF(pc)->fname);
1878
1879       while(pc->next && !ispCodeFunction(pc->next)) {
1880         pc = pc->next;
1881         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
1882           fprintf(of,"\t%s\n",get_op(PCI(pc)));
1883       }
1884     }
1885
1886     pbr = pbr->next;
1887   }
1888
1889
1890   /* Re-allocate the registers so that there are no collisions
1891    * between local variables when one function call another */
1892
1893   pic14_deallocateAllRegs();
1894
1895   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1896     if(!pb->visited)
1897       register_usage(pb);
1898   }
1899
1900   fprintf(of,"\n**************\n\na better call tree\n");
1901   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1902     if(pb->visited)
1903       pct2(of,pb,0);
1904   }
1905
1906   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1907     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
1908   }
1909 }
1910 /*-----------------------------------------------------------------
1911
1912   pCode peephole optimization
1913
1914
1915   The pCode "peep hole" optimization is not too unlike the peep hole
1916   optimization in SDCCpeeph.c. The major difference is that here we
1917   use pCode's whereas there we use ASCII strings. The advantage with
1918   pCode's is that we can ascertain flow information in the instructions
1919   being optimized.
1920
1921
1922 <FIX ME> - elaborate...
1923
1924   -----------------------------------------------------------------*/
1925
1926 #if 0
1927 /*-----------------------------------------------------------------*/
1928 /* pCodePeep */
1929 /*-----------------------------------------------------------------*/
1930 int pCodePeepCompare(pCode *pc, pCodePeep *pcp)
1931 {
1932   pCode *pcfrom,*pcto;
1933
1934   pcfrom = pc;
1935   for( pcto=pcp->target; pcto; pcto=pcto->next) {
1936
1937     pcfrom = findNextInstruction(pcfrom);
1938
1939     if( pcfrom &&  
1940         (PCI(pcfrom)->op == PCI(pcto)->op || 
1941          PCI(pcto)->op == POC_WILD))
1942       continue;
1943     return 0;
1944   }
1945   return 0;
1946 }
1947
1948 /*-----------------------------------------------------------------*/
1949 /* pCodePeep */
1950 /*-----------------------------------------------------------------*/
1951 void pCodePeepSearch(pCodePeep *snippet)
1952 {
1953   pBlock *pb;
1954   pCode *pc;
1955
1956   if(!the_pFile)
1957     return;
1958
1959   /* compare the chain to the pCode that we've 
1960      got so far. If a match is found, then replace
1961      the pCode chain.
1962   */
1963   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1964     for(pc = pb->pcHead; pc; pc = pc->next) {
1965       pCodePeepCompare(pc,snippet);
1966     }
1967   }
1968
1969 }
1970 #endif
1971
1972 #if 0
1973 pBlock *pBlockAppend(pBlock *pb1, pBlock *pb2)
1974 {
1975   pBlock *pb;
1976
1977   if(!pb1->tail)
1978     return pb2;
1979
1980   pb = pb1->tail;
1981
1982   pb2->head = pb1;
1983   pb2->tail = NULL;
1984   pb1->tail = pb2;
1985
1986 }
1987
1988 #endif
1989
1990 void pCodePeepInit(void)
1991 {
1992   pBlock *pb;
1993   //  pCode *pc;
1994   pCodePeep *pcp;
1995   pCodePeepSnippets *pcps;
1996
1997   /* Declare a peep code snippet */
1998   /* <FIXME> do I really need a separate struct just to DLL the snippets? */
1999   /* e.g. I could put the DLL into the pCodePeep structure */
2000   pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
2001   pcp = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
2002   peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
2003
2004
2005   pb = newpCodeChain(NULL, 'W', newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
2006   addpCode2pBlock( pb,     newpCode(POC_MOVFW, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
2007
2008   pcp->target = pb;
2009
2010   pcp->replace = newpCodeChain(NULL, 'W',newpCode(POC_MOVWF, newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER))) );
2011
2012   /* Allocate space to store pointers to the wildcard variables */
2013   pcp->nvars = 1;
2014   pcp->vars  = Safe_calloc(pcp->nvars, sizeof(char *));
2015   pcp->nwildpCodes = 0;
2016   pcp->wildpCodes  = NULL;
2017
2018   pcp->postFalseCond = PCC_Z;
2019   pcp->postTrueCond  = PCC_NONE;
2020
2021   fprintf(stderr,"Peep rule\nTarget:\n");
2022   printpCodeString(stderr,pcp->target->pcHead, 10);
2023   fprintf(stderr,"Replaced with:\n");
2024   printpCodeString(stderr,pcp->replace->pcHead, 10);
2025
2026   /* Now for another peep example */
2027   pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
2028   pcp = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
2029   peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
2030
2031   {
2032     pCodeOp *pcl;
2033     pCodeOp *pcw;
2034     pCodeOp *pcwb;
2035
2036     pcwb =  newpCodeOpWild(0,pcp,newpCodeOpBit(NULL,-1));
2037     pb = newpCodeChain(NULL, 'W',newpCode(POC_BTFSC,pcwb));
2038
2039     pcl = newpCodeOpLabel(-1);
2040     pcw = newpCodeOpWild(1, pcp, pcl);
2041     addpCode2pBlock( pb,     newpCode(POC_GOTO,  pcw));
2042     addpCode2pBlock( pb,     newpCodeWild(0,NULL,NULL));
2043     addpCode2pBlock( pb,     newpCodeWild(1,NULL,pcw));
2044
2045
2046     pcp->target = pb;
2047
2048     pb = newpCodeChain(NULL, 'W',newpCode(POC_BTFSS, pcwb));
2049     addpCode2pBlock( pb,     newpCodeWild(0,NULL,NULL));
2050     addpCode2pBlock( pb,     newpCodeWild(1,NULL,pcw));
2051
2052     pcp->replace = pb;
2053
2054     /* Allocate space to store pointers to the wildcard variables */
2055     pcp->nvars = 2;
2056     pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
2057     pcp->nwildpCodes = 2;
2058     pcp->wildpCodes = Safe_calloc(pcp->nwildpCodes, sizeof(pCode *));
2059
2060     pcp->postFalseCond = PCC_NONE;
2061     pcp->postTrueCond  = PCC_NONE;
2062   }
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073   //-------------
2074
2075   /* Now for another peep example */
2076   pcps = Safe_calloc(1,sizeof(pCodePeepSnippets));
2077   pcp = pcps->peep  = Safe_calloc(1,sizeof(pCodePeep));
2078   peepSnippets = DLL_append((_DLL*)peepSnippets,(_DLL*)pcps);
2079
2080   {
2081     pCodeOp *pcw;
2082
2083     pcw = newpCodeOpWild(0,pcp,newpCodeOp(NULL,PO_GPR_REGISTER));
2084
2085     pb = newpCodeChain(NULL, 'W', newpCode(POC_MOVWF, pcw));
2086     addpCode2pBlock( pb,     newpCode(POC_MOVWF, pcw));
2087
2088     pcp->target = pb;
2089
2090     pb = newpCodeChain(NULL, 'W',newpCode(POC_MOVWF, pcw));
2091
2092     pcp->replace = pb;
2093
2094     /* Allocate space to store pointers to the wildcard variables */
2095     pcp->nvars = 1;
2096     pcp->vars = Safe_calloc(pcp->nvars, sizeof(char *));
2097     pcp->nwildpCodes = 0;
2098     pcp->wildpCodes = NULL;
2099
2100     pcp->postFalseCond = PCC_NONE;
2101     pcp->postTrueCond  = PCC_NONE;
2102   }
2103
2104
2105
2106
2107 }
2108
2109 /*-----------------------------------------------------------------*/
2110 /* pCodeSearchCondition - Search a pCode chain for a 'condition'   */
2111 /*                                                                 */
2112 /* return conditions                                               */
2113 /*  1 - The Condition was found for a pCode's input                */
2114 /*  0 - No matching condition was found for the whole chain        */
2115 /* -1 - The Condition was found for a pCode's output               */
2116 /*                                                                 */
2117 /*-----------------------------------------------------------------*/
2118 int pCodeSearchCondition(pCode *pc, unsigned int cond)
2119 {
2120
2121   while(pc) {
2122
2123     /* If we reach a function end (presumably an end since we most
2124        probably began the search in the middle of a function), then
2125        the condition was not found. */
2126     if(pc->type == PC_FUNCTION)
2127       return 0;
2128
2129     if(pc->type == PC_OPCODE) {
2130       if(PCI(pc)->inCond & cond)
2131         return 1;
2132       if(PCI(pc)->outCond & cond)
2133         return -1;
2134     }
2135
2136     pc = pc->next;
2137   }
2138
2139   return 0;
2140 }
2141 /*-----------------------------------------------------------------*/
2142 /* pCodePeepMatchLine - Compare source and destination pCodes to   */
2143 /*                      see they're the same.                      */
2144 /*-----------------------------------------------------------------*/
2145 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd)
2146 {
2147   int index;   // index into wild card arrays
2148
2149   if(pcs->type == pcd->type) {
2150
2151     if(pcs->type == PC_OPCODE) {
2152
2153       /* If the opcodes don't match then the line doesn't match */
2154       if(PCI(pcs)->op != PCI(pcd)->op)
2155         return 0;
2156
2157       fprintf(stderr,"%s comparing\n",__FUNCTION__);
2158       pcs->print(stderr,pcs);
2159       pcd->print(stderr,pcd);
2160
2161       /* Compare the operands */
2162       if(PCI(pcd)->pcop) {
2163         if (PCI(pcd)->pcop->type == PO_WILD) {
2164           index = PCOW(PCI(pcd)->pcop)->id;
2165
2166           fprintf(stderr,"destination is wild\n");
2167 #ifdef DEBUG_PCODEPEEP
2168           if (index > peepBlock->nvars) {
2169             fprintf(stderr,"%s - variables exceeded\n",__FUNCTION__);
2170             exit(1);
2171           }
2172 #endif
2173           PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
2174           {
2175             char *n;
2176
2177             if(PCI(pcs)->pcop->type == PO_GPR_TEMP)
2178               n = PCOR(PCI(pcs)->pcop)->r->name;
2179             else
2180               n = PCI(pcs)->pcop->name;
2181
2182             if(peepBlock->vars[index])
2183               return  (strcmp(peepBlock->vars[index],n) == 0);
2184             else {
2185               peepBlock->vars[index] = n; //PCI(pcs)->pcop->name;
2186               return 1;
2187             }
2188           }
2189         }
2190       } else
2191         /* The pcd has no operand. Lines match if pcs has no operand either*/
2192         return (PCI(pcs)->pcop == NULL);
2193     }
2194   }
2195
2196
2197   if((pcd->type == PC_WILD) && (pcs->type == PC_OPCODE)) {
2198
2199     int labindex;
2200
2201     index = PCW(pcd)->id;
2202
2203     fprintf(stderr,"%s comparing wild cards\n",__FUNCTION__);
2204     pcs->print(stderr,pcs);
2205     pcd->print(stderr,pcd);
2206
2207     peepBlock->wildpCodes[PCW(pcd)->id] = pcs;
2208
2209     /* Check for a label associated with this wild pCode */
2210     // If the wild card has a label, make sure the source code does too.
2211     if(PCW(pcd)->label) {
2212       if(!pcs->label)
2213         return 0;
2214
2215       labindex = PCOW(PCW(pcd)->label)->id;
2216       if(peepBlock->vars[labindex] == NULL) {
2217         // First time to encounter this label
2218         peepBlock->vars[labindex] = PCL(pcs->label->pc)->label;
2219         fprintf(stderr,"first time for a label\n");
2220       } else {
2221         if(strcmp(peepBlock->vars[labindex],PCL(pcs->label->pc)->label) != 0) {
2222           fprintf(stderr,"labels don't match\n");
2223           return 0;
2224         }
2225         fprintf(stderr,"matched a label\n");
2226       }
2227
2228     }
2229
2230     if(PCW(pcd)->operand) {
2231       PCOW(PCI(pcd)->pcop)->matched = PCI(pcs)->pcop;
2232       if(peepBlock->vars[index]) {
2233         int i = (strcmp(peepBlock->vars[index],PCI(pcs)->pcop->name) == 0);
2234         if(i)
2235           fprintf(stderr," (matched)\n");
2236         else {
2237           fprintf(stderr," (no match: wild card operand mismatch\n");
2238           fprintf(stderr,"  peepblock= %s,  pcodeop= %s\n",
2239                   peepBlock->vars[index],
2240                   PCI(pcs)->pcop->name);
2241         }
2242         return i;
2243       } else {
2244         peepBlock->vars[index] = PCI(pcs)->pcop->name;
2245         return 1;
2246       }
2247     }
2248
2249     pcs = findNextInstruction(pcs->next); 
2250     if(pcs) {
2251       fprintf(stderr," (next to match)\n");
2252       pcs->print(stderr,pcs);
2253     }
2254
2255     return 1; /*  wild card matches */
2256   }
2257
2258   return 0;
2259 }
2260
2261 /*-----------------------------------------------------------------*/
2262 /*-----------------------------------------------------------------*/
2263 void pCodePeepClrVars(pCodePeep *pcp)
2264 {
2265
2266   int i;
2267
2268   for(i=0;i<pcp->nvars; i++)
2269     pcp->vars[i] = NULL;
2270
2271 }
2272
2273 /*-----------------------------------------------------------------*/
2274 /*-----------------------------------------------------------------*/
2275 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2276 {
2277
2278   if(!pc1 || !pc2)
2279     return;
2280
2281   pc2->next = pc1->next;
2282   if(pc1->next)
2283     pc1->next->prev = pc2;
2284
2285   pc2->prev = pc1;
2286   pc1->next = pc2;
2287
2288 }
2289
2290 /*-----------------------------------------------------------------*/
2291 /* pCodeOpCopy - copy a pcode operator                             */
2292 /*-----------------------------------------------------------------*/
2293 static pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2294 {
2295   pCodeOp *pcopnew=NULL;
2296
2297   if(!pcop)
2298     return NULL;
2299
2300   switch(pcop->type) { 
2301   case PO_CRY:
2302   case PO_BIT:
2303     pcopnew = Safe_calloc(1,sizeof(pCodeOpBit) );
2304     PCOB(pcopnew)->bit = PCOB(pcop)->bit;
2305     PCOB(pcopnew)->inBitSpace = PCOB(pcop)->inBitSpace;
2306
2307     break;
2308
2309   case PO_WILD:
2310     /* Here we expand the wild card into the appropriate type: */
2311     /* By recursively calling pCodeOpCopy */
2312     if(PCOW(pcop)->matched)
2313       pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2314     else {
2315       // Probably a label
2316       pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2317       pcopnew->name = Safe_strdup(PCOW(pcop)->pcp->vars[PCOW(pcop)->id]);
2318       fprintf(stderr,"copied a wild op named %s\n",pcopnew->name);
2319     }
2320
2321     return pcopnew;
2322     break;
2323
2324   case PO_LABEL:
2325     pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2326     PCOLAB(pcopnew)->key =  PCOLAB(pcop)->key;
2327     break;
2328
2329   case PO_LITERAL:
2330   case PO_IMMEDIATE:
2331     pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2332     PCOL(pcopnew)->lit = PCOL(pcop)->lit;
2333     break;
2334
2335   case PO_GPR_REGISTER:
2336   case PO_GPR_TEMP:
2337   case PO_SFR_REGISTER:
2338   case PO_DIR:
2339   case PO_STR:
2340   case PO_NONE:
2341   case PO_W:
2342   case PO_STATUS:
2343   case PO_FSR:
2344   case PO_INDF:
2345
2346     pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
2347
2348   }
2349
2350   pcopnew->type = pcop->type;
2351   pcopnew->name = Safe_strdup(pcop->name);
2352
2353   return pcopnew;
2354 }
2355
2356 #if 0
2357 /*-----------------------------------------------------------------*/
2358 /* pCodeCopy - copy a pcode                                        */
2359 /*-----------------------------------------------------------------*/
2360 static pCode *pCodeCopy(pCode *pc)
2361 {
2362
2363   pCode *pcnew;
2364
2365   pcnew = newpCode(pc->type,pc->pcop);
2366 }
2367 #endif
2368 /*-----------------------------------------------------------------*/
2369 /*-----------------------------------------------------------------*/
2370 void pCodeDeleteChain(pCode *f,pCode *t)
2371 {
2372   pCode *pc;
2373
2374   while(f && f!=t) {
2375     fprintf(stderr,"delete pCode:\n");
2376     pc = f->next;
2377     f->print(stderr,f);
2378     //f->delete(f);
2379     f = pc;
2380   }
2381
2382 }
2383 /*-----------------------------------------------------------------*/
2384 /*-----------------------------------------------------------------*/
2385 int pCodePeepMatchRule(pCode *pc)
2386 {
2387   pCodePeep *peepBlock;
2388   pCode *pct, *pcin;
2389   _DLL *peeprules;
2390   int matched;
2391
2392   peeprules = (_DLL *)peepSnippets;
2393
2394   while(peeprules) {
2395     peepBlock = ((pCodePeepSnippets*)peeprules)->peep;
2396     pCodePeepClrVars(peepBlock);
2397
2398     pcin = pc;
2399     pct = peepBlock->target->pcHead;
2400     matched = 0;
2401     while(pct && pcin) {
2402
2403       if(! (matched = pCodePeepMatchLine(peepBlock, pcin,pct)))
2404         break;
2405
2406       pcin = findNextInstruction(pcin->next);
2407       pct = pct->next;
2408       //debug:
2409       fprintf(stderr,"    matched\n");
2410       if(!pcin)
2411         fprintf(stderr," end of code\n");
2412       if(!pct)
2413         fprintf(stderr," end of rule\n");
2414     }
2415
2416     if(matched && pcin) {
2417
2418       /* So far we matched the rule up to the point of the conditions .
2419        * In other words, all of the opcodes match. Now we need to see
2420        * if the post conditions are satisfied.
2421        * First we check the 'postFalseCond'. This means that we check
2422        * to see if any of the subsequent pCode's in the pCode chain 
2423        * following the point just past where we have matched depend on
2424        * the `postFalseCond' as input then we abort the match
2425        */
2426       fprintf(stderr,"    matched rule so far, now checking conditions\n");
2427       if (peepBlock->postFalseCond && 
2428           (pCodeSearchCondition(pcin,peepBlock->postFalseCond) > 0) )
2429         matched = 0;
2430     }
2431
2432     if(matched && pcin) {
2433
2434       pCode *pcprev;
2435       pCode *pcr;
2436
2437
2438       /* We matched a rule! Now we have to go through and remove the
2439          inefficient code with the optimized version */
2440
2441       fprintf(stderr, "Found a pcode peep match:\nRule:\n");
2442       printpCodeString(stderr,peepBlock->target->pcHead,10);
2443       fprintf(stderr,"first thing matched\n");
2444       pc->print(stderr,pc);
2445       fprintf(stderr,"last thing matched\n");
2446       pcin->print(stderr,pcin);
2447
2448       /* Unlink the original code */
2449       pcprev = pc->prev;
2450       pcprev->next = pcin;
2451       pcin->prev = pc->prev;
2452       pCodeDeleteChain(pc,pcin);
2453
2454       /* Generate the replacement code */
2455       pc = pcprev;
2456       pcr = peepBlock->replace->pcHead;  // This is the replacement code
2457       while (pcr) {
2458         pCodeOp *pcop=NULL;
2459         /* If the replace pcode is an instruction with an operand, */
2460         /* then duplicate the operand (and expand wild cards in the process). */
2461         if(pcr->type == PC_OPCODE) {
2462           if(PCI(pcr)->pcop)
2463             pcop = pCodeOpCopy(PCI(pcr)->pcop);
2464
2465           pCodeInsertAfter(pc, newpCode(PCI(pcr)->op,pcop));
2466         } else if (pcr->type == PC_WILD) {
2467           pCodeInsertAfter(pc,peepBlock->wildpCodes[PCW(pcr)->id]);
2468         }
2469
2470
2471         pc = pc->next;
2472         pc->print(stderr,pc);
2473         pcr = pcr->next;
2474       }
2475
2476       return 1;
2477     }
2478
2479     peeprules = peeprules->next;
2480   }
2481
2482   return 0;
2483 }