95188313ab9b9476c95a7d11de6c881cc8239520
[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_RETURN,
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,int dest)
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       if((pci->num_ops <= 1) || (pci->dest == dest))
795         return(pci->op);
796     }
797
798     pci = hTabNextItemWK (pic14MnemonicsHash);
799   
800   }
801
802   return -1;
803 }
804
805 char getpBlock_dbName(pBlock *pb)
806 {
807   if(!pb)
808     return 0;
809
810   if(pb->cmemmap)
811     return pb->cmemmap->dbName;
812
813   return pb->dbName;
814 }
815 /*-----------------------------------------------------------------*/
816 /* movepBlock2Head - given the dbname of a pBlock, move all        */
817 /*                   instances to the front of the doubly linked   */
818 /*                   list of pBlocks                               */
819 /*-----------------------------------------------------------------*/
820
821 void movepBlock2Head(char dbName)
822 {
823   pBlock *pb;
824
825   pb = the_pFile->pbHead;
826
827   while(pb) {
828
829     if(getpBlock_dbName(pb) == dbName) {
830       pBlock *pbn = pb->next;
831       pb->next = the_pFile->pbHead;
832       the_pFile->pbHead->prev = pb;
833       the_pFile->pbHead = pb;
834
835       if(pb->prev)
836         pb->prev->next = pbn;
837
838       // If the pBlock that we just moved was the last
839       // one in the link of all of the pBlocks, then we
840       // need to point the tail to the block just before
841       // the one we moved.
842       // Note: if pb->next is NULL, then pb must have 
843       // been the last pBlock in the chain.
844
845       if(pbn)
846         pbn->prev = pb->prev;
847       else
848         the_pFile->pbTail = pb->prev;
849
850       pb = pbn;
851
852     } else
853       pb = pb->next;
854
855   }
856
857 }
858
859 void copypCode(FILE *of, char dbName)
860 {
861   pBlock *pb;
862
863   if(!of || !the_pFile)
864     return;
865
866   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
867     if(getpBlock_dbName(pb) == dbName)
868       printpBlock(of,pb);
869   }
870
871 }
872 void pcode_test(void)
873 {
874
875   printf("pcode is alive!\n");
876
877   //initMnemonics();
878
879   if(the_pFile) {
880
881     pBlock *pb;
882     FILE *pFile;
883     char buffer[100];
884
885     /* create the file name */
886     strcpy(buffer,srcFileName);
887     strcat(buffer,".p");
888
889     if( !(pFile = fopen(buffer, "w" ))) {
890       werror(E_FILE_OPEN_ERR,buffer);
891       exit(1);
892     }
893
894     fprintf(pFile,"pcode dump\n\n");
895
896     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
897       fprintf(pFile,"\n\tNew pBlock\n\n");
898       if(pb->cmemmap)
899         fprintf(pFile,"%s",pb->cmemmap->sname);
900       else
901         fprintf(pFile,"internal pblock");
902
903       fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
904       printpBlock(pFile,pb);
905     }
906   }
907 }
908 static int RegCond(pCodeOp *pcop)
909 {
910
911   if(!pcop)
912     return 0;
913
914   if(pcop->type == PO_BIT  && !strcmp(pcop->name, pc_status.pcop.name)) {
915     switch(PCOB(pcop)->bit) {
916     case PIC_C_BIT:
917       return PCC_C;
918     case PIC_DC_BIT:
919         return PCC_DC;
920     case PIC_Z_BIT:
921       return PCC_Z;
922     }
923
924   }
925
926   return 0;
927 }
928
929 /*-----------------------------------------------------------------*/
930 /* newpCode - create and return a newly initialized pCode          */
931 /*                                                                 */
932 /*  fixme - rename this                                            */
933 /*                                                                 */
934 /* The purpose of this routine is to create a new Instruction      */
935 /* pCode. This is called by gen.c while the assembly code is being */
936 /* generated.                                                      */
937 /*                                                                 */
938 /* Inouts:                                                         */
939 /*  PIC_OPCODE op - the assembly instruction we wish to create.    */
940 /*                  (note that the op is analogous to but not the  */
941 /*                  same thing as the opcode of the instruction.)  */
942 /*  pCdoeOp *pcop - pointer to the operand of the instruction.     */
943 /*                                                                 */
944 /* Outputs:                                                        */
945 /*  a pointer to the new malloc'd pCode is returned.               */
946 /*                                                                 */
947 /*                                                                 */
948 /*                                                                 */
949 /*-----------------------------------------------------------------*/
950 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
951 {
952   pCodeInstruction *pci ;
953
954   if(!mnemonics_initialized)
955     pic14initMnemonics();
956     
957   pci = Safe_calloc(1, sizeof(pCodeInstruction));
958
959   if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
960     memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
961     pci->pcop = pcop;
962
963     if(pci->inCond == PCC_EXAMINE_PCOP)
964       pci->inCond   = RegCond(pcop);
965
966     if(pci->outCond == PCC_EXAMINE_PCOP)
967       pci->outCond   = RegCond(pcop);
968
969     return (pCode *)pci;
970   }
971
972   fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
973   exit(1);
974
975   return NULL;
976 }       
977
978 /*-----------------------------------------------------------------*/
979 /* newpCodeWild - create a "wild" as in wild card pCode            */
980 /*                                                                 */
981 /* Wild pcodes are used during the peep hole optimizer to serve    */
982 /* as place holders for any instruction. When a snippet of code is */
983 /* compared to a peep hole rule, the wild card opcode will match   */
984 /* any instruction. However, the optional operand and label are    */
985 /* additional qualifiers that must also be matched before the      */
986 /* line (of assembly code) is declared matched. Note that the      */
987 /* operand may be wild too.                                        */
988 /*                                                                 */
989 /*   Note, a wild instruction is specified just like a wild var:   */
990 /*      %4     ; A wild instruction,                               */
991 /*  See the peeph.def file for additional examples                 */
992 /*                                                                 */
993 /*-----------------------------------------------------------------*/
994
995 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
996 {
997
998   pCodeWild *pcw;
999     
1000   pcw = Safe_calloc(1,sizeof(pCodeWild));
1001
1002   pcw->pc.type = PC_WILD;
1003   pcw->pc.prev = pcw->pc.next = NULL;
1004   pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
1005   pcw->pc.pb = NULL;
1006
1007   pcw->pc.analyze = genericAnalyze;
1008   pcw->pc.destruct = genericDestruct;
1009   pcw->pc.print = genericPrint;
1010
1011   pcw->id = pCodeID;              // this is the 'n' in %n
1012   pcw->operand = optional_operand;
1013   pcw->label   = optional_label;
1014
1015   return ( (pCode *)pcw);
1016   
1017 }
1018
1019 /*-----------------------------------------------------------------*/
1020 /* newPcodeCharP - create a new pCode from a char string           */
1021 /*-----------------------------------------------------------------*/
1022
1023 pCode *newpCodeCharP(char *cP)
1024 {
1025
1026   pCodeComment *pcc ;
1027     
1028   pcc = Safe_calloc(1,sizeof(pCodeComment));
1029
1030   pcc->pc.type = PC_COMMENT;
1031   pcc->pc.prev = pcc->pc.next = NULL;
1032   pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1033   pcc->pc.pb = NULL;
1034
1035   pcc->pc.analyze = genericAnalyze;
1036   pcc->pc.destruct = genericDestruct;
1037   pcc->pc.print = genericPrint;
1038
1039   pcc->comment = Safe_strdup(cP);
1040
1041   return ( (pCode *)pcc);
1042
1043 }
1044
1045 /*-----------------------------------------------------------------*/
1046 /* newpCodeGLabel - create a new global label                      */
1047 /*-----------------------------------------------------------------*/
1048
1049
1050 pCode *newpCodeFunction(char *mod,char *f)
1051 {
1052   pCodeFunction *pcf;
1053
1054   _ALLOC(pcf,sizeof(pCodeFunction));
1055
1056   pcf->pc.type = PC_FUNCTION;
1057   pcf->pc.prev = pcf->pc.next = NULL;
1058   pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1059   pcf->pc.pb = NULL;
1060
1061   pcf->pc.analyze = genericAnalyze;
1062   pcf->pc.destruct = genericDestruct;
1063   pcf->pc.print = pCodePrintFunction;
1064
1065   if(mod) {
1066     _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1067     strcpy(pcf->modname,mod);
1068   } else
1069     pcf->modname = NULL;
1070
1071   if(f) {
1072     _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1073     strcpy(pcf->fname,f);
1074   } else
1075     pcf->fname = NULL;
1076
1077   return ( (pCode *)pcf);
1078
1079 }
1080
1081 static void pCodeLabelDestruct(pCode *pc)
1082 {
1083
1084   if(!pc)
1085     return;
1086
1087   unlinkPC(pc);
1088
1089   if(PCL(pc)->label)
1090     free(PCL(pc)->label);
1091
1092   free(pc);
1093
1094 }
1095
1096 pCode *newpCodeLabel(int key)
1097 {
1098
1099   char *s = buffer;
1100   pCodeLabel *pcl;
1101     
1102   pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1103
1104   pcl->pc.type = PC_LABEL;
1105   pcl->pc.prev = pcl->pc.next = NULL;
1106   pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1107   pcl->pc.pb = NULL;
1108
1109   pcl->pc.analyze = genericAnalyze;
1110   pcl->pc.destruct = pCodeLabelDestruct;
1111   pcl->pc.print = pCodePrintLabel;
1112
1113   pcl->key = key;
1114
1115   if(key>0) {
1116     sprintf(s,"_%05d_DS_",key);
1117     pcl->label = Safe_strdup(s);
1118   } else
1119     pcl->label = NULL;
1120
1121   return ( (pCode *)pcl);
1122
1123 }
1124 pCode *newpCodeLabelStr(char *str)
1125 {
1126   pCode *pc = newpCodeLabel(-1);
1127
1128   PCL(pc)->label = Safe_strdup(str);
1129
1130   return pc;
1131 }
1132
1133 /*-----------------------------------------------------------------*/
1134 /* newpBlock - create and return a pointer to a new pBlock         */
1135 /*-----------------------------------------------------------------*/
1136 pBlock *newpBlock(void)
1137 {
1138
1139   pBlock *PpB;
1140
1141   PpB = Safe_calloc(1,sizeof(pBlock) );
1142   PpB->next = PpB->prev = NULL;
1143
1144   PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1145   PpB->registers = NULL;
1146   PpB->visited = 0;
1147
1148   return PpB;
1149
1150 }
1151
1152 /*-----------------------------------------------------------------*/
1153 /* newpCodeChain - create a new chain of pCodes                    */
1154 /*-----------------------------------------------------------------*
1155  *
1156  *  This function will create a new pBlock and the pointer to the
1157  *  pCode that is passed in will be the first pCode in the block.
1158  *-----------------------------------------------------------------*/
1159
1160
1161 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1162 {
1163
1164   pBlock *pB  = newpBlock();
1165
1166   pB->pcHead  = pB->pcTail = pc;
1167   pB->cmemmap = cm;
1168   pB->dbName  = c;
1169
1170   return pB;
1171 }
1172
1173 /*-----------------------------------------------------------------*/
1174 /* newpCodeOpLabel - Create a new label given the key              */
1175 /*  Note, a negative key means that the label is part of wild card */
1176 /*  (and hence a wild card label) used in the pCodePeep            */
1177 /*   optimizations).                                               */
1178 /*-----------------------------------------------------------------*/
1179
1180 pCodeOp *newpCodeOpLabel(int key)
1181 {
1182   char *s = buffer;
1183   pCodeOp *pcop;
1184
1185   pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1186   pcop->type = PO_LABEL;
1187
1188   if(key>0) {
1189     sprintf(s,"_%05d_DS_",key);
1190     pcop->name = Safe_strdup(s);
1191   } else
1192     pcop->name = NULL;
1193
1194   ((pCodeOpLabel *)pcop)->key = key;
1195
1196   return pcop;
1197 }
1198
1199 pCodeOp *newpCodeOpLit(int lit)
1200 {
1201   char *s = buffer;
1202   pCodeOp *pcop;
1203
1204
1205   pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1206   pcop->type = PO_LITERAL;
1207   if(lit>=0) {
1208     sprintf(s,"0x%02x",lit);
1209     pcop->name = Safe_strdup(s);
1210   } else
1211     pcop->name = NULL;
1212
1213   ((pCodeOpLit *)pcop)->lit = lit;
1214
1215   return pcop;
1216 }
1217
1218 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1219 {
1220   char *s = buffer;
1221   pCodeOp *pcop;
1222
1223
1224   if(!pcp || !subtype) {
1225     fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1226     exit(1);
1227   }
1228
1229   pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1230   pcop->type = PO_WILD;
1231   sprintf(s,"%%%d",id);
1232   pcop->name = Safe_strdup(s);
1233
1234   PCOW(pcop)->id = id;
1235   PCOW(pcop)->pcp = pcp;
1236   PCOW(pcop)->subtype = subtype;
1237   PCOW(pcop)->matched = NULL;
1238
1239   return pcop;
1240 }
1241
1242 pCodeOp *newpCodeOpBit(char *s, int bit)
1243 {
1244   pCodeOp *pcop;
1245
1246   pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1247   pcop->type = PO_BIT;
1248   pcop->name = Safe_strdup(s);   
1249
1250   PCOB(pcop)->bit = bit;
1251   if(bit>=0)
1252     PCOB(pcop)->inBitSpace = 1;
1253   else
1254     PCOB(pcop)->inBitSpace = 0;
1255
1256   return pcop;
1257 }
1258
1259 /*-----------------------------------------------------------------*/
1260 /*-----------------------------------------------------------------*/
1261
1262 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1263 {
1264   pCodeOp *pcop;
1265
1266   switch(type) {
1267   case PO_BIT:
1268     pcop = newpCodeOpBit(name, -1);
1269     break;
1270
1271   case PO_LITERAL:
1272     pcop = newpCodeOpLit(-1);
1273     break;
1274
1275   case PO_LABEL:
1276     pcop = newpCodeOpLabel(-1);
1277     break;
1278
1279   default:
1280     pcop = Safe_calloc(1,sizeof(pCodeOp) );
1281     pcop->type = type;
1282     pcop->name = Safe_strdup(name);   
1283   }
1284
1285   return pcop;
1286 }
1287
1288 /*-----------------------------------------------------------------*/
1289 /* addpCode2pBlock - place the pCode into the pBlock linked list   */
1290 /*-----------------------------------------------------------------*/
1291 void addpCode2pBlock(pBlock *pb, pCode *pc)
1292 {
1293
1294   pb->pcTail->next = pc;
1295   pc->prev = pb->pcTail;
1296   pc->next = NULL;
1297   pc->pb = pb;
1298   pb->pcTail = pc;
1299 }
1300
1301 /*-----------------------------------------------------------------*/
1302 /* addpBlock - place a pBlock into the pFile                       */
1303 /*-----------------------------------------------------------------*/
1304 void addpBlock(pBlock *pb)
1305 {
1306
1307   if(!the_pFile) {
1308     /* First time called, we'll pass through here. */
1309     _ALLOC(the_pFile,sizeof(the_pFile));
1310     the_pFile->pbHead = the_pFile->pbTail = pb;
1311     the_pFile->functions = NULL;
1312     return;
1313   }
1314
1315   the_pFile->pbTail->next = pb;
1316   pb->prev = the_pFile->pbTail;
1317   pb->next = NULL;
1318   the_pFile->pbTail = pb;
1319 }
1320
1321 /*-----------------------------------------------------------------*/
1322 /* printpCode - write the contents of a pCode to a file            */
1323 /*-----------------------------------------------------------------*/
1324 void printpCode(FILE *of, pCode *pc)
1325 {
1326
1327   if(!pc || !of)
1328     return;
1329
1330   if(pc->print) {
1331     pc->print(of,pc);
1332     return;
1333   }
1334
1335   fprintf(of,"warning - unable to print pCode\n");
1336 }
1337
1338 /*-----------------------------------------------------------------*/
1339 /* printpBlock - write the contents of a pBlock to a file          */
1340 /*-----------------------------------------------------------------*/
1341 void printpBlock(FILE *of, pBlock *pb)
1342 {
1343   pCode *pc;
1344
1345   if(!pb)
1346     return;
1347
1348   if(!of)
1349     of = stderr;
1350
1351   for(pc = pb->pcHead; pc; pc = pc->next)
1352     printpCode(of,pc);
1353
1354 }
1355
1356 /*-----------------------------------------------------------------*/
1357 /*                                                                 */
1358 /*       pCode processing                                          */
1359 /*                                                                 */
1360 /*                                                                 */
1361 /*                                                                 */
1362 /*-----------------------------------------------------------------*/
1363
1364 static void unlinkPC(pCode *pc)
1365 {
1366   if(pc  && pc->prev && pc->next) {
1367
1368     pc->prev->next = pc->next;
1369     pc->next->prev = pc->prev;
1370   }
1371 }
1372 static void genericDestruct(pCode *pc)
1373 {
1374   fprintf(stderr,"warning, calling default pCode destructor\n");
1375
1376   unlinkPC(pc);
1377
1378   free(pc);
1379
1380 }
1381
1382
1383 void pBlockRegs(FILE *of, pBlock *pb)
1384 {
1385
1386   regs  *r;
1387
1388   r = setFirstItem(pb->registers);
1389   while (r) {
1390     fprintf(of,"   %s\n",r->name);
1391     r = setNextItem(pb->registers);
1392   }
1393 }
1394
1395
1396 static char *get_op( pCodeInstruction *pcc)
1397 {
1398   regs *r;
1399
1400   if(pcc && pcc->pcop) {
1401
1402
1403     switch(pcc->pcop->type) {
1404
1405     case PO_FSR:
1406     case PO_GPR_TEMP:
1407       r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1408       fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1409       pBlockRegs(stderr,pcc->pc.pb);
1410       return r->name;
1411
1412     default:
1413       if  (pcc->pcop->name)
1414         return pcc->pcop->name;
1415
1416     }
1417   }
1418
1419   return "NO operand";
1420 }
1421
1422 /*-----------------------------------------------------------------*/
1423 /*-----------------------------------------------------------------*/
1424 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1425 {
1426
1427   fprintf(of,"pcodeopprint\n");
1428 }
1429
1430 /*-----------------------------------------------------------------*/
1431 /* genericPrint - the contents of a pCode to a file                */
1432 /*-----------------------------------------------------------------*/
1433 static void genericPrint(FILE *of, pCode *pc)
1434 {
1435
1436   if(!pc || !of)
1437     return;
1438
1439   switch(pc->type) {
1440   case PC_COMMENT:
1441     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1442     break;
1443
1444   case PC_OPCODE:
1445     // If the opcode has a label, print that first
1446     {
1447       pBranch *pbl = pc->label;
1448       while(pbl) {
1449         if(pbl->pc->type == PC_LABEL)
1450           pCodePrintLabel(of, pbl->pc);
1451         pbl = pbl->next;
1452       }
1453     }
1454
1455     fprintf(of, "\t%s\t", PCI(pc)->mnemonic);
1456     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1457
1458       if(PCI(pc)->bit_inst) {
1459         if(PCI(pc)->pcop->type == PO_BIT) {
1460           if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1461             fprintf(of,"(%s >> 3), (%s & 7)", 
1462                     PCI(pc)->pcop->name ,
1463                     PCI(pc)->pcop->name );
1464           else
1465             fprintf(of,"%s,%d", get_op(PCI(pc)), (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1466         } else
1467           fprintf(of,"%s,0 ; ?bug", get_op(PCI(pc)));
1468         //PCI(pc)->pcop->t.bit );
1469       } else {
1470
1471         if(PCI(pc)->pcop->type == PO_BIT) {
1472           if( PCI(pc)->num_ops == 2)
1473             fprintf(of,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1474           else
1475             fprintf(of,"(1 << (%s & 7))",get_op(PCI(pc)));
1476
1477 /*
1478           if( PCI(pc)->num_ops == 2)
1479             fprintf(of,"(%s >> 3),%c",PCI(pc)->pcop->name,((PCI(pc)->dest) ? 'F':'W'));
1480           else
1481             fprintf(of,"(1 << (%s & 7))",PCI(pc)->pcop->name);
1482 */
1483         }else {
1484           fprintf(of,"%s",get_op(PCI(pc)));
1485
1486           if( PCI(pc)->num_ops == 2)
1487             fprintf(of,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1488         }
1489       }
1490     }
1491
1492     {
1493       pBranch *dpb = pc->to;   // debug
1494       while(dpb) {
1495         switch ( dpb->pc->type) {
1496         case PC_OPCODE:
1497           fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1498           break;
1499         case PC_LABEL:
1500           fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1501           break;
1502         case PC_FUNCTION:
1503           fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1504           break;
1505         case PC_COMMENT:
1506         case PC_WILD:
1507           break;
1508         }
1509         dpb = dpb->next;
1510       }
1511       fprintf(of,"\n");
1512     }
1513
1514     break;
1515
1516   case PC_WILD:
1517     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1518     if(PCW(pc)->operand) {
1519       fprintf(of,";\toperand  ");
1520       pCodeOpPrint(of,PCW(pc)->operand );
1521     }
1522     break;
1523
1524   case PC_LABEL:
1525   default:
1526     fprintf(of,"unknown pCode type %d\n",pc->type);
1527   }
1528
1529 }
1530
1531 /*-----------------------------------------------------------------*/
1532 /* pCodePrintFunction - prints function begin/end                  */
1533 /*-----------------------------------------------------------------*/
1534
1535 static void pCodePrintFunction(FILE *of, pCode *pc)
1536 {
1537
1538   if(!pc || !of)
1539     return;
1540
1541   if( ((pCodeFunction *)pc)->modname) 
1542     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1543
1544   if(PCF(pc)->fname) {
1545     pBranch *exits = pc->to;
1546     int i=0;
1547     fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1548     while(exits) {
1549       i++;
1550       exits = exits->next;
1551     }
1552     //if(i) i--;
1553     fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1554     
1555   }else {
1556     if(pc->from && 
1557        pc->from->pc->type == PC_FUNCTION &&
1558        PCF(pc->from->pc)->fname) 
1559       fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1560     else
1561       fprintf(of,"; exit point [can't find entry point]\n");
1562   }
1563 }
1564 /*-----------------------------------------------------------------*/
1565 /* pCodePrintLabel - prints label                                  */
1566 /*-----------------------------------------------------------------*/
1567
1568 static void pCodePrintLabel(FILE *of, pCode *pc)
1569 {
1570
1571   if(!pc || !of)
1572     return;
1573
1574   if(PCL(pc)->label) 
1575     fprintf(of,"%s\n",PCL(pc)->label);
1576   else if (PCL(pc)->key >=0) 
1577     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1578   else
1579     fprintf(of,";wild card label\n");
1580
1581 }
1582 /*-----------------------------------------------------------------*/
1583
1584 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1585 {
1586   pBranch *b;
1587
1588   if(!h)
1589     return n;
1590
1591   b = h;
1592   while(b->next)
1593     b = b->next;
1594
1595   b->next = n;
1596
1597   return h;
1598   
1599 }  
1600 /*-----------------------------------------------------------------*/
1601 /* pBranchLink - given two pcodes, this function will link them    */
1602 /*               together through their pBranches                  */
1603 /*-----------------------------------------------------------------*/
1604 static void pBranchLink(pCode *f, pCode *t)
1605 {
1606   pBranch *b;
1607
1608   // Declare a new branch object for the 'from' pCode.
1609
1610   _ALLOC(b,sizeof(pBranch));
1611   b->pc = t;                    // The link to the 'to' pCode.
1612   b->next = NULL;
1613
1614   f->to = pBranchAppend(f->to,b);
1615
1616   // Now do the same for the 'to' pCode.
1617
1618   _ALLOC(b,sizeof(pBranch));
1619   b->pc = f;
1620   b->next = NULL;
1621
1622   t->from = pBranchAppend(t->from,b);
1623   
1624 }
1625
1626 #if 0
1627 /*-----------------------------------------------------------------*/
1628 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1629 /*               a pCode                                           */
1630 /*-----------------------------------------------------------------*/
1631 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1632 {
1633   while(pb) {
1634
1635     if(pb->pc == pc)
1636       return pb;
1637
1638     pb = pb->next;
1639   }
1640
1641   return NULL;
1642 }
1643
1644 /*-----------------------------------------------------------------*/
1645 /* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
1646 /*-----------------------------------------------------------------*/
1647 static void pCodeUnlink(pCode *pc)
1648 {
1649   pBranch *pb1,*pb2;
1650   pCode *pc1;
1651
1652   if(!pc->prev || !pc->next) {
1653     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1654     exit(1);
1655   }
1656
1657   /* first remove the pCode from the chain */
1658   pc->prev->next = pc->next;
1659   pc->next->prev = pc->prev;
1660
1661   /* Now for the hard part... */
1662
1663   /* Remove the branches */
1664
1665   pb1 = pc->from;
1666   while(pb1) {
1667     pc1 = pb1->pc;    /* Get the pCode that branches to the
1668                        * one we're unlinking */
1669
1670     /* search for the link back to this pCode (the one we're
1671      * unlinking) */
1672     if(pb2 = pBranchFind(pc1->to,pc)) {
1673       pb2->pc = pc->to->pc;  // make the replacement
1674
1675       /* if the pCode we're unlinking contains multiple 'to'
1676        * branches (e.g. this a skip instruction) then we need
1677        * to copy these extra branches to the chain. */
1678       if(pc->to->next)
1679         pBranchAppend(pb2, pc->to->next);
1680     }
1681     
1682     pb1 = pb1->next;
1683   }
1684
1685
1686 }
1687 #endif
1688 /*-----------------------------------------------------------------*/
1689 /*-----------------------------------------------------------------*/
1690 static void genericAnalyze(pCode *pc)
1691 {
1692   switch(pc->type) {
1693   case PC_WILD:
1694   case PC_COMMENT:
1695     return;
1696   case PC_LABEL:
1697   case PC_FUNCTION:
1698   case PC_OPCODE:
1699     {
1700       // Go through the pCodes that are in pCode chain and link
1701       // them together through the pBranches. Note, the pCodes
1702       // are linked together as a contiguous stream like the 
1703       // assembly source code lines. The linking here mimics this
1704       // except that comments are not linked in.
1705       // 
1706       pCode *npc = pc->next;
1707       while(npc) {
1708         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1709           pBranchLink(pc,npc);
1710           return;
1711         } else
1712           npc = npc->next;
1713       }
1714     }
1715   }
1716 }
1717
1718 /*-----------------------------------------------------------------*/
1719 /* findLabel - Search the pCode for a particular label             */
1720 /*-----------------------------------------------------------------*/
1721 pCode * findLabel(pCodeOpLabel *pcop_label)
1722 {
1723   pBlock *pb;
1724   pCode  *pc;
1725   pBranch *pbr;
1726
1727   if(!the_pFile)
1728     return NULL;
1729
1730   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1731     for(pc = pb->pcHead; pc; pc = pc->next) {
1732       if(pc->type == PC_LABEL) {
1733         if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
1734           return pc;
1735       }
1736       if(pc->type == PC_OPCODE) {
1737         pbr = pc->label;
1738         while(pbr) {
1739           if(pbr->pc->type == PC_LABEL) {
1740             if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
1741               return pc;
1742           }
1743           pbr = pbr->next;
1744         }
1745       }
1746
1747     }
1748   }
1749
1750   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1751   return NULL;
1752 }
1753
1754 /*-----------------------------------------------------------------*/
1755 /* findNextInstruction - given a pCode, find the next instruction  */
1756 /*                       in the linked list                        */
1757 /*-----------------------------------------------------------------*/
1758 pCode * findNextInstruction(pCode *pc)
1759 {
1760
1761   while(pc) {
1762     if(pc->type == PC_OPCODE)
1763       return pc;
1764
1765     pc = pc->next;
1766   }
1767
1768   fprintf(stderr,"Couldn't find instruction\n");
1769   return NULL;
1770 }
1771
1772 /*-----------------------------------------------------------------*/
1773 /* findFunctionEnd - given a pCode find the end of the function    */
1774 /*                   that contains it     t                        */
1775 /*-----------------------------------------------------------------*/
1776 pCode * findFunctionEnd(pCode *pc)
1777 {
1778
1779   while(pc) {
1780     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
1781       return pc;
1782
1783     pc = pc->next;
1784   }
1785
1786   fprintf(stderr,"Couldn't find function end\n");
1787   return NULL;
1788 }
1789
1790 #if 0
1791 /*-----------------------------------------------------------------*/
1792 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
1793 /*                instruction with which it is associated.         */
1794 /*-----------------------------------------------------------------*/
1795 static void AnalyzeLabel(pCode *pc)
1796 {
1797
1798   pCodeUnlink(pc);
1799
1800 }
1801 #endif
1802
1803 static void AnalyzeGOTO(pCode *pc)
1804 {
1805
1806   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
1807
1808 }
1809
1810 static void AnalyzeSKIP(pCode *pc)
1811 {
1812
1813   pBranchLink(pc,findNextInstruction(pc->next));
1814   pBranchLink(pc,findNextInstruction(pc->next->next));
1815
1816 }
1817
1818 static void AnalyzeRETURN(pCode *pc)
1819 {
1820
1821   //  branch_link(pc,findFunctionEnd(pc->next));
1822
1823 }
1824
1825
1826 void AnalyzepBlock(pBlock *pb)
1827 {
1828   pCode *pc;
1829
1830   if(!pb)
1831     return;
1832
1833   /* Find all of the registers used in this pBlock */
1834   for(pc = pb->pcHead; pc; pc = pc->next) {
1835     if(pc->type == PC_OPCODE) {
1836       if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
1837
1838         /* Loop through all of the registers declared so far in
1839            this block and see if we find this new there */
1840
1841         regs *r = setFirstItem(pb->registers);
1842
1843         while(r) {
1844           if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
1845             PCOR(PCI(pc)->pcop)->r = r;
1846             break;
1847           }
1848           r = setNextItem(pb->registers);
1849         }
1850
1851         if(!r) {
1852           /* register wasn't found */
1853           r = Safe_calloc(1, sizeof(regs));
1854           memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
1855           addSet(&pb->registers, r);
1856           PCOR(PCI(pc)->pcop)->r = r;
1857           fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
1858         } else 
1859           fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
1860       }
1861     }
1862   }
1863 }
1864
1865 int OptimizepBlock(pBlock *pb)
1866 {
1867   pCode *pc;
1868   int matches =0;
1869
1870   if(!pb || !peepOptimizing)
1871     return 0;
1872
1873   fprintf(stderr," Optimizing pBlock\n");
1874
1875   for(pc = pb->pcHead; pc; pc = pc->next)
1876     matches += pCodePeepMatchRule(pc);
1877
1878   return matches;
1879
1880 }
1881 /*-----------------------------------------------------------------*/
1882 /* pBlockMergeLabels - remove the pCode labels from the pCode      */
1883 /*                     chain and put them into pBranches that are  */
1884 /*                     associated with the appropriate pCode       */
1885 /*                     instructions.                               */
1886 /*-----------------------------------------------------------------*/
1887 void pBlockMergeLabels(pBlock *pb)
1888 {
1889   pBranch *pbr;
1890   pCode *pc, *pcnext=NULL;
1891
1892   if(!pb)
1893     return;
1894
1895   for(pc = pb->pcHead; pc; pc = pc->next) {
1896
1897     if(pc->type == PC_LABEL) {
1898       if( !(pcnext = findNextInstruction(pc)) ) 
1899         return;  // Couldn't find an instruction associated with this label
1900
1901       // Unlink the pCode label from it's pCode chain
1902       if(pc->prev) 
1903         pc->prev->next = pc->next;
1904       if(pc->next)
1905         pc->next->prev = pc->prev;
1906
1907       // And link it into the instruction's pBranch labels. (Note, since
1908       // it's possible to have multiple labels associated with one instruction
1909       // we must provide a means to accomodate the additional labels. Thus
1910       // the labels are placed into the singly-linked list "label" as 
1911       // opposed to being a single member of the pCodeInstruction.)
1912
1913       _ALLOC(pbr,sizeof(pBranch));
1914       pbr->pc = pc;
1915       pbr->next = NULL;
1916
1917       pcnext->label = pBranchAppend(pcnext->label,pbr);
1918     }
1919
1920   }
1921
1922 }
1923
1924 /*-----------------------------------------------------------------*/
1925 /*-----------------------------------------------------------------*/
1926 void OptimizepCode(char dbName)
1927 {
1928 #define MAX_PASSES 4
1929
1930   int matches = 0;
1931   int passes = 0;
1932   pBlock *pb;
1933
1934   if(!the_pFile)
1935     return;
1936
1937   fprintf(stderr," Optimizing pCode\n");
1938
1939   do {
1940     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1941       if('*' == dbName || getpBlock_dbName(pb) == dbName)
1942         matches += OptimizepBlock(pb);
1943     }
1944   }
1945   while(matches && ++passes < MAX_PASSES);
1946
1947 }
1948
1949 /*-----------------------------------------------------------------*/
1950 /* AnalyzepCode - parse the pCode that has been generated and form */
1951 /*                all of the logical connections.                  */
1952 /*                                                                 */
1953 /* Essentially what's done here is that the pCode flow is          */
1954 /* determined.                                                     */
1955 /*-----------------------------------------------------------------*/
1956
1957 void AnalyzepCode(char dbName)
1958 {
1959   pBlock *pb;
1960   pCode *pc;
1961   pBranch *pbr;
1962
1963   if(!the_pFile)
1964     return;
1965
1966   fprintf(stderr," Analyzing pCode");
1967
1968   /* First, merge the labels with the instructions */
1969   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1970     if('*' == dbName || getpBlock_dbName(pb) == dbName) {
1971       pBlockMergeLabels(pb);
1972       AnalyzepBlock(pb);
1973     }
1974   }
1975
1976   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1977     if('*' == dbName || getpBlock_dbName(pb) == dbName)
1978       OptimizepBlock(pb);
1979   }
1980
1981   /* Now build the call tree.
1982      First we examine all of the pCodes for functions.
1983      Keep in mind that the function boundaries coincide
1984      with pBlock boundaries. 
1985
1986      The algorithm goes something like this:
1987      We have two nested loops. The outer loop iterates
1988      through all of the pBlocks/functions. The inner
1989      loop iterates through all of the pCodes for
1990      a given pBlock. When we begin iterating through
1991      a pBlock, the variable pc_fstart, pCode of the start
1992      of a function, is cleared. We then search for pCodes
1993      of type PC_FUNCTION. When one is encountered, we
1994      initialize pc_fstart to this and at the same time
1995      associate a new pBranch object that signifies a 
1996      branch entry. If a return is found, then this signifies
1997      a function exit point. We'll link the pCodes of these
1998      returns to the matching pc_fstart.
1999
2000      When we're done, a doubly linked list of pBranches
2001      will exist. The head of this list is stored in
2002      `the_pFile', which is the meta structure for all
2003      of the pCode. Look at the printCallTree function
2004      on how the pBranches are linked together.
2005
2006    */
2007   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2008     if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2009       pCode *pc_fstart=NULL;
2010       for(pc = pb->pcHead; pc; pc = pc->next) {
2011         if(pc->type == PC_FUNCTION) {
2012           if (PCF(pc)->fname) {
2013             // I'm not liking this....
2014             // Found the beginning of a function.
2015             _ALLOC(pbr,sizeof(pBranch));
2016             pbr->pc = pc_fstart = pc;
2017             pbr->next = NULL;
2018
2019             the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2020
2021             // Here's a better way of doing the same:
2022             addSet(&pb->function_entries, pc);
2023
2024           } else {
2025             // Found an exit point in a function, e.g. return
2026             // (Note, there may be more than one return per function)
2027             if(pc_fstart)
2028               pBranchLink(pc_fstart, pc);
2029
2030             addSet(&pb->function_exits, pc);
2031           }
2032         } else  if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2033           addSet(&pb->function_calls,pc);
2034         }
2035       }
2036     }
2037   }
2038 }
2039
2040 /*-----------------------------------------------------------------*/
2041 /* ispCodeFunction - returns true if *pc is the pCode of a         */
2042 /*                   function                                      */
2043 /*-----------------------------------------------------------------*/
2044 bool ispCodeFunction(pCode *pc)
2045 {
2046
2047   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2048     return 1;
2049
2050   return 0;
2051 }
2052
2053 /*-----------------------------------------------------------------*/
2054 /* findFunction - Search for a function by name (given the name)   */
2055 /*                in the set of all functions that are in a pBlock */
2056 /* (note - I expect this to change because I'm planning to limit   */
2057 /*  pBlock's to just one function declaration                      */
2058 /*-----------------------------------------------------------------*/
2059 pCode *findFunction(char *fname)
2060 {
2061   pBlock *pb;
2062   pCode *pc;
2063   if(!fname)
2064     return NULL;
2065
2066   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2067
2068     pc = setFirstItem(pb->function_entries);
2069     while(pc) {
2070     
2071       if((pc->type == PC_FUNCTION) &&
2072          (PCF(pc)->fname) && 
2073          (strcmp(fname, PCF(pc)->fname)==0))
2074         return pc;
2075
2076       pc = setNextItem(pb->function_entries);
2077
2078     }
2079
2080   }
2081   return NULL;
2082 }
2083
2084 void MarkUsedRegisters(set *regset)
2085 {
2086
2087   regs *r1,*r2;
2088
2089   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2090     r2 = pic14_regWithIdx(r1->rIdx);
2091     r2->isFree = 0;
2092     r2->wasUsed = 1;
2093   }
2094 }
2095
2096 void pBlockStats(FILE *of, pBlock *pb)
2097 {
2098
2099   pCode *pc;
2100   regs  *r;
2101
2102   fprintf(of,"***\n  pBlock Stats\n***\n");
2103
2104   // for now just print the first element of each set
2105   pc = setFirstItem(pb->function_entries);
2106   if(pc) {
2107     fprintf(of,"entry\n");
2108     pc->print(of,pc);
2109   }
2110   pc = setFirstItem(pb->function_exits);
2111   if(pc) {
2112     fprintf(of,"has an exit\n");
2113     pc->print(of,pc);
2114   }
2115
2116   pc = setFirstItem(pb->function_calls);
2117   if(pc) {
2118     fprintf(of,"functions called\n");
2119
2120     while(pc) {
2121       pc->print(of,pc);
2122       pc = setNextItem(pb->function_calls);
2123     }
2124   }
2125
2126   r = setFirstItem(pb->registers);
2127   if(r) {
2128     int n = elementsInSet(pb->registers);
2129
2130     fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2131
2132     while (r) {
2133       fprintf(of,"   %s\n",r->name);
2134       r = setNextItem(pb->registers);
2135     }
2136   }
2137 }
2138
2139 /*-----------------------------------------------------------------*/
2140 /*-----------------------------------------------------------------*/
2141 void sequencepCode(void)
2142 {
2143   pBlock *pb;
2144   pCode *pc;
2145
2146
2147   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2148
2149     pb->seq = GpCodeSequenceNumber+1;
2150
2151     for( pc = pb->pcHead; pc; pc = pc->next)
2152       pc->seq = ++GpCodeSequenceNumber;
2153   }
2154
2155 }
2156
2157 /*-----------------------------------------------------------------*/
2158 /*-----------------------------------------------------------------*/
2159 set *register_usage(pBlock *pb)
2160 {
2161   pCode *pc,*pcn;
2162   set *registers=NULL;
2163   set *registersInCallPath = NULL;
2164
2165   /* check recursion */
2166
2167   pc = setFirstItem(pb->function_entries);
2168
2169   if(!pc)
2170     return registers;
2171
2172   pb->visited = 1;
2173
2174   if(pc->type != PC_FUNCTION)
2175     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2176
2177   pc = setFirstItem(pb->function_calls);
2178   for( ; pc; pc = setNextItem(pb->function_calls)) {
2179
2180     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2181       char *dest = get_op(PCI(pc));
2182
2183       pcn = findFunction(dest);
2184       if(pcn) 
2185         registersInCallPath = register_usage(pcn->pb);
2186     } else
2187       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2188
2189   }
2190
2191
2192   pBlockStats(stderr,pb);  // debug
2193   if(registersInCallPath) {
2194     /* registers were used in the functions this pBlock has called */
2195     /* so now, we need to see if these collide with the ones we are */
2196     /* using here */
2197
2198     regs *r1,*r2, *newreg;
2199
2200     fprintf(stderr,"comparing registers\n");
2201
2202     r1 = setFirstItem(registersInCallPath);
2203     while(r1) {
2204
2205       r2 = setFirstItem(pb->registers);
2206
2207       while(r2) {
2208
2209         if(r2->rIdx == r1->rIdx) {
2210           newreg = pic14_findFreeReg();
2211
2212
2213           if(!newreg) {
2214             fprintf(stderr,"Bummer, no more registers.\n");
2215             exit(1);
2216           }
2217
2218           fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2219                   r1->rIdx, newreg->rIdx);
2220           r2->rIdx = newreg->rIdx;
2221           //if(r2->name) free(r2->name);
2222           r2->name = Safe_strdup(newreg->name);
2223           newreg->isFree = 0;
2224           newreg->wasUsed = 1;
2225         }
2226         r2 = setNextItem(pb->registers);
2227       }
2228
2229       r1 = setNextItem(registersInCallPath);
2230     }
2231
2232     /* Collisions have been resolved. Now free the registers in the call path */
2233     r1 = setFirstItem(registersInCallPath);
2234     while(r1) {
2235       newreg = pic14_regWithIdx(r1->rIdx);
2236       newreg->isFree = 1;
2237       r1 = setNextItem(registersInCallPath);
2238     }
2239
2240   } else
2241     MarkUsedRegisters(pb->registers);
2242
2243   registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2244
2245   if(registers) 
2246     fprintf(stderr,"returning regs\n");
2247   else
2248     fprintf(stderr,"not returning regs\n");
2249
2250   fprintf(stderr,"pBlock after register optim.\n");
2251   pBlockStats(stderr,pb);  // debug
2252
2253
2254   return registers;
2255 }
2256
2257 /*-----------------------------------------------------------------*/
2258 /* printCallTree - writes the call tree to a file                  */
2259 /*                                                                 */
2260 /*-----------------------------------------------------------------*/
2261 void pct2(FILE *of,pBlock *pb,int indent)
2262 {
2263   pCode *pc,*pcn;
2264   int i;
2265   //  set *registersInCallPath = NULL;
2266
2267   if(!of)
2268     return;// registers;
2269
2270   if(indent > 10)
2271     return; // registers;   //recursion ?
2272
2273   pc = setFirstItem(pb->function_entries);
2274
2275   if(!pc)
2276     return;
2277
2278   pb->visited = 0;
2279
2280   for(i=0;i<indent;i++)   // Indentation
2281     fputc(' ',of);
2282
2283   if(pc->type == PC_FUNCTION)
2284     fprintf(of,"%s\n",PCF(pc)->fname);
2285   else
2286     return;  // ???
2287
2288
2289   pc = setFirstItem(pb->function_calls);
2290   for( ; pc; pc = setNextItem(pb->function_calls)) {
2291
2292     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2293       char *dest = get_op(PCI(pc));
2294
2295       pcn = findFunction(dest);
2296       if(pcn) 
2297         pct2(of,pcn->pb,indent+1);
2298     } else
2299       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2300
2301   }
2302
2303
2304 }
2305
2306 #if 0
2307   fprintf(stderr,"pBlock before register optim.\n");
2308   pBlockStats(stderr,pb);  // debug
2309
2310   if(registersInCallPath) {
2311     /* registers were used in the functions this pBlock has called */
2312     /* so now, we need to see if these collide with the ones we are using here */
2313
2314     regs *r1,*r2, *newreg;
2315
2316     fprintf(stderr,"comparing registers\n");
2317
2318     r1 = setFirstItem(registersInCallPath);
2319     while(r1) {
2320
2321       r2 = setFirstItem(pb->registers);
2322
2323       while(r2) {
2324
2325         if(r2->rIdx == r1->rIdx) {
2326           newreg = pic14_findFreeReg();
2327
2328
2329           if(!newreg) {
2330             fprintf(stderr,"Bummer, no more registers.\n");
2331             exit(1);
2332           }
2333
2334           fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2335                   r1->rIdx, newreg->rIdx);
2336           r2->rIdx = newreg->rIdx;
2337           //if(r2->name) free(r2->name);
2338           r2->name = Safe_strdup(newreg->name);
2339           newreg->isFree = 0;
2340           newreg->wasUsed = 1;
2341         }
2342         r2 = setNextItem(pb->registers);
2343       }
2344
2345       r1 = setNextItem(registersInCallPath);
2346     }
2347
2348     /* Collisions have been resolved. Now free the registers in the call path */
2349     r1 = setFirstItem(registersInCallPath);
2350     while(r1) {
2351       newreg = pic14_regWithIdx(r1->rIdx);
2352       newreg->isFree = 1;
2353       r1 = setNextItem(registersInCallPath);
2354     }
2355
2356   } else
2357     MarkUsedRegisters(pb->registers);
2358
2359   registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2360
2361   if(registers) 
2362     fprintf(stderr,"returning regs\n");
2363   else
2364     fprintf(stderr,"not returning regs\n");
2365
2366   fprintf(stderr,"pBlock after register optim.\n");
2367   pBlockStats(stderr,pb);  // debug
2368
2369
2370   return registers;
2371
2372 #endif
2373
2374
2375 /*-----------------------------------------------------------------*/
2376 /* printCallTree - writes the call tree to a file                  */
2377 /*                                                                 */
2378 /*-----------------------------------------------------------------*/
2379
2380 void printCallTree(FILE *of)
2381 {
2382   pBranch *pbr;
2383   pBlock  *pb;
2384   pCode   *pc;
2385
2386   if(!the_pFile)
2387     return;
2388
2389   if(!of)
2390     of = stderr;
2391
2392   fprintf(of, "\npBlock statistics\n");
2393   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
2394     pBlockStats(stderr,pb);
2395
2396
2397
2398   fprintf(of,"Call Tree\n");
2399   pbr = the_pFile->functions;
2400   while(pbr) {
2401     if(pbr->pc) {
2402       pc = pbr->pc;
2403       if(!ispCodeFunction(pc))
2404         fprintf(of,"bug in call tree");
2405
2406
2407       fprintf(of,"Function: %s\n", PCF(pc)->fname);
2408
2409       while(pc->next && !ispCodeFunction(pc->next)) {
2410         pc = pc->next;
2411         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2412           fprintf(of,"\t%s\n",get_op(PCI(pc)));
2413       }
2414     }
2415
2416     pbr = pbr->next;
2417   }
2418
2419
2420   /* Re-allocate the registers so that there are no collisions
2421    * between local variables when one function call another */
2422
2423   pic14_deallocateAllRegs();
2424
2425   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2426     if(!pb->visited)
2427       register_usage(pb);
2428   }
2429
2430   fprintf(of,"\n**************\n\na better call tree\n");
2431   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2432     if(pb->visited)
2433       pct2(of,pb,0);
2434   }
2435
2436   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2437     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
2438   }
2439 }