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