Added pCode to the PIC port
[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
25 #include "pcode.h"
26
27 // Eventually this will go into device depended files:
28 pCodeOp pc_status    = {PO_STATUS,  "status"};
29 pCodeOp pc_indf      = {PO_INDF,    "indf"};
30 pCodeOp pc_fsr       = {PO_FSR,     "fsr"};
31
32
33 //static char *PIC_mnemonics[] = {
34 static char *scpADDLW = "ADDLW";
35 static char *scpADDWF = "ADDWF";
36 static char *scpANDLW = "ANDLW";
37 static char *scpANDWF = "ANDWF";
38 static char *scpBCF = "BCF";
39 static char *scpBSF = "BSF";
40 static char *scpBTFSC = "BTFSC";
41 static char *scpBTFSS = "BTFSS";
42 static char *scpCALL = "CALL";
43 static char *scpCOMF = "COMF";
44 static char *scpCLRF = "CLRF";
45 static char *scpCLRW = "CLRW";
46 static char *scpDECF = "DECF";
47 static char *scpDECFSZ = "DECFSZ";
48 static char *scpGOTO = "GOTO";
49 static char *scpINCF = "INCF";
50 static char *scpINCFSZ = "INCFSZ";
51 static char *scpIORLW = "IORLW";
52 static char *scpIORWF = "IORWF";
53 static char *scpMOVF = "MOVF";
54 static char *scpMOVLW = "MOVLW";
55 static char *scpMOVWF = "MOVWF";
56 static char *scpNEGF = "NEGF";
57 static char *scpRETLW = "RETLW";
58 static char *scpRETURN = "RETURN";
59 static char *scpSUBLW = "SUBLW";
60 static char *scpSUBWF = "SUBWF";
61 static char *scpTRIS = "TRIS";
62 static char *scpXORLW = "XORLW";
63 static char *scpXORWF = "XORWF";
64
65
66 static pFile *the_pFile = NULL;
67
68 /****************************************************************/
69 /****************************************************************/
70 static pBlock *peepSnippets=NULL;
71
72 /****************************************************************/
73 /*                      Forward declarations                    */
74 /****************************************************************/
75
76 static void unlink(pCode *pc);
77 static void genericAnalyze(pCode *pc);
78 static void AnalyzeGOTO(pCode *pc);
79 static void AnalyzeSKIP(pCode *pc);
80 static void AnalyzeRETURN(pCode *pc);
81
82 static void genericDestruct(pCode *pc);
83 static void genericPrint(FILE *of,pCode *pc);
84
85 static void pCodePrintLabel(FILE *of, pCode *pc);
86 static void pCodePrintFunction(FILE *of, pCode *pc);
87 static char *get_op( pCodeInstruction *pcc);
88
89 void copypCode(FILE *of, char dbName)
90 {
91   pBlock *pb;
92
93   if(!of || !the_pFile)
94     return;
95
96   fprintf(of,";dumping pcode to a file");
97
98   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
99     if(pb->cmemmap->dbName == dbName)
100       printpBlock(of,pb);
101   }
102
103 }
104 void pcode_test(void)
105 {
106
107   printf("pcode is alive!\n");
108
109   if(the_pFile) {
110
111     pBlock *pb;
112     FILE *pFile;
113     char buffer[100];
114
115     /* create the file name */
116     strcpy(buffer,srcFileName);
117     strcat(buffer,".p");
118
119     if( !(pFile = fopen(buffer, "w" ))) {
120       werror(E_FILE_OPEN_ERR,buffer);
121       exit(1);
122     }
123
124     fprintf(pFile,"pcode dump\n\n");
125
126     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
127       fprintf(pFile,"\n\tNew pBlock\n\n");
128       fprintf(pFile,"%s, dbName =%c\n",pb->cmemmap->sname,pb->cmemmap->dbName);
129       printpBlock(pFile,pb);
130     }
131   }
132 }
133
134 /*-----------------------------------------------------------------*/
135 /* newpCode - create and return a newly initialized pCode          */
136 /*-----------------------------------------------------------------*/
137 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
138 {
139   pCodeInstruction *pci ;
140     
141
142   _ALLOC(pci,sizeof(pCodeInstruction));
143   pci->pc.analyze = genericAnalyze;
144   pci->pc.destruct = genericDestruct;
145   pci->pc.type = PC_OPCODE;
146   pci->op = op;
147   pci->pc.prev = pci->pc.next = NULL;
148   pci->pcop = pcop;
149   pci->dest = 0;
150   pci->bit_inst = 0;
151   pci->num_ops = 2;
152   pci->pc.print = genericPrint;
153   pci->pc.from = pci->pc.to = pci->pc.label = NULL;
154
155   if(pcop && pcop->name)
156     printf("newpCode  operand name %s\n",pcop->name);
157
158   switch(op) { 
159
160   case POC_ANDLW:
161     pci->mnemonic = scpANDLW;
162     pci->num_ops = 1;
163     break;
164   case POC_ANDWF:
165     pci->dest = 1;
166   case POC_ANDFW:
167     pci->mnemonic = scpANDWF;
168     break;
169
170   case POC_ADDLW:
171     pci->mnemonic = scpADDLW;
172     pci->num_ops = 1;
173     break;
174   case POC_ADDWF:
175     pci->dest = 1;
176   case POC_ADDFW:
177     pci->mnemonic = scpADDWF;
178     break;
179   case POC_BCF:
180     pci->bit_inst = 1;
181     pci->mnemonic = scpBCF;
182     break;
183   case POC_BSF:
184     pci->bit_inst = 1;
185     pci->mnemonic = scpBSF;
186     break;
187   case POC_BTFSC:
188     pci->bit_inst = 1;
189     pci->mnemonic = scpBTFSC;
190     pci->pc.analyze = AnalyzeSKIP;
191     break;
192   case POC_BTFSS:
193     pci->bit_inst = 1;
194     pci->mnemonic = scpBTFSS;
195     pci->pc.analyze = AnalyzeSKIP;
196     break;
197   case POC_CALL:
198     pci->num_ops = 1;
199     pci->mnemonic = scpCALL;
200     break;
201   case POC_COMF:
202     pci->mnemonic = scpCOMF;
203     break;
204   case POC_CLRF:
205     pci->num_ops = 1;
206     pci->mnemonic = scpCLRF;
207     break;
208   case POC_CLRW:
209     pci->num_ops = 0;
210     pci->mnemonic = scpCLRW;
211     break;
212   case POC_DECF:
213     pci->dest = 1;
214   case POC_DECFW:
215     pci->mnemonic = scpDECF;
216     break;
217   case POC_DECFSZ:
218     pci->dest = 1;
219   case POC_DECFSZW:
220     pci->mnemonic = scpDECFSZ;
221     pci->pc.analyze = AnalyzeSKIP;
222     break;
223   case POC_GOTO:
224     pci->num_ops = 1;
225     pci->mnemonic = scpGOTO;
226     pci->pc.analyze = AnalyzeGOTO;
227     break;
228   case POC_INCF:
229     pci->dest = 1;
230   case POC_INCFW:
231     pci->mnemonic = scpINCF;
232     break;
233   case POC_INCFSZ:
234     pci->dest = 1;
235   case POC_INCFSZW:
236     pci->mnemonic = scpINCFSZ;
237     pci->pc.analyze = AnalyzeSKIP;
238     break;
239   case POC_IORLW:
240     pci->num_ops = 1;
241     pci->mnemonic = scpIORLW;
242     break;
243   case POC_IORWF:
244     pci->dest = 1;
245   case POC_IORFW:
246     pci->mnemonic = scpIORWF;
247     break;
248   case POC_MOVF:
249     pci->dest = 1;
250   case POC_MOVFW:
251     pci->mnemonic = scpMOVF;
252     break;
253   case POC_MOVLW:
254     pci->num_ops = 1;
255     pci->mnemonic = scpMOVLW;
256     break;
257   case POC_MOVWF:
258     pci->num_ops = 1;
259     pci->mnemonic = scpMOVWF;
260     break;
261   case POC_NEGF:
262     pci->mnemonic = scpNEGF;
263     break;
264   case POC_RETLW:
265     pci->num_ops = 1;
266     pci->mnemonic = scpRETLW;
267     pci->pc.analyze = AnalyzeRETURN;
268     break;
269   case POC_RETURN:
270     pci->num_ops = 0;
271     pci->mnemonic = scpRETURN;
272     pci->pc.analyze = AnalyzeRETURN;
273     break;
274   case POC_SUBLW:
275     pci->mnemonic = scpSUBLW;
276     pci->num_ops = 1;
277     break;
278   case POC_SUBWF:
279     pci->dest = 1;
280   case POC_SUBFW:
281     pci->mnemonic = scpSUBWF;
282     break;
283   case POC_TRIS:
284     pci->mnemonic = scpTRIS;
285     break;
286   case POC_XORLW:
287     pci->num_ops = 1;
288     pci->mnemonic = scpXORLW;
289     break;
290   case POC_XORWF:
291     pci->dest = 1;
292   case POC_XORFW:
293     pci->mnemonic = scpXORWF;
294     break;
295
296   default:
297     pci->pc.print = genericPrint;
298   }
299    
300   return (pCode *)pci;
301 }       
302
303
304 /*-----------------------------------------------------------------*/
305 /* newPcodeCharP - create a new pCode from a char string           */
306 /*-----------------------------------------------------------------*/
307
308 pCode *newpCodeCharP(char *cP)
309 {
310
311   pCodeComment *pcc ;
312     
313   _ALLOC(pcc,sizeof(pCodeComment));
314    
315   pcc->pc.type = PC_COMMENT;
316   pcc->pc.prev = pcc->pc.next = NULL;
317   pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
318
319   pcc->pc.analyze = genericAnalyze;
320   pcc->pc.destruct = genericDestruct;
321   pcc->pc.print = genericPrint;
322
323   if(cP) {
324     _ALLOC_ATOMIC(pcc->comment,strlen(cP)+1);
325     strcpy(pcc->comment,cP);
326   } else
327     pcc->comment = NULL;
328
329   return ( (pCode *)pcc);
330
331 }
332
333 /*-----------------------------------------------------------------*/
334 /* newpCodeGLabel - create a new global label                      */
335 /*-----------------------------------------------------------------*/
336
337
338 pCode *newpCodeFunction(char *mod,char *f)
339 {
340   pCodeFunction *pcf;
341
342   _ALLOC(pcf,sizeof(pCodeFunction));
343
344   pcf->pc.type = PC_FUNCTION;
345   pcf->pc.prev = pcf->pc.next = NULL;
346   pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
347
348   pcf->pc.analyze = genericAnalyze;
349   pcf->pc.destruct = genericDestruct;
350   pcf->pc.print = pCodePrintFunction;
351
352   if(mod) {
353     _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
354     strcpy(pcf->modname,mod);
355   } else
356     pcf->modname = NULL;
357
358   if(f) {
359     _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
360     strcpy(pcf->fname,f);
361   } else
362     pcf->fname = NULL;
363
364   return ( (pCode *)pcf);
365
366 }
367
368
369 pCode *newpCodeLabel(int key)
370 {
371
372   pCodeLabel *pcl;
373     
374   _ALLOC(pcl,sizeof(pCodeLabel));
375    
376   pcl->pc.type = PC_LABEL;
377   pcl->pc.prev = pcl->pc.next = NULL;
378   pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
379
380   pcl->pc.analyze = genericAnalyze;
381   pcl->pc.destruct = genericDestruct;
382   pcl->pc.print = pCodePrintLabel;
383
384   pcl->key = key;
385
386   return ( (pCode *)pcl);
387
388 }
389
390 /*-----------------------------------------------------------------*/
391 /* newpBlock - create and return a pointer to a new pBlock         */
392 /*-----------------------------------------------------------------*/
393 pBlock *newpBlock(void)
394 {
395
396   pBlock *PpB;
397
398   _ALLOC(PpB,sizeof(pBlock));
399   PpB->next = PpB->prev = NULL;
400
401   return PpB;
402
403 }
404
405 /*-----------------------------------------------------------------*/
406 /* newpCodeChain - create a new chain of pCodes                    */
407 /*-----------------------------------------------------------------*
408  *
409  *  This function will create a new pBlock and the pointer to the
410  *  pCode that is passed in will be the first pCode in the block.
411  *-----------------------------------------------------------------*/
412
413
414 pBlock *newpCodeChain(memmap *cm,pCode *pc)
415 {
416
417   pBlock *pB = newpBlock();
418
419   pB->pcHead = pB->pcTail = pc;
420   pB->cmemmap = cm;
421
422   return pB;
423 }
424
425 /*-----------------------------------------------------------------*/
426 /*-----------------------------------------------------------------*/
427
428 pCodeOp *newpCodeOp(char *name)
429 {
430   pCodeOp *pcop;
431
432   _ALLOC(pcop,sizeof(pCodeOp) );
433   pcop->type = PO_NONE;
434   pcop->name = strdup(name);   
435
436   return pcop;
437 }
438
439 pCodeOp *newpCodeOpLabel(int key)
440 {
441   char *s = buffer;
442   pCodeOp *pcop;
443
444   _ALLOC(pcop,sizeof(pCodeOpLabel) );
445   sprintf(s,"_%05d_DS_",key);
446   pcop->type = PO_LABEL;
447   pcop->name = strdup(s);
448   ((pCodeOpLabel *)pcop)->key = key;
449
450   return pcop;
451 }
452
453 pCodeOp *newpCodeOpLit(int lit)
454 {
455   char *s = buffer;
456   pCodeOp *pcop;
457
458
459   _ALLOC(pcop,sizeof(pCodeOpLit) );
460   pcop->type = PO_LITERAL;
461   sprintf(s,"0x%02x",lit);
462   _ALLOC_ATOMIC(pcop->name,strlen(s)+1);
463   strcpy(pcop->name,s);
464   ((pCodeOpLit *)pcop)->lit = lit;
465
466   return pcop;
467 }
468
469 pCodeOp *newpCodeOpWild(int id)
470 {
471   char *s = buffer;
472   pCodeOp *pcop;
473
474
475   _ALLOC(pcop,sizeof(pCodeOpWild) );
476   pcop->type = PO_WILD;
477   sprintf(s,"%%%d",id);
478   _ALLOC_ATOMIC(pcop->name,strlen(s)+1);
479   strcpy(pcop->name,s);
480   ((pCodeOpWild *)pcop)->id = id;
481
482   return pcop;
483 }
484
485 pCodeOp *newpCodeOpBit(char *s, int bit)
486 {
487   pCodeOp *pcop;
488
489   _ALLOC(pcop,sizeof(pCodeOpBit) );
490   pcop->type = PO_BIT;
491   pcop->name = strdup(s);   
492   ((pCodeOpBit *)pcop)->bit = bit;
493   ((pCodeOpBit *)pcop)->inBitSpace = 1;
494
495   return pcop;
496 }
497
498 /*-----------------------------------------------------------------*/
499 /* addpCode2pBlock - place the pCode into the pBlock linked list   */
500 /*-----------------------------------------------------------------*/
501 void addpCode2pBlock(pBlock *pb, pCode *pc)
502 {
503
504   pb->pcTail->next = pc;
505   pc->prev = pb->pcTail;
506   pc->next = NULL;
507   pb->pcTail = pc;
508 }
509
510 /*-----------------------------------------------------------------*/
511 /* addpBlock - place a pBlock into the pFile                       */
512 /*-----------------------------------------------------------------*/
513 void addpBlock(pBlock *pb)
514 {
515
516   if(!the_pFile) {
517     /* First time called, we'll pass through here. */
518     _ALLOC(the_pFile,sizeof(the_pFile));
519     the_pFile->pbHead = the_pFile->pbTail = pb;
520     the_pFile->functions = NULL;
521     return;
522   }
523
524   the_pFile->pbTail->next = pb;
525   pb->prev = the_pFile->pbTail;
526   pb->next = NULL;
527   the_pFile->pbTail = pb;
528 }
529
530
531 /*-----------------------------------------------------------------*/
532 /* printpCode - write the contents of a pCode to a file            */
533 /*-----------------------------------------------------------------*/
534 void printpCode(FILE *of, pCode *pc)
535 {
536
537   if(!pc || !of)
538     return;
539
540   if(pc->print) {
541     pc->print(of,pc);
542     return;
543   }
544
545   fprintf(of,"warning - unable to print pCode\n");
546 }
547
548 /*-----------------------------------------------------------------*/
549 /* printpBlock - write the contents of a pBlock to a file          */
550 /*-----------------------------------------------------------------*/
551 void printpBlock(FILE *of, pBlock *pb)
552 {
553   pCode *pc;
554
555   if(!pb)
556     return;
557
558   if(!of)
559     of = stderr;
560
561   for(pc = pb->pcHead; pc; pc = pc->next)
562     printpCode(of,pc);
563
564 }
565
566 /*-----------------------------------------------------------------*/
567 /*                                                                 */
568 /*       pCode processing                                          */
569 /*                                                                 */
570 /*    The stuff that follows is very PIC specific!                 */
571 /*                                                                 */
572 /*                                                                 */
573 /*                                                                 */
574 /*                                                                 */
575 /*-----------------------------------------------------------------*/
576
577 static void unlink(pCode *pc)
578 {
579   if(pc  && pc->prev && pc->next) {
580
581     pc->prev->next = pc->next;
582     pc->next->prev = pc->prev;
583   }
584 }
585 static void genericDestruct(pCode *pc)
586 {
587   unlink(pc);
588
589   fprintf(stderr,"warning, calling default pCode destructor\n");
590   free(pc);
591 }
592
593 static char *get_op( pCodeInstruction *pcc)
594 {
595   if(pcc && pcc->pcop && pcc->pcop->name)
596     return pcc->pcop->name;
597   return "NO operand";
598 #if 0
599   operand *op;
600
601   switch(pcc->lrr) {
602
603   case POT_RESULT:
604     op = IC_RESULT(pcc->ic);
605     break;
606   case POT_LEFT:
607     op = IC_LEFT(pcc->ic);
608     break;
609   case POT_RIGHT:
610     op = IC_RIGHT(pcc->ic);
611     break;
612
613   default:
614     return "get_op bad lrr";
615   }
616
617   return(OP_SYMBOL(op)->rname[0] ? OP_SYMBOL(op)->rname : OP_SYMBOL(op)->name);
618   
619 #endif
620 }
621
622 /*-----------------------------------------------------------------*/
623 /* genericPrint - the contents of a pCode to a file                */
624 /*-----------------------------------------------------------------*/
625 static void genericPrint(FILE *of, pCode *pc)
626 {
627
628   if(!pc || !of)
629     return;
630
631   switch(pc->type) {
632   case PC_COMMENT:
633     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
634     break;
635
636   case PC_OPCODE:
637     // If the opcode has a label, print that first
638     {
639       pBranch *pbl = pc->label;
640       while(pbl) {
641         if(pbl->pc->type == PC_LABEL)
642           pCodePrintLabel(of, pbl->pc);
643         pbl = pbl->next;
644       }
645     }
646
647     fprintf(of, "\t%s\t", PCI(pc)->mnemonic);
648     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
649
650       if(PCI(pc)->bit_inst) {
651         if(PCI(pc)->pcop->type == PO_BIT) {
652           if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
653             fprintf(of,"(%s >> 3), (%s & 7)", 
654                     PCI(pc)->pcop->name ,
655                     PCI(pc)->pcop->name );
656           else
657             fprintf(of,"%s,%d", get_op(PCI(pc)), (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
658         } else
659           fprintf(of,"%s,0 ; ?bug", get_op(PCI(pc)));
660         //PCI(pc)->pcop->t.bit );
661       } else {
662
663         if(PCI(pc)->pcop->type == PO_BIT) {
664           if( PCI(pc)->num_ops == 2)
665             fprintf(of,"(%s >> 3),%c",PCI(pc)->pcop->name,((PCI(pc)->dest) ? 'F':'W'));
666           else
667             fprintf(of,"(1 << (%s & 7))",PCI(pc)->pcop->name);
668         }else {
669           fprintf(of,"%s",get_op(PCI(pc)));
670
671           if( PCI(pc)->num_ops == 2)
672             fprintf(of,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
673         }
674       }
675     }
676
677     {
678       pBranch *dpb = pc->to;   // debug
679       while(dpb) {
680         switch ( dpb->pc->type) {
681         case PC_OPCODE:
682           fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
683           break;
684         case PC_LABEL:
685           fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
686           break;
687         case PC_FUNCTION:
688           fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
689           break;
690         case PC_COMMENT:
691         case PC_WILD:
692           break;
693         }
694         dpb = dpb->next;
695       }
696       fprintf(of,"\n");
697     }
698
699     break;
700
701   case PC_LABEL:
702   default:
703     fprintf(of,"unknown pCode type %d\n",pc->type);
704   }
705
706 }
707
708 /*-----------------------------------------------------------------*/
709 /* pCodePrintFunction - prints function begin/end                  */
710 /*-----------------------------------------------------------------*/
711
712 static void pCodePrintFunction(FILE *of, pCode *pc)
713 {
714
715   if(!pc || !of)
716     return;
717
718   if( ((pCodeFunction *)pc)->modname) 
719     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
720
721   if(PCF(pc)->fname) {
722     pBranch *exits = pc->to;
723     int i=0;
724     fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
725     while(exits) {
726       i++;
727       exits = exits->next;
728     }
729     if(i) i--;
730     fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
731     
732   }else {
733     if(pc->from && 
734        pc->from->pc->type == PC_FUNCTION &&
735        PCF(pc->from->pc)->fname) 
736       fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
737     else
738       fprintf(of,"; exit point [can't find entry point]\n");
739   }
740 }
741 /*-----------------------------------------------------------------*/
742 /* pCodePrintLabel - prints label                                  */
743 /*-----------------------------------------------------------------*/
744
745 static void pCodePrintLabel(FILE *of, pCode *pc)
746 {
747
748   if(!pc || !of)
749     return;
750
751   fprintf(of,"_%05d_DS_:\n",((pCodeLabel *)pc)->key);
752
753 }
754
755 /*-----------------------------------------------------------------*/
756
757 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
758 {
759   pBranch *b;
760
761   if(!h)
762     return n;
763
764   b = h;
765   while(b->next)
766     b = b->next;
767
768   b->next = n;
769
770   return h;
771   
772 }  
773 /*-----------------------------------------------------------------*/
774 /* pBranchLink - given two pcodes, this function will link them    */
775 /*               together through their pBranches                  */
776 /*-----------------------------------------------------------------*/
777 static void pBranchLink(pCode *f, pCode *t)
778 {
779   pBranch *b;
780
781   // Declare a new branch object for the 'from' pCode.
782
783   _ALLOC(b,sizeof(pBranch));
784   b->pc = t;                    // The link to the 'to' pCode.
785   b->next = NULL;
786
787   f->to = pBranchAppend(f->to,b);
788
789   // Now do the same for the 'to' pCode.
790
791   _ALLOC(b,sizeof(pBranch));
792   b->pc = f;
793   b->next = NULL;
794
795   t->from = pBranchAppend(t->from,b);
796   
797 }
798
799 #if 0
800 /*-----------------------------------------------------------------*/
801 /* pBranchFind - find the pBranch in a pBranch chain that contains */
802 /*               a pCode                                           */
803 /*-----------------------------------------------------------------*/
804 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
805 {
806   while(pb) {
807
808     if(pb->pc == pc)
809       return pb;
810
811     pb = pb->next;
812   }
813
814   return NULL;
815 }
816
817 /*-----------------------------------------------------------------*/
818 /* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
819 /*-----------------------------------------------------------------*/
820 static void pCodeUnlink(pCode *pc)
821 {
822   pBranch *pb1,*pb2;
823   pCode *pc1;
824
825   if(!pc->prev || !pc->next) {
826     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
827     exit(1);
828   }
829
830   /* first remove the pCode from the chain */
831   pc->prev->next = pc->next;
832   pc->next->prev = pc->prev;
833
834   /* Now for the hard part... */
835
836   /* Remove the branches */
837
838   pb1 = pc->from;
839   while(pb1) {
840     pc1 = pb1->pc;    /* Get the pCode that branches to the
841                        * one we're unlinking */
842
843     /* search for the link back to this pCode (the one we're
844      * unlinking) */
845     if(pb2 = pBranchFind(pc1->to,pc)) {
846       pb2->pc = pc->to->pc;  // make the replacement
847
848       /* if the pCode we're unlinking contains multiple 'to'
849        * branches (e.g. this a skip instruction) then we need
850        * to copy these extra branches to the chain. */
851       if(pc->to->next)
852         pBranchAppend(pb2, pc->to->next);
853     }
854     
855     pb1 = pb1->next;
856   }
857
858
859 }
860 #endif
861 /*-----------------------------------------------------------------*/
862 /*-----------------------------------------------------------------*/
863 static void genericAnalyze(pCode *pc)
864 {
865   switch(pc->type) {
866   case PC_WILD:
867   case PC_COMMENT:
868     return;
869   case PC_LABEL:
870   case PC_FUNCTION:
871   case PC_OPCODE:
872     {
873       // Go through the pCodes that are in pCode chain and link
874       // them together through the pBranches. Note, the pCodes
875       // are linked together as a contiguous stream like the 
876       // assembly source code lines. The linking here mimics this
877       // except that comments are not linked in.
878       // 
879       pCode *npc = pc->next;
880       while(npc) {
881         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
882           pBranchLink(pc,npc);
883           return;
884         } else
885           npc = npc->next;
886       }
887     }
888   }
889 }
890
891 /*-----------------------------------------------------------------*/
892 /* findLabel - Search the pCode for a particular label             */
893 /*-----------------------------------------------------------------*/
894 pCode * findLabel(pCodeOpLabel *pcop_label)
895 {
896   pBlock *pb;
897   pCode  *pc;
898   pBranch *pbr;
899
900   if(!the_pFile)
901     return NULL;
902
903   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
904     for(pc = pb->pcHead; pc; pc = pc->next) {
905       if(pc->type == PC_LABEL) {
906         if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
907           return pc;
908       }
909       if(pc->type == PC_OPCODE) {
910         pbr = pc->label;
911         while(pbr) {
912           if(pbr->pc->type == PC_LABEL) {
913             if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
914               return pc;
915           }
916           pbr = pbr->next;
917         }
918       }
919
920     }
921   }
922
923   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
924   return NULL;
925 }
926
927 /*-----------------------------------------------------------------*/
928 /* findNextInstruction - given a pCode, find the next instruction  */
929 /*                       in the linked list                        */
930 /*-----------------------------------------------------------------*/
931 pCode * findNextInstruction(pCode *pc)
932 {
933
934   while(pc) {
935     if(pc->type == PC_OPCODE)
936       return pc;
937
938     pc = pc->next;
939   }
940
941   fprintf(stderr,"Couldn't find instruction\n");
942   return NULL;
943 }
944
945 /*-----------------------------------------------------------------*/
946 /* findFunctionEnd - given a pCode find the end of the function    */
947 /*                   that contains it     t                        */
948 /*-----------------------------------------------------------------*/
949 pCode * findFunctionEnd(pCode *pc)
950 {
951
952   while(pc) {
953     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
954       return pc;
955
956     pc = pc->next;
957   }
958
959   fprintf(stderr,"Couldn't find function end\n");
960   return NULL;
961 }
962
963 #if 0
964 /*-----------------------------------------------------------------*/
965 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
966 /*                instruction with which it is associated.         */
967 /*-----------------------------------------------------------------*/
968 static void AnalyzeLabel(pCode *pc)
969 {
970
971   pCodeUnlink(pc);
972
973 }
974 #endif
975
976 static void AnalyzeGOTO(pCode *pc)
977 {
978
979   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
980
981 }
982
983 static void AnalyzeSKIP(pCode *pc)
984 {
985
986   pBranchLink(pc,findNextInstruction(pc->next));
987   pBranchLink(pc,findNextInstruction(pc->next->next));
988
989 }
990
991 static void AnalyzeRETURN(pCode *pc)
992 {
993
994   //  branch_link(pc,findFunctionEnd(pc->next));
995
996 }
997
998
999 void optimizepBlock(pBlock *pb)
1000 {
1001   pCode *pc;
1002
1003   if(!pb)
1004     return;
1005
1006   for(pc = pb->pcHead; pc; pc = pc->next)
1007     pc->analyze(pc);
1008
1009 }
1010 /*-----------------------------------------------------------------*/
1011 /* pBlockMergeLabels - remove the pCode labels from the pCode      */
1012 /*                     chain and put them into pBranches that are  */
1013 /*                     associated with the appropriate pCode       */
1014 /*                     instructions.                               */
1015 /*-----------------------------------------------------------------*/
1016 void pBlockMergeLabels(pBlock *pb)
1017 {
1018   pBranch *pbr;
1019   pCode *pc, *pcnext=NULL;
1020
1021   if(!pb)
1022     return;
1023
1024   for(pc = pb->pcHead; pc; pc = pc->next) {
1025
1026     if(pc->type == PC_LABEL) {
1027       if( !(pcnext = findNextInstruction(pc)) ) 
1028         return;  // Couldn't find an instruction associated with this label
1029
1030       // Unlink the pCode label from it's pCode chain
1031       if(pc->prev) 
1032         pc->prev->next = pc->next;
1033       if(pc->next)
1034         pc->next->prev = pc->prev;
1035
1036       // And link it into the instruction's pBranch labels. (Note, since
1037       // it's possible to have multiple labels associated with one instruction
1038       // we must provide a means to accomodate the additional labels. Thus
1039       // the labels are placed into the singly-linked list "label" as 
1040       // opposed to being a single member of the pCodeInstruction.)
1041
1042       _ALLOC(pbr,sizeof(pBranch));
1043       pbr->pc = pc;
1044       pbr->next = NULL;
1045
1046       pcnext->label = pBranchAppend(pcnext->label,pbr);
1047     }
1048
1049   }
1050
1051 }
1052 /*-----------------------------------------------------------------*/
1053 /* AnalyzepCode - parse the pCode that has been generated and form */
1054 /*                all of the logical connections.                  */
1055 /*                                                                 */
1056 /* Essentially what's done here is that the pCode flow is          */
1057 /* determined.                                                     */
1058 /*-----------------------------------------------------------------*/
1059
1060 void AnalyzepCode(char dbName)
1061 {
1062   pBlock *pb;
1063   pCode *pc;
1064   pBranch *pbr;
1065
1066   if(!the_pFile)
1067     return;
1068
1069   fprintf(stderr," Analyzing pCode");
1070
1071   /* First, merge the labels with the instructions */
1072   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1073     if(pb->cmemmap->dbName == dbName)
1074       pBlockMergeLabels(pb);
1075   }
1076
1077   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1078     if(pb->cmemmap->dbName == dbName)
1079       optimizepBlock(pb);
1080   }
1081
1082   /* Now build the call tree.
1083      First we examine all of the pCodes for functions.
1084      
1085    */
1086   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1087     if(pb->cmemmap->dbName == dbName) {
1088       pCode *pc_fstart=NULL;
1089       for(pc = pb->pcHead; pc; pc = pc->next) {
1090         if(pc->type == PC_FUNCTION) {
1091           if (PCF(pc)->fname) {
1092             // Found the beginning of a function.
1093             _ALLOC(pbr,sizeof(pBranch));
1094             pbr->pc = pc_fstart = pc;
1095             pbr->next = NULL;
1096
1097             the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
1098           } else {
1099             // Found an exit point in a function, e.g. return
1100             // (Note, there may be more than one return per function)
1101             if(pc_fstart)
1102               pBranchLink(pc_fstart, pc);
1103           }
1104         }
1105       }
1106     }
1107   }
1108 }
1109
1110 /*-----------------------------------------------------------------*/
1111 /* ispCodeFunction - returns true if *pc is the pCode of a         */
1112 /*                   function                                      */
1113 /*-----------------------------------------------------------------*/
1114 bool ispCodeFunction(pCode *pc)
1115 {
1116
1117   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
1118     return 1;
1119
1120   return 0;
1121 }
1122
1123 void printCallTree(FILE *of)
1124 {
1125   pBranch *pbr;
1126
1127   if(!the_pFile)
1128     return;
1129
1130   if(!of)
1131     of = stderr;
1132
1133   pbr = the_pFile->functions;
1134
1135   fprintf(of,"Call Tree\n");
1136   while(pbr) {
1137     if(pbr->pc) {
1138       pCode *pc = pbr->pc;
1139       if(!ispCodeFunction(pc))
1140         fprintf(of,"bug in call tree");
1141
1142
1143       fprintf(of,"Function: %s\n", PCF(pc)->fname);
1144
1145       while(pc->next && !ispCodeFunction(pc->next)) {
1146         pc = pc->next;
1147         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
1148           fprintf(of,"\t%s\n",get_op(PCI(pc)));
1149       }
1150     }
1151
1152     pbr = pbr->next;
1153   }
1154 }
1155 #if 0
1156 /*-----------------------------------------------------------------*/
1157 /* pCodePeep */
1158 /*-----------------------------------------------------------------*/
1159 int pCodePeepCompare(pCode *pc, pCodePeep *pcp)
1160 {
1161   pCode *pcfrom,*pcto;
1162
1163   pcfrom = pc;
1164   for( pcto=pcp->target; pcto; pcto=pcto->next) {
1165
1166     pcfrom = findNextInstruction(pcfrom);
1167
1168     if( pcfrom &&  
1169         (PCI(pcfrom)->op == PCI(pcto)->op || 
1170          PCI(pcto)->op == POC_WILD))
1171       continue;
1172     return 0;
1173   }
1174   return 0;
1175 }
1176
1177 /*-----------------------------------------------------------------*/
1178 /* pCodePeep */
1179 /*-----------------------------------------------------------------*/
1180 void pCodePeepSearch(pCodePeep *snippet)
1181 {
1182   pBlock *pb;
1183   pCode *pc;
1184
1185   if(!the_pFile)
1186     return;
1187
1188   /* compare the chain to the pCode that we've 
1189      got so far. If a match is found, then replace
1190      the pCode chain.
1191   */
1192   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1193     for(pc = pb->pcHead; pc; pc = pc->next) {
1194       pCodePeepCompare(pc,snippet);
1195     }
1196   }
1197
1198 }
1199 #endif
1200
1201 #if 0
1202 pBlock *pBlockAppend(pBlock *pb1, pBlock *pb2)
1203 {
1204   pBlock *pb;
1205
1206   if(!pb1->tail)
1207     return pb2;
1208
1209   pb = pb1->tail;
1210
1211   pb2->head = pb1;
1212   pb2->tail = NULL;
1213   pb1->tail = pb2;
1214
1215 }
1216
1217 #endif
1218
1219 void pCodePeepInit(void)
1220 {
1221   pBlock *pb;
1222   //  pCode *pc;
1223
1224   if(!peepSnippets)
1225     _ALLOC(peepSnippets,sizeof(pBlock));
1226
1227
1228   pb = newpCodeChain(NULL,newpCodeCharP("; Starting pCode block"));
1229
1230   if(!peepSnippets->next)
1231     peepSnippets->next = pb;
1232   else {
1233     peepSnippets->next->next = pb;
1234     pb->prev = peepSnippets->next;
1235   }
1236   // now create some sample peep pcodes
1237
1238   addpCode2pBlock( pb, newpCode(POC_MOVWF, newpCodeOpWild(1)) );
1239   addpCode2pBlock( pb, newpCode(POC_MOVFW, newpCodeOpWild(1)) );
1240   // addpBlock(pb);
1241
1242 }