Changed name of unlink function for cygnus and MSVC
[fw/sdcc] / src / pic / pcode.c
1 /*-------------------------------------------------------------------------
2
3    pcode.c - 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
26
27 #include "pcode.h"
28 #include "ralloc.h"
29 // Eventually this will go into device dependent files:
30 pCodeOpReg pc_status    = {{PO_STATUS,  "STATUS"}, -1, NULL,NULL};
31 pCodeOpReg pc_indf      = {{PO_INDF,    "INDF"}, -1, NULL,NULL};
32 pCodeOpReg pc_fsr       = {{PO_FSR,     "FSR"}, -1, NULL,NULL};
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 /*                      Forward declarations                    */
73 /****************************************************************/
74
75 static void unlinkPC(pCode *pc);
76 static void genericAnalyze(pCode *pc);
77 static void AnalyzeGOTO(pCode *pc);
78 static void AnalyzeSKIP(pCode *pc);
79 static void AnalyzeRETURN(pCode *pc);
80
81 static void genericDestruct(pCode *pc);
82 static void genericPrint(FILE *of,pCode *pc);
83
84 static void pCodePrintLabel(FILE *of, pCode *pc);
85 static void pCodePrintFunction(FILE *of, pCode *pc);
86 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
87 static char *get_op( pCodeInstruction *pcc);
88 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
89 int pCodePeepMatchRule(pCode *pc);
90
91
92 char *Safe_strdup(char *str)
93 {
94   char *copy;
95
96   if(!str)
97     return NULL;
98
99   copy = strdup(str);
100   if(!copy) {
101     fprintf(stderr, "out of memory %s,%d\n",__FUNCTION__,__LINE__);
102     exit(1);
103   }
104
105   return copy;
106     
107 }
108
109 void  pCodeInitRegisters(void)
110 {
111
112   pc_fsr.rIdx = 4;
113   pc_fsr.r = pic14_regWithIdx(4);
114
115 }
116
117 char getpBlock_dbName(pBlock *pb)
118 {
119   if(!pb)
120     return 0;
121
122   if(pb->cmemmap)
123     return pb->cmemmap->dbName;
124
125   return pb->dbName;
126 }
127 /*-----------------------------------------------------------------*/
128 /* movepBlock2Head - given the dbname of a pBlock, move all        */
129 /*                   instances to the front of the doubly linked   */
130 /*                   list of pBlocks                               */
131 /*-----------------------------------------------------------------*/
132
133 void movepBlock2Head(char dbName)
134 {
135   pBlock *pb;
136
137   pb = the_pFile->pbHead;
138
139   while(pb) {
140
141     if(getpBlock_dbName(pb) == dbName) {
142       pBlock *pbn = pb->next;
143       pb->next = the_pFile->pbHead;
144       the_pFile->pbHead->prev = pb;
145       the_pFile->pbHead = pb;
146
147       if(pb->prev)
148         pb->prev->next = pbn;
149
150       // If the pBlock that we just moved was the last
151       // one in the link of all of the pBlocks, then we
152       // need to point the tail to the block just before
153       // the one we moved.
154       // Note: if pb->next is NULL, then pb must have 
155       // been the last pBlock in the chain.
156
157       if(pbn)
158         pbn->prev = pb->prev;
159       else
160         the_pFile->pbTail = pb->prev;
161
162       pb = pbn;
163
164     } else
165       pb = pb->next;
166
167   }
168
169 }
170
171 void copypCode(FILE *of, char dbName)
172 {
173   pBlock *pb;
174
175   if(!of || !the_pFile)
176     return;
177
178   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
179     if(getpBlock_dbName(pb) == dbName)
180       printpBlock(of,pb);
181   }
182
183 }
184 void pcode_test(void)
185 {
186
187   printf("pcode is alive!\n");
188
189   if(the_pFile) {
190
191     pBlock *pb;
192     FILE *pFile;
193     char buffer[100];
194
195     /* create the file name */
196     strcpy(buffer,srcFileName);
197     strcat(buffer,".p");
198
199     if( !(pFile = fopen(buffer, "w" ))) {
200       werror(E_FILE_OPEN_ERR,buffer);
201       exit(1);
202     }
203
204     fprintf(pFile,"pcode dump\n\n");
205
206     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
207       fprintf(pFile,"\n\tNew pBlock\n\n");
208       if(pb->cmemmap)
209         fprintf(pFile,"%s",pb->cmemmap->sname);
210       else
211         fprintf(pFile,"internal pblock");
212
213       fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
214       printpBlock(pFile,pb);
215     }
216   }
217 }
218 static int RegCond(pCodeOp *pcop)
219 {
220
221   if(!pcop)
222     return 0;
223
224   if(pcop->type == PO_BIT  && !strcmp(pcop->name, pc_status.pcop.name)) {
225     switch(PCOB(pcop)->bit) {
226     case PIC_C_BIT:
227       return PCC_C;
228     case PIC_DC_BIT:
229         return PCC_DC;
230     case PIC_Z_BIT:
231       return PCC_Z;
232     }
233
234   }
235
236   return 0;
237 }
238
239 /*-----------------------------------------------------------------*/
240 /* newpCode - create and return a newly initialized pCode          */
241 /*                                                                 */
242 /*  fixme - rename this                                            */
243 /*                                                                 */
244 /* The purpose of this routine is to create a new Instruction      */
245 /* pCode. This is called by gen.c while the assembly code is being */
246 /* generated.                                                      */
247 /*                                                                 */
248 /* Inouts:                                                         */
249 /*  PIC_OPCODE op - the assembly instruction we wish to create.    */
250 /*                  (note that the op is analogous to but not the  */
251 /*                  same thing as the opcode of the instruction.)  */
252 /*  pCdoeOp *pcop - pointer to the operand of the instruction.     */
253 /*                                                                 */
254 /* Outputs:                                                        */
255 /*  a pointer to the new malloc'd pCode is returned.               */
256 /*                                                                 */
257 /*                                                                 */
258 /*                                                                 */
259 /*-----------------------------------------------------------------*/
260 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
261 {
262   pCodeInstruction *pci ;
263     
264
265   pci = Safe_calloc(1, sizeof(pCodeInstruction));
266
267   pci->pc.analyze  = genericAnalyze;       // pointers to the generic functions, it
268   pci->pc.destruct = genericDestruct;      // doesn't hurt to think about C++ virtual
269   pci->pc.print    = genericPrint;         // functions here.
270   pci->pc.type = PC_OPCODE;                // 
271   pci->op = op;                            // the "opcode" for the instruction.
272   pci->pc.prev = pci->pc.next = NULL;      // The pCode gets linked in later
273   pci->pcop = pcop;                        // The operand of the instruction
274   pci->dest = 0;                           // e.g. W or F 
275   pci->bit_inst = 0;                       // e.g. btfxx instructions
276   pci->num_ops = 2;                        // Most instructions have two ops...
277   pci->inCond = pci->outCond = PCC_NONE;   /* input/output conditions. This is used during
278                                             * optimization to ascertain instruction dependencies.
279                                             * For example, if an instruction affects the Z bit,
280                                             * then the output condition for this instruction
281                                             * is "z bit is affected". The "conditions" are bit
282                                             * constants defined in pcode.h. */
283   pci->pc.from = pci->pc.to = NULL;        // Flow linkages are defined later
284   pci->pc.label = NULL;                    // Labels get merged into instructions here.
285   pci->pc.pb = NULL;                       // The pBlock to which this instruction belongs
286
287   if(pcop && pcop->name)
288     printf("newpCode  operand name %s\n",pcop->name);
289
290   // The most pic dependent portion of the pCode logic:
291   switch(op) { 
292
293   case POC_ANDLW:
294     pci->inCond   = PCC_W;
295     pci->outCond  = PCC_W | PCC_Z;
296     pci->mnemonic = scpANDLW;
297     pci->num_ops  = 1;
298     break;
299   case POC_ANDWF:
300     pci->dest = 1;
301     pci->inCond   = PCC_W | PCC_REGISTER;
302     pci->outCond  = PCC_REGISTER | PCC_Z;
303     pci->mnemonic = scpANDWF;
304     break;
305   case POC_ANDFW:
306     pci->inCond   = PCC_W | PCC_REGISTER;
307     pci->outCond  = PCC_W | PCC_Z;
308     pci->mnemonic = scpANDWF;
309     break;
310
311   case POC_ADDLW:
312     pci->inCond   = PCC_W;
313     pci->outCond  = PCC_W | PCC_Z | PCC_C | PCC_DC;
314     pci->mnemonic = scpADDLW;
315     pci->num_ops = 1;
316     break;
317   case POC_ADDWF:
318     pci->dest     = 1;
319     pci->inCond   = PCC_W | PCC_REGISTER;
320     pci->outCond  = PCC_REGISTER | PCC_Z | PCC_C | PCC_DC;
321     pci->mnemonic = scpADDWF;
322     break;
323   case POC_ADDFW:
324     pci->inCond   = PCC_W | PCC_REGISTER;
325     pci->outCond  = PCC_W | PCC_Z | PCC_C | PCC_DC;
326     pci->mnemonic = scpADDWF;
327     break;
328
329   case POC_BCF:
330     pci->bit_inst = 1;
331     pci->mnemonic = scpBCF;
332     pci->outCond   = RegCond(pcop);
333     break;
334   case POC_BSF:
335     pci->bit_inst = 1;
336     pci->mnemonic = scpBSF;
337     pci->outCond   = RegCond(pcop);
338     break;
339   case POC_BTFSC:
340     pci->bit_inst = 1;
341     pci->mnemonic = scpBTFSC;
342     pci->pc.analyze = AnalyzeSKIP;
343     pci->inCond   = RegCond(pcop);
344     break;
345   case POC_BTFSS:
346     pci->bit_inst = 1;
347     pci->mnemonic = scpBTFSS;
348     pci->pc.analyze = AnalyzeSKIP;
349     pci->inCond   = RegCond(pcop);
350     break;
351   case POC_CALL:
352     pci->num_ops = 1;
353     pci->mnemonic = scpCALL;
354     break;
355   case POC_COMF:
356     pci->mnemonic = scpCOMF;
357     break;
358   case POC_CLRF:
359     pci->num_ops = 1;
360     pci->mnemonic = scpCLRF;
361     break;
362   case POC_CLRW:
363     pci->num_ops = 0;
364     pci->mnemonic = scpCLRW;
365     break;
366   case POC_DECF:
367     pci->dest = 1;
368   case POC_DECFW:
369     pci->mnemonic = scpDECF;
370     break;
371   case POC_DECFSZ:
372     pci->dest = 1;
373   case POC_DECFSZW:
374     pci->mnemonic = scpDECFSZ;
375     pci->pc.analyze = AnalyzeSKIP;
376     break;
377   case POC_GOTO:
378     pci->num_ops = 1;
379     pci->mnemonic = scpGOTO;
380     pci->pc.analyze = AnalyzeGOTO;
381     break;
382   case POC_INCF:
383     pci->dest = 1;
384   case POC_INCFW:
385     pci->mnemonic = scpINCF;
386     break;
387   case POC_INCFSZ:
388     pci->dest = 1;
389   case POC_INCFSZW:
390     pci->mnemonic = scpINCFSZ;
391     pci->pc.analyze = AnalyzeSKIP;
392     break;
393   case POC_IORLW:
394     pci->num_ops = 1;
395     pci->mnemonic = scpIORLW;
396     break;
397   case POC_IORWF:
398     pci->dest = 1;
399   case POC_IORFW:
400     pci->mnemonic = scpIORWF;
401     break;
402   case POC_MOVF:
403     pci->dest = 1;
404   case POC_MOVFW:
405     pci->mnemonic = scpMOVF;
406     break;
407   case POC_MOVLW:
408     pci->num_ops = 1;
409     pci->mnemonic = scpMOVLW;
410     break;
411   case POC_MOVWF:
412     pci->num_ops = 1;
413     pci->mnemonic = scpMOVWF;
414     break;
415   case POC_NEGF:
416     pci->mnemonic = scpNEGF;
417     break;
418   case POC_RETLW:
419     pci->num_ops = 1;
420     pci->mnemonic = scpRETLW;
421     pci->pc.analyze = AnalyzeRETURN;
422     break;
423   case POC_RETURN:
424     pci->num_ops = 0;
425     pci->mnemonic = scpRETURN;
426     pci->pc.analyze = AnalyzeRETURN;
427     break;
428   case POC_SUBLW:
429     pci->mnemonic = scpSUBLW;
430     pci->num_ops = 1;
431     break;
432   case POC_SUBWF:
433     pci->dest = 1;
434   case POC_SUBFW:
435     pci->mnemonic = scpSUBWF;
436     break;
437   case POC_TRIS:
438     pci->mnemonic = scpTRIS;
439     break;
440   case POC_XORLW:
441     pci->num_ops = 1;
442     pci->mnemonic = scpXORLW;
443     break;
444   case POC_XORWF:
445     pci->dest = 1;
446   case POC_XORFW:
447     pci->mnemonic = scpXORWF;
448     break;
449
450   default:
451     pci->pc.print = genericPrint;
452   }
453    
454   return (pCode *)pci;
455 }       
456
457 /*-----------------------------------------------------------------*/
458 /* newpCodeWild - create a "wild" as in wild card pCode            */
459 /*                                                                 */
460 /* Wild pcodes are used during the peep hole optimizer to serve    */
461 /* as place holders for any instruction. When a snippet of code is */
462 /* compared to a peep hole rule, the wild card opcode will match   */
463 /* any instruction. However, the optional operand and label are    */
464 /* additional qualifiers that must also be matched before the      */
465 /* line (of assembly code) is declared matched. Note that the      */
466 /* operand may be wild too.                                        */
467 /*                                                                 */
468 /*-----------------------------------------------------------------*/
469
470 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
471 {
472
473   pCodeWild *pcw;
474     
475   pcw = Safe_calloc(1,sizeof(pCodeWild));
476
477   pcw->pc.type = PC_WILD;
478   pcw->pc.prev = pcw->pc.next = NULL;
479   pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
480   pcw->pc.pb = NULL;
481
482   pcw->pc.analyze = genericAnalyze;
483   pcw->pc.destruct = genericDestruct;
484   pcw->pc.print = genericPrint;
485
486   pcw->id = pCodeID;
487   pcw->operand = optional_operand;
488   pcw->label   = optional_label;
489
490   return ( (pCode *)pcw);
491   
492 }
493
494 /*-----------------------------------------------------------------*/
495 /* newPcodeCharP - create a new pCode from a char string           */
496 /*-----------------------------------------------------------------*/
497
498 pCode *newpCodeCharP(char *cP)
499 {
500
501   pCodeComment *pcc ;
502     
503   pcc = Safe_calloc(1,sizeof(pCodeComment));
504
505   pcc->pc.type = PC_COMMENT;
506   pcc->pc.prev = pcc->pc.next = NULL;
507   pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
508   pcc->pc.pb = NULL;
509
510   pcc->pc.analyze = genericAnalyze;
511   pcc->pc.destruct = genericDestruct;
512   pcc->pc.print = genericPrint;
513
514   pcc->comment = Safe_strdup(cP);
515
516   return ( (pCode *)pcc);
517
518 }
519
520 /*-----------------------------------------------------------------*/
521 /* newpCodeGLabel - create a new global label                      */
522 /*-----------------------------------------------------------------*/
523
524
525 pCode *newpCodeFunction(char *mod,char *f)
526 {
527   pCodeFunction *pcf;
528
529   _ALLOC(pcf,sizeof(pCodeFunction));
530
531   pcf->pc.type = PC_FUNCTION;
532   pcf->pc.prev = pcf->pc.next = NULL;
533   pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
534   pcf->pc.pb = NULL;
535
536   pcf->pc.analyze = genericAnalyze;
537   pcf->pc.destruct = genericDestruct;
538   pcf->pc.print = pCodePrintFunction;
539
540   if(mod) {
541     _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
542     strcpy(pcf->modname,mod);
543   } else
544     pcf->modname = NULL;
545
546   if(f) {
547     _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
548     strcpy(pcf->fname,f);
549   } else
550     pcf->fname = NULL;
551
552   return ( (pCode *)pcf);
553
554 }
555
556
557 pCode *newpCodeLabel(int key)
558 {
559
560   char *s = buffer;
561   pCodeLabel *pcl;
562     
563   pcl = Safe_calloc(1,sizeof(pCodeLabel) );
564
565   pcl->pc.type = PC_LABEL;
566   pcl->pc.prev = pcl->pc.next = NULL;
567   pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
568   pcl->pc.pb = NULL;
569
570   pcl->pc.analyze = genericAnalyze;
571   pcl->pc.destruct = genericDestruct;
572   pcl->pc.print = pCodePrintLabel;
573
574   pcl->key = key;
575
576   if(key>0) {
577     sprintf(s,"_%05d_DS_",key);
578     pcl->label = Safe_strdup(s);
579   } else
580     pcl->label = NULL;
581
582   return ( (pCode *)pcl);
583
584 }
585 pCode *newpCodeLabelStr(char *str)
586 {
587   pCode *pc = newpCodeLabel(-1);
588
589   PCL(pc)->label = Safe_strdup(str);
590
591   return pc;
592 }
593
594 /*-----------------------------------------------------------------*/
595 /* newpBlock - create and return a pointer to a new pBlock         */
596 /*-----------------------------------------------------------------*/
597 pBlock *newpBlock(void)
598 {
599
600   pBlock *PpB;
601
602   _ALLOC(PpB,sizeof(pBlock));
603   PpB->next = PpB->prev = NULL;
604
605   PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
606   PpB->registers = NULL;
607   PpB->visited = 0;
608
609   return PpB;
610
611 }
612
613 /*-----------------------------------------------------------------*/
614 /* newpCodeChain - create a new chain of pCodes                    */
615 /*-----------------------------------------------------------------*
616  *
617  *  This function will create a new pBlock and the pointer to the
618  *  pCode that is passed in will be the first pCode in the block.
619  *-----------------------------------------------------------------*/
620
621
622 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
623 {
624
625   pBlock *pB  = newpBlock();
626
627   pB->pcHead  = pB->pcTail = pc;
628   pB->cmemmap = cm;
629   pB->dbName  = c;
630
631   return pB;
632 }
633
634 /*-----------------------------------------------------------------*/
635 /*-----------------------------------------------------------------*/
636
637 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
638 {
639   pCodeOp *pcop;
640
641   pcop = Safe_calloc(1,sizeof(pCodeOp) );
642   pcop->type = type;
643   pcop->name = Safe_strdup(name);   
644
645   return pcop;
646 }
647
648 /*-----------------------------------------------------------------*/
649 /* newpCodeOpLabel - Create a new label given the key              */
650 /*  Note, a negative key means that the label is part of wild card */
651 /*  (and hence a wild card label) used in the pCodePeep            */
652 /*   optimizations).                                               */
653 /*-----------------------------------------------------------------*/
654
655 pCodeOp *newpCodeOpLabel(int key)
656 {
657   char *s = buffer;
658   pCodeOp *pcop;
659
660   pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
661   pcop->type = PO_LABEL;
662
663   if(key>0) {
664     sprintf(s,"_%05d_DS_",key);
665     pcop->name = Safe_strdup(s);
666   } else
667     pcop->name = NULL;
668
669   ((pCodeOpLabel *)pcop)->key = key;
670
671   return pcop;
672 }
673
674 pCodeOp *newpCodeOpLit(int lit)
675 {
676   char *s = buffer;
677   pCodeOp *pcop;
678
679
680   _ALLOC(pcop,sizeof(pCodeOpLit) );
681   pcop->type = PO_LITERAL;
682   sprintf(s,"0x%02x",lit);
683   _ALLOC_ATOMIC(pcop->name,strlen(s)+1);
684   strcpy(pcop->name,s);
685   ((pCodeOpLit *)pcop)->lit = lit;
686
687   return pcop;
688 }
689
690 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
691 {
692   char *s = buffer;
693   pCodeOp *pcop;
694
695
696   if(!pcp || !subtype) {
697     fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
698     exit(1);
699   }
700
701   pcop = Safe_calloc(1,sizeof(pCodeOpWild));
702   pcop->type = PO_WILD;
703   sprintf(s,"%%%d",id);
704   pcop->name = Safe_strdup(s);
705
706   PCOW(pcop)->id = id;
707   PCOW(pcop)->pcp = pcp;
708   PCOW(pcop)->subtype = subtype;
709   PCOW(pcop)->matched = NULL;
710
711   return pcop;
712 }
713
714 pCodeOp *newpCodeOpBit(char *s, int bit)
715 {
716   pCodeOp *pcop;
717
718   _ALLOC(pcop,sizeof(pCodeOpBit) );
719   pcop->type = PO_BIT;
720   pcop->name = Safe_strdup(s);   
721   PCOB(pcop)->bit = bit;
722   if(bit>=0)
723     PCOB(pcop)->inBitSpace = 1;
724   else
725     PCOB(pcop)->inBitSpace = 0;
726
727   return pcop;
728 }
729
730 /*-----------------------------------------------------------------*/
731 /* addpCode2pBlock - place the pCode into the pBlock linked list   */
732 /*-----------------------------------------------------------------*/
733 void addpCode2pBlock(pBlock *pb, pCode *pc)
734 {
735
736   pb->pcTail->next = pc;
737   pc->prev = pb->pcTail;
738   pc->next = NULL;
739   pc->pb = pb;
740   pb->pcTail = pc;
741 }
742
743 /*-----------------------------------------------------------------*/
744 /* addpBlock - place a pBlock into the pFile                       */
745 /*-----------------------------------------------------------------*/
746 void addpBlock(pBlock *pb)
747 {
748
749   if(!the_pFile) {
750     /* First time called, we'll pass through here. */
751     _ALLOC(the_pFile,sizeof(the_pFile));
752     the_pFile->pbHead = the_pFile->pbTail = pb;
753     the_pFile->functions = NULL;
754     return;
755   }
756
757   the_pFile->pbTail->next = pb;
758   pb->prev = the_pFile->pbTail;
759   pb->next = NULL;
760   the_pFile->pbTail = pb;
761 }
762
763 /*-----------------------------------------------------------------*/
764 /* printpCode - write the contents of a pCode to a file            */
765 /*-----------------------------------------------------------------*/
766 void printpCode(FILE *of, pCode *pc)
767 {
768
769   if(!pc || !of)
770     return;
771
772   if(pc->print) {
773     pc->print(of,pc);
774     return;
775   }
776
777   fprintf(of,"warning - unable to print pCode\n");
778 }
779
780 /*-----------------------------------------------------------------*/
781 /* printpBlock - write the contents of a pBlock to a file          */
782 /*-----------------------------------------------------------------*/
783 void printpBlock(FILE *of, pBlock *pb)
784 {
785   pCode *pc;
786
787   if(!pb)
788     return;
789
790   if(!of)
791     of = stderr;
792
793   for(pc = pb->pcHead; pc; pc = pc->next)
794     printpCode(of,pc);
795
796 }
797
798 /*-----------------------------------------------------------------*/
799 /*                                                                 */
800 /*       pCode processing                                          */
801 /*                                                                 */
802 /*                                                                 */
803 /*                                                                 */
804 /*-----------------------------------------------------------------*/
805
806 static void unlinkPC(pCode *pc)
807 {
808   if(pc  && pc->prev && pc->next) {
809
810     pc->prev->next = pc->next;
811     pc->next->prev = pc->prev;
812   }
813 }
814 static void genericDestruct(pCode *pc)
815 {
816   unlinkPC(pc);
817
818   fprintf(stderr,"warning, calling default pCode destructor\n");
819   free(pc);
820 }
821
822
823 void pBlockRegs(FILE *of, pBlock *pb)
824 {
825
826   regs  *r;
827
828   r = setFirstItem(pb->registers);
829   while (r) {
830     fprintf(of,"   %s\n",r->name);
831     r = setNextItem(pb->registers);
832   }
833 }
834
835
836 static char *get_op( pCodeInstruction *pcc)
837 {
838   regs *r;
839
840   if(pcc && pcc->pcop) {
841
842
843     switch(pcc->pcop->type) {
844
845     case PO_FSR:
846     case PO_GPR_TEMP:
847       r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
848       fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
849       pBlockRegs(stderr,pcc->pc.pb);
850       return r->name;
851
852     default:
853       if  (pcc->pcop->name)
854         return pcc->pcop->name;
855
856     }
857   }
858
859   return "NO operand";
860 }
861
862 /*-----------------------------------------------------------------*/
863 /*-----------------------------------------------------------------*/
864 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
865 {
866
867   fprintf(of,"pcodeopprint\n");
868 }
869
870 /*-----------------------------------------------------------------*/
871 /* genericPrint - the contents of a pCode to a file                */
872 /*-----------------------------------------------------------------*/
873 static void genericPrint(FILE *of, pCode *pc)
874 {
875
876   if(!pc || !of)
877     return;
878
879   switch(pc->type) {
880   case PC_COMMENT:
881     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
882     break;
883
884   case PC_OPCODE:
885     // If the opcode has a label, print that first
886     {
887       pBranch *pbl = pc->label;
888       while(pbl) {
889         if(pbl->pc->type == PC_LABEL)
890           pCodePrintLabel(of, pbl->pc);
891         pbl = pbl->next;
892       }
893     }
894
895     fprintf(of, "\t%s\t", PCI(pc)->mnemonic);
896     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
897
898       if(PCI(pc)->bit_inst) {
899         if(PCI(pc)->pcop->type == PO_BIT) {
900           if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
901             fprintf(of,"(%s >> 3), (%s & 7)", 
902                     PCI(pc)->pcop->name ,
903                     PCI(pc)->pcop->name );
904           else
905             fprintf(of,"%s,%d", get_op(PCI(pc)), (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
906         } else
907           fprintf(of,"%s,0 ; ?bug", get_op(PCI(pc)));
908         //PCI(pc)->pcop->t.bit );
909       } else {
910
911         if(PCI(pc)->pcop->type == PO_BIT) {
912           if( PCI(pc)->num_ops == 2)
913             fprintf(of,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
914           else
915             fprintf(of,"(1 << (%s & 7))",get_op(PCI(pc)));
916
917 /*
918           if( PCI(pc)->num_ops == 2)
919             fprintf(of,"(%s >> 3),%c",PCI(pc)->pcop->name,((PCI(pc)->dest) ? 'F':'W'));
920           else
921             fprintf(of,"(1 << (%s & 7))",PCI(pc)->pcop->name);
922 */
923         }else {
924           fprintf(of,"%s",get_op(PCI(pc)));
925
926           if( PCI(pc)->num_ops == 2)
927             fprintf(of,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
928         }
929       }
930     }
931
932     {
933       pBranch *dpb = pc->to;   // debug
934       while(dpb) {
935         switch ( dpb->pc->type) {
936         case PC_OPCODE:
937           fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
938           break;
939         case PC_LABEL:
940           fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
941           break;
942         case PC_FUNCTION:
943           fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
944           break;
945         case PC_COMMENT:
946         case PC_WILD:
947           break;
948         }
949         dpb = dpb->next;
950       }
951       fprintf(of,"\n");
952     }
953
954     break;
955
956   case PC_WILD:
957     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
958     if(PCW(pc)->operand) {
959       fprintf(of,";\toperand  ");
960       pCodeOpPrint(of,PCW(pc)->operand );
961     }
962     break;
963
964   case PC_LABEL:
965   default:
966     fprintf(of,"unknown pCode type %d\n",pc->type);
967   }
968
969 }
970
971 /*-----------------------------------------------------------------*/
972 /* pCodePrintFunction - prints function begin/end                  */
973 /*-----------------------------------------------------------------*/
974
975 static void pCodePrintFunction(FILE *of, pCode *pc)
976 {
977
978   if(!pc || !of)
979     return;
980
981   if( ((pCodeFunction *)pc)->modname) 
982     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
983
984   if(PCF(pc)->fname) {
985     pBranch *exits = pc->to;
986     int i=0;
987     fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
988     while(exits) {
989       i++;
990       exits = exits->next;
991     }
992     //if(i) i--;
993     fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
994     
995   }else {
996     if(pc->from && 
997        pc->from->pc->type == PC_FUNCTION &&
998        PCF(pc->from->pc)->fname) 
999       fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1000     else
1001       fprintf(of,"; exit point [can't find entry point]\n");
1002   }
1003 }
1004 /*-----------------------------------------------------------------*/
1005 /* pCodePrintLabel - prints label                                  */
1006 /*-----------------------------------------------------------------*/
1007
1008 static void pCodePrintLabel(FILE *of, pCode *pc)
1009 {
1010
1011   if(!pc || !of)
1012     return;
1013
1014   if(PCL(pc)->label) 
1015     fprintf(of,"%s\n",PCL(pc)->label);
1016   else if (PCL(pc)->key >=0) 
1017     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1018   else
1019     fprintf(of,";wild card label\n");
1020
1021 }
1022 /*-----------------------------------------------------------------*/
1023
1024 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1025 {
1026   pBranch *b;
1027
1028   if(!h)
1029     return n;
1030
1031   b = h;
1032   while(b->next)
1033     b = b->next;
1034
1035   b->next = n;
1036
1037   return h;
1038   
1039 }  
1040 /*-----------------------------------------------------------------*/
1041 /* pBranchLink - given two pcodes, this function will link them    */
1042 /*               together through their pBranches                  */
1043 /*-----------------------------------------------------------------*/
1044 static void pBranchLink(pCode *f, pCode *t)
1045 {
1046   pBranch *b;
1047
1048   // Declare a new branch object for the 'from' pCode.
1049
1050   _ALLOC(b,sizeof(pBranch));
1051   b->pc = t;                    // The link to the 'to' pCode.
1052   b->next = NULL;
1053
1054   f->to = pBranchAppend(f->to,b);
1055
1056   // Now do the same for the 'to' pCode.
1057
1058   _ALLOC(b,sizeof(pBranch));
1059   b->pc = f;
1060   b->next = NULL;
1061
1062   t->from = pBranchAppend(t->from,b);
1063   
1064 }
1065
1066 #if 0
1067 /*-----------------------------------------------------------------*/
1068 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1069 /*               a pCode                                           */
1070 /*-----------------------------------------------------------------*/
1071 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1072 {
1073   while(pb) {
1074
1075     if(pb->pc == pc)
1076       return pb;
1077
1078     pb = pb->next;
1079   }
1080
1081   return NULL;
1082 }
1083
1084 /*-----------------------------------------------------------------*/
1085 /* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
1086 /*-----------------------------------------------------------------*/
1087 static void pCodeUnlink(pCode *pc)
1088 {
1089   pBranch *pb1,*pb2;
1090   pCode *pc1;
1091
1092   if(!pc->prev || !pc->next) {
1093     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1094     exit(1);
1095   }
1096
1097   /* first remove the pCode from the chain */
1098   pc->prev->next = pc->next;
1099   pc->next->prev = pc->prev;
1100
1101   /* Now for the hard part... */
1102
1103   /* Remove the branches */
1104
1105   pb1 = pc->from;
1106   while(pb1) {
1107     pc1 = pb1->pc;    /* Get the pCode that branches to the
1108                        * one we're unlinking */
1109
1110     /* search for the link back to this pCode (the one we're
1111      * unlinking) */
1112     if(pb2 = pBranchFind(pc1->to,pc)) {
1113       pb2->pc = pc->to->pc;  // make the replacement
1114
1115       /* if the pCode we're unlinking contains multiple 'to'
1116        * branches (e.g. this a skip instruction) then we need
1117        * to copy these extra branches to the chain. */
1118       if(pc->to->next)
1119         pBranchAppend(pb2, pc->to->next);
1120     }
1121     
1122     pb1 = pb1->next;
1123   }
1124
1125
1126 }
1127 #endif
1128 /*-----------------------------------------------------------------*/
1129 /*-----------------------------------------------------------------*/
1130 static void genericAnalyze(pCode *pc)
1131 {
1132   switch(pc->type) {
1133   case PC_WILD:
1134   case PC_COMMENT:
1135     return;
1136   case PC_LABEL:
1137   case PC_FUNCTION:
1138   case PC_OPCODE:
1139     {
1140       // Go through the pCodes that are in pCode chain and link
1141       // them together through the pBranches. Note, the pCodes
1142       // are linked together as a contiguous stream like the 
1143       // assembly source code lines. The linking here mimics this
1144       // except that comments are not linked in.
1145       // 
1146       pCode *npc = pc->next;
1147       while(npc) {
1148         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1149           pBranchLink(pc,npc);
1150           return;
1151         } else
1152           npc = npc->next;
1153       }
1154     }
1155   }
1156 }
1157
1158 /*-----------------------------------------------------------------*/
1159 /* findLabel - Search the pCode for a particular label             */
1160 /*-----------------------------------------------------------------*/
1161 pCode * findLabel(pCodeOpLabel *pcop_label)
1162 {
1163   pBlock *pb;
1164   pCode  *pc;
1165   pBranch *pbr;
1166
1167   if(!the_pFile)
1168     return NULL;
1169
1170   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1171     for(pc = pb->pcHead; pc; pc = pc->next) {
1172       if(pc->type == PC_LABEL) {
1173         if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
1174           return pc;
1175       }
1176       if(pc->type == PC_OPCODE) {
1177         pbr = pc->label;
1178         while(pbr) {
1179           if(pbr->pc->type == PC_LABEL) {
1180             if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
1181               return pc;
1182           }
1183           pbr = pbr->next;
1184         }
1185       }
1186
1187     }
1188   }
1189
1190   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1191   return NULL;
1192 }
1193
1194 /*-----------------------------------------------------------------*/
1195 /* findNextInstruction - given a pCode, find the next instruction  */
1196 /*                       in the linked list                        */
1197 /*-----------------------------------------------------------------*/
1198 pCode * findNextInstruction(pCode *pc)
1199 {
1200
1201   while(pc) {
1202     if(pc->type == PC_OPCODE)
1203       return pc;
1204
1205     pc = pc->next;
1206   }
1207
1208   fprintf(stderr,"Couldn't find instruction\n");
1209   return NULL;
1210 }
1211
1212 /*-----------------------------------------------------------------*/
1213 /* findFunctionEnd - given a pCode find the end of the function    */
1214 /*                   that contains it     t                        */
1215 /*-----------------------------------------------------------------*/
1216 pCode * findFunctionEnd(pCode *pc)
1217 {
1218
1219   while(pc) {
1220     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
1221       return pc;
1222
1223     pc = pc->next;
1224   }
1225
1226   fprintf(stderr,"Couldn't find function end\n");
1227   return NULL;
1228 }
1229
1230 #if 0
1231 /*-----------------------------------------------------------------*/
1232 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
1233 /*                instruction with which it is associated.         */
1234 /*-----------------------------------------------------------------*/
1235 static void AnalyzeLabel(pCode *pc)
1236 {
1237
1238   pCodeUnlink(pc);
1239
1240 }
1241 #endif
1242
1243 static void AnalyzeGOTO(pCode *pc)
1244 {
1245
1246   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
1247
1248 }
1249
1250 static void AnalyzeSKIP(pCode *pc)
1251 {
1252
1253   pBranchLink(pc,findNextInstruction(pc->next));
1254   pBranchLink(pc,findNextInstruction(pc->next->next));
1255
1256 }
1257
1258 static void AnalyzeRETURN(pCode *pc)
1259 {
1260
1261   //  branch_link(pc,findFunctionEnd(pc->next));
1262
1263 }
1264
1265
1266 void AnalyzepBlock(pBlock *pb)
1267 {
1268   pCode *pc;
1269
1270   if(!pb)
1271     return;
1272
1273   /* Find all of the registers used in this pBlock */
1274   for(pc = pb->pcHead; pc; pc = pc->next) {
1275     if(pc->type == PC_OPCODE) {
1276       if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
1277
1278         /* Loop through all of the registers declared so far in
1279            this block and see if we find this new there */
1280
1281         regs *r = setFirstItem(pb->registers);
1282
1283         while(r) {
1284           if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
1285             PCOR(PCI(pc)->pcop)->r = r;
1286             break;
1287           }
1288           r = setNextItem(pb->registers);
1289         }
1290
1291         if(!r) {
1292           /* register wasn't found */
1293           r = Safe_calloc(1, sizeof(regs));
1294           memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
1295           addSet(&pb->registers, r);
1296           PCOR(PCI(pc)->pcop)->r = r;
1297           fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
1298         } else 
1299           fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
1300       }
1301     }
1302   }
1303 }
1304
1305 int OptimizepBlock(pBlock *pb)
1306 {
1307   pCode *pc;
1308   int matches =0;
1309
1310   if(!pb || !peepOptimizing)
1311     return 0;
1312
1313   fprintf(stderr," Optimizing pBlock\n");
1314
1315   for(pc = pb->pcHead; pc; pc = pc->next)
1316     matches += pCodePeepMatchRule(pc);
1317
1318   return matches;
1319
1320 }
1321 /*-----------------------------------------------------------------*/
1322 /* pBlockMergeLabels - remove the pCode labels from the pCode      */
1323 /*                     chain and put them into pBranches that are  */
1324 /*                     associated with the appropriate pCode       */
1325 /*                     instructions.                               */
1326 /*-----------------------------------------------------------------*/
1327 void pBlockMergeLabels(pBlock *pb)
1328 {
1329   pBranch *pbr;
1330   pCode *pc, *pcnext=NULL;
1331
1332   if(!pb)
1333     return;
1334
1335   for(pc = pb->pcHead; pc; pc = pc->next) {
1336
1337     if(pc->type == PC_LABEL) {
1338       if( !(pcnext = findNextInstruction(pc)) ) 
1339         return;  // Couldn't find an instruction associated with this label
1340
1341       // Unlink the pCode label from it's pCode chain
1342       if(pc->prev) 
1343         pc->prev->next = pc->next;
1344       if(pc->next)
1345         pc->next->prev = pc->prev;
1346
1347       // And link it into the instruction's pBranch labels. (Note, since
1348       // it's possible to have multiple labels associated with one instruction
1349       // we must provide a means to accomodate the additional labels. Thus
1350       // the labels are placed into the singly-linked list "label" as 
1351       // opposed to being a single member of the pCodeInstruction.)
1352
1353       _ALLOC(pbr,sizeof(pBranch));
1354       pbr->pc = pc;
1355       pbr->next = NULL;
1356
1357       pcnext->label = pBranchAppend(pcnext->label,pbr);
1358     }
1359
1360   }
1361
1362 }
1363
1364 /*-----------------------------------------------------------------*/
1365 /*-----------------------------------------------------------------*/
1366 void OptimizepCode(char dbName)
1367 {
1368 #define MAX_PASSES 4
1369
1370   int matches = 0;
1371   int passes = 0;
1372   pBlock *pb;
1373
1374   if(!the_pFile)
1375     return;
1376
1377   fprintf(stderr," Optimizing pCode\n");
1378
1379   do {
1380     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1381       if('*' == dbName || getpBlock_dbName(pb) == dbName)
1382         matches += OptimizepBlock(pb);
1383     }
1384   }
1385   while(matches && ++passes < MAX_PASSES);
1386
1387 }
1388
1389 /*-----------------------------------------------------------------*/
1390 /* AnalyzepCode - parse the pCode that has been generated and form */
1391 /*                all of the logical connections.                  */
1392 /*                                                                 */
1393 /* Essentially what's done here is that the pCode flow is          */
1394 /* determined.                                                     */
1395 /*-----------------------------------------------------------------*/
1396
1397 void AnalyzepCode(char dbName)
1398 {
1399   pBlock *pb;
1400   pCode *pc;
1401   pBranch *pbr;
1402
1403   if(!the_pFile)
1404     return;
1405
1406   fprintf(stderr," Analyzing pCode");
1407
1408   /* First, merge the labels with the instructions */
1409   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1410     if('*' == dbName || getpBlock_dbName(pb) == dbName) {
1411       pBlockMergeLabels(pb);
1412       AnalyzepBlock(pb);
1413     }
1414   }
1415
1416   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1417     if('*' == dbName || getpBlock_dbName(pb) == dbName)
1418       OptimizepBlock(pb);
1419   }
1420
1421   /* Now build the call tree.
1422      First we examine all of the pCodes for functions.
1423      Keep in mind that the function boundaries coincide
1424      with pBlock boundaries. 
1425
1426      The algorithm goes something like this:
1427      We have two nested loops. The outer loop iterates
1428      through all of the pBlocks/functions. The inner
1429      loop iterates through all of the pCodes for
1430      a given pBlock. When we begin iterating through
1431      a pBlock, the variable pc_fstart, pCode of the start
1432      of a function, is cleared. We then search for pCodes
1433      of type PC_FUNCTION. When one is encountered, we
1434      initialize pc_fstart to this and at the same time
1435      associate a new pBranch object that signifies a 
1436      branch entry. If a return is found, then this signifies
1437      a function exit point. We'll link the pCodes of these
1438      returns to the matching pc_fstart.
1439
1440      When we're done, a doubly linked list of pBranches
1441      will exist. The head of this list is stored in
1442      `the_pFile', which is the meta structure for all
1443      of the pCode. Look at the printCallTree function
1444      on how the pBranches are linked together.
1445
1446    */
1447   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1448     if('*' == dbName || getpBlock_dbName(pb) == dbName) {
1449       pCode *pc_fstart=NULL;
1450       for(pc = pb->pcHead; pc; pc = pc->next) {
1451         if(pc->type == PC_FUNCTION) {
1452           if (PCF(pc)->fname) {
1453             // I'm not liking this....
1454             // Found the beginning of a function.
1455             _ALLOC(pbr,sizeof(pBranch));
1456             pbr->pc = pc_fstart = pc;
1457             pbr->next = NULL;
1458
1459             the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
1460
1461             // Here's a better way of doing the same:
1462             addSet(&pb->function_entries, pc);
1463
1464           } else {
1465             // Found an exit point in a function, e.g. return
1466             // (Note, there may be more than one return per function)
1467             if(pc_fstart)
1468               pBranchLink(pc_fstart, pc);
1469
1470             addSet(&pb->function_exits, pc);
1471           }
1472         } else  if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
1473           addSet(&pb->function_calls,pc);
1474         }
1475       }
1476     }
1477   }
1478 }
1479
1480 /*-----------------------------------------------------------------*/
1481 /* ispCodeFunction - returns true if *pc is the pCode of a         */
1482 /*                   function                                      */
1483 /*-----------------------------------------------------------------*/
1484 bool ispCodeFunction(pCode *pc)
1485 {
1486
1487   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
1488     return 1;
1489
1490   return 0;
1491 }
1492
1493 /*-----------------------------------------------------------------*/
1494 /* findFunction - Search for a function by name (given the name)   */
1495 /*                in the set of all functions that are in a pBlock */
1496 /* (note - I expect this to change because I'm planning to limit   */
1497 /*  pBlock's to just one function declaration                      */
1498 /*-----------------------------------------------------------------*/
1499 pCode *findFunction(char *fname)
1500 {
1501   pBlock *pb;
1502   pCode *pc;
1503   if(!fname)
1504     return NULL;
1505
1506   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1507
1508     pc = setFirstItem(pb->function_entries);
1509     while(pc) {
1510     
1511       if((pc->type == PC_FUNCTION) &&
1512          (PCF(pc)->fname) && 
1513          (strcmp(fname, PCF(pc)->fname)==0))
1514         return pc;
1515
1516       pc = setNextItem(pb->function_entries);
1517
1518     }
1519
1520   }
1521   return NULL;
1522 }
1523
1524 void MarkUsedRegisters(set *regset)
1525 {
1526
1527   regs *r1,*r2;
1528
1529   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
1530     r2 = pic14_regWithIdx(r1->rIdx);
1531     r2->isFree = 0;
1532     r2->wasUsed = 1;
1533   }
1534 }
1535
1536 void pBlockStats(FILE *of, pBlock *pb)
1537 {
1538
1539   pCode *pc;
1540   regs  *r;
1541
1542   fprintf(of,"***\n  pBlock Stats\n***\n");
1543
1544   // for now just print the first element of each set
1545   pc = setFirstItem(pb->function_entries);
1546   if(pc) {
1547     fprintf(of,"entry\n");
1548     pc->print(of,pc);
1549   }
1550   pc = setFirstItem(pb->function_exits);
1551   if(pc) {
1552     fprintf(of,"has an exit\n");
1553     pc->print(of,pc);
1554   }
1555
1556   pc = setFirstItem(pb->function_calls);
1557   if(pc) {
1558     fprintf(of,"functions called\n");
1559
1560     while(pc) {
1561       pc->print(of,pc);
1562       pc = setNextItem(pb->function_calls);
1563     }
1564   }
1565
1566   r = setFirstItem(pb->registers);
1567   if(r) {
1568     int n = elementsInSet(pb->registers);
1569
1570     fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
1571
1572     while (r) {
1573       fprintf(of,"   %s\n",r->name);
1574       r = setNextItem(pb->registers);
1575     }
1576   }
1577 }
1578
1579 /*-----------------------------------------------------------------*/
1580 /*-----------------------------------------------------------------*/
1581 void sequencepCode(void)
1582 {
1583   pBlock *pb;
1584   pCode *pc;
1585
1586
1587   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1588
1589     pb->seq = GpCodeSequenceNumber+1;
1590
1591     for( pc = pb->pcHead; pc; pc = pc->next)
1592       pc->seq = ++GpCodeSequenceNumber;
1593   }
1594
1595 }
1596
1597 /*-----------------------------------------------------------------*/
1598 /*-----------------------------------------------------------------*/
1599 set *register_usage(pBlock *pb)
1600 {
1601   pCode *pc,*pcn;
1602   set *registers=NULL;
1603   set *registersInCallPath = NULL;
1604
1605   /* check recursion */
1606
1607   pc = setFirstItem(pb->function_entries);
1608
1609   if(!pc)
1610     return registers;
1611
1612   pb->visited = 1;
1613
1614   if(pc->type != PC_FUNCTION)
1615     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
1616
1617   pc = setFirstItem(pb->function_calls);
1618   for( ; pc; pc = setNextItem(pb->function_calls)) {
1619
1620     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
1621       char *dest = get_op(PCI(pc));
1622
1623       pcn = findFunction(dest);
1624       if(pcn) 
1625         registersInCallPath = register_usage(pcn->pb);
1626     } else
1627       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
1628
1629   }
1630
1631
1632   pBlockStats(stderr,pb);  // debug
1633   if(registersInCallPath) {
1634     /* registers were used in the functions this pBlock has called */
1635     /* so now, we need to see if these collide with the ones we are */
1636     /* using here */
1637
1638     regs *r1,*r2, *newreg;
1639
1640     fprintf(stderr,"comparing registers\n");
1641
1642     r1 = setFirstItem(registersInCallPath);
1643     while(r1) {
1644
1645       r2 = setFirstItem(pb->registers);
1646
1647       while(r2) {
1648
1649         if(r2->rIdx == r1->rIdx) {
1650           newreg = pic14_findFreeReg();
1651
1652
1653           if(!newreg) {
1654             fprintf(stderr,"Bummer, no more registers.\n");
1655             exit(1);
1656           }
1657
1658           fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
1659                   r1->rIdx, newreg->rIdx);
1660           r2->rIdx = newreg->rIdx;
1661           //if(r2->name) free(r2->name);
1662           r2->name = Safe_strdup(newreg->name);
1663           newreg->isFree = 0;
1664           newreg->wasUsed = 1;
1665         }
1666         r2 = setNextItem(pb->registers);
1667       }
1668
1669       r1 = setNextItem(registersInCallPath);
1670     }
1671
1672     /* Collisions have been resolved. Now free the registers in the call path */
1673     r1 = setFirstItem(registersInCallPath);
1674     while(r1) {
1675       newreg = pic14_regWithIdx(r1->rIdx);
1676       newreg->isFree = 1;
1677       r1 = setNextItem(registersInCallPath);
1678     }
1679
1680   } else
1681     MarkUsedRegisters(pb->registers);
1682
1683   registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
1684
1685   if(registers) 
1686     fprintf(stderr,"returning regs\n");
1687   else
1688     fprintf(stderr,"not returning regs\n");
1689
1690   fprintf(stderr,"pBlock after register optim.\n");
1691   pBlockStats(stderr,pb);  // debug
1692
1693
1694   return registers;
1695 }
1696
1697 /*-----------------------------------------------------------------*/
1698 /* printCallTree - writes the call tree to a file                  */
1699 /*                                                                 */
1700 /*-----------------------------------------------------------------*/
1701 void pct2(FILE *of,pBlock *pb,int indent)
1702 {
1703   pCode *pc,*pcn;
1704   int i;
1705   //  set *registersInCallPath = NULL;
1706
1707   if(!of)
1708     return;// registers;
1709
1710   if(indent > 10)
1711     return; // registers;   //recursion ?
1712
1713   pc = setFirstItem(pb->function_entries);
1714
1715   if(!pc)
1716     return;
1717
1718   pb->visited = 0;
1719
1720   for(i=0;i<indent;i++)   // Indentation
1721     fputc(' ',of);
1722
1723   if(pc->type == PC_FUNCTION)
1724     fprintf(of,"%s\n",PCF(pc)->fname);
1725   else
1726     return;  // ???
1727
1728
1729   pc = setFirstItem(pb->function_calls);
1730   for( ; pc; pc = setNextItem(pb->function_calls)) {
1731
1732     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
1733       char *dest = get_op(PCI(pc));
1734
1735       pcn = findFunction(dest);
1736       if(pcn) 
1737         pct2(of,pcn->pb,indent+1);
1738     } else
1739       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
1740
1741   }
1742
1743
1744 }
1745
1746 #if 0
1747   fprintf(stderr,"pBlock before register optim.\n");
1748   pBlockStats(stderr,pb);  // debug
1749
1750   if(registersInCallPath) {
1751     /* registers were used in the functions this pBlock has called */
1752     /* so now, we need to see if these collide with the ones we are using here */
1753
1754     regs *r1,*r2, *newreg;
1755
1756     fprintf(stderr,"comparing registers\n");
1757
1758     r1 = setFirstItem(registersInCallPath);
1759     while(r1) {
1760
1761       r2 = setFirstItem(pb->registers);
1762
1763       while(r2) {
1764
1765         if(r2->rIdx == r1->rIdx) {
1766           newreg = pic14_findFreeReg();
1767
1768
1769           if(!newreg) {
1770             fprintf(stderr,"Bummer, no more registers.\n");
1771             exit(1);
1772           }
1773
1774           fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
1775                   r1->rIdx, newreg->rIdx);
1776           r2->rIdx = newreg->rIdx;
1777           //if(r2->name) free(r2->name);
1778           r2->name = Safe_strdup(newreg->name);
1779           newreg->isFree = 0;
1780           newreg->wasUsed = 1;
1781         }
1782         r2 = setNextItem(pb->registers);
1783       }
1784
1785       r1 = setNextItem(registersInCallPath);
1786     }
1787
1788     /* Collisions have been resolved. Now free the registers in the call path */
1789     r1 = setFirstItem(registersInCallPath);
1790     while(r1) {
1791       newreg = pic14_regWithIdx(r1->rIdx);
1792       newreg->isFree = 1;
1793       r1 = setNextItem(registersInCallPath);
1794     }
1795
1796   } else
1797     MarkUsedRegisters(pb->registers);
1798
1799   registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
1800
1801   if(registers) 
1802     fprintf(stderr,"returning regs\n");
1803   else
1804     fprintf(stderr,"not returning regs\n");
1805
1806   fprintf(stderr,"pBlock after register optim.\n");
1807   pBlockStats(stderr,pb);  // debug
1808
1809
1810   return registers;
1811
1812 #endif
1813
1814
1815 /*-----------------------------------------------------------------*/
1816 /* printCallTree - writes the call tree to a file                  */
1817 /*                                                                 */
1818 /*-----------------------------------------------------------------*/
1819
1820 void printCallTree(FILE *of)
1821 {
1822   pBranch *pbr;
1823   pBlock  *pb;
1824   pCode   *pc;
1825
1826   if(!the_pFile)
1827     return;
1828
1829   if(!of)
1830     of = stderr;
1831
1832   fprintf(of, "\npBlock statistics\n");
1833   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
1834     pBlockStats(stderr,pb);
1835
1836
1837
1838   fprintf(of,"Call Tree\n");
1839   pbr = the_pFile->functions;
1840   while(pbr) {
1841     if(pbr->pc) {
1842       pc = pbr->pc;
1843       if(!ispCodeFunction(pc))
1844         fprintf(of,"bug in call tree");
1845
1846
1847       fprintf(of,"Function: %s\n", PCF(pc)->fname);
1848
1849       while(pc->next && !ispCodeFunction(pc->next)) {
1850         pc = pc->next;
1851         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
1852           fprintf(of,"\t%s\n",get_op(PCI(pc)));
1853       }
1854     }
1855
1856     pbr = pbr->next;
1857   }
1858
1859
1860   /* Re-allocate the registers so that there are no collisions
1861    * between local variables when one function call another */
1862
1863   pic14_deallocateAllRegs();
1864
1865   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1866     if(!pb->visited)
1867       register_usage(pb);
1868   }
1869
1870   fprintf(of,"\n**************\n\na better call tree\n");
1871   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1872     if(pb->visited)
1873       pct2(of,pb,0);
1874   }
1875
1876   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1877     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
1878   }
1879 }