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