Fixed some pointer bugs. Added option to selectively enable/disable function inlining.
[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 "pcodeflow.h"
29 #include "ralloc.h"
30 #include "device.h"
31
32 #if defined(__BORLANDC__) || defined(_MSC_VER)
33 #define STRCASECMP stricmp
34 #else
35 #define STRCASECMP strcasecmp
36 #endif
37
38 /****************************************************************/
39 /****************************************************************/
40
41 peepCommand peepCommands[] = {
42
43   {NOTBITSKIP, "_NOTBITSKIP_"},
44   {BITSKIP, "_BITSKIP_"},
45   {INVERTBITSKIP, "_INVERTBITSKIP_"},
46
47   {-1, NULL}
48 };
49
50
51
52 // Eventually this will go into device dependent files:
53 pCodeOpReg pc_status    = {{PO_STATUS,  "STATUS"}, -1, NULL,0,NULL};
54 pCodeOpReg pc_indf      = {{PO_INDF,    "INDF"}, -1, NULL,0,NULL};
55 pCodeOpReg pc_fsr       = {{PO_FSR,     "FSR"}, -1, NULL,0,NULL};
56 pCodeOpReg pc_intcon    = {{PO_INTCON,  ""}, -1, NULL,0,NULL};
57 pCodeOpReg pc_pcl       = {{PO_PCL,     "PCL"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_pclath    = {{PO_PCLATH,  "PCLATH"}, -1, NULL,0,NULL};
59
60 pCodeOpReg pc_kzero     = {{PO_GPR_REGISTER,  "KZ"}, -1, NULL,0,NULL};
61 pCodeOpReg pc_wsave     = {{PO_GPR_REGISTER,  "WSAVE"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_ssave     = {{PO_GPR_REGISTER,  "SSAVE"}, -1, NULL,0,NULL};
63
64 static int mnemonics_initialized = 0;
65
66
67 static hTab *pic14MnemonicsHash = NULL;
68 static hTab *pic14pCodePeepCommandsHash = NULL;
69
70
71
72 static pFile *the_pFile = NULL;
73
74 /* Hardcoded flags to change the behavior of the PIC port */
75 static int peepOptimizing = 1;        /* run the peephole optimizer if nonzero */
76 static int functionInlining = 1;      /* inline functions if nonzero */
77
78 static int GpCodeSequenceNumber = 1;
79 static int GpcFlowSeq = 1;
80
81 #define isPCI(x)        ((PCODE(x)->type == PC_OPCODE))
82 #define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isBranch)
83 #define isPCI_SKIP(x)   ((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isSkip)
84 #define isPCI_BITSKIP(x)((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isSkip && PCI(x)->isBitInst)
85 #define isPCFL(x)       ((PCODE(x)->type == PC_FLOW))
86 #define isPCF(x)        ((PCODE(x)->type == PC_FUNCTION))
87 #define isPCL(x)        ((PCODE(x)->type == PC_LABEL))
88 #define isPCW(x)        ((PCODE(x)->type == PC_WILD))
89 #define isPCCS(x)       ((PCODE(x)->type == PC_CSOURCE))
90
91 #define isCALL(x)       ((isPCI(x)) && (PCI(x)->op == POC_CALL))
92 #define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS)
93
94 #define isPCOLAB(x)     ((PCOP(x)->type) == PO_LABEL)
95
96 /****************************************************************/
97 /*                      Forward declarations                    */
98 /****************************************************************/
99
100 static void unlinkPC(pCode *pc);
101 #if 0
102 static void genericAnalyze(pCode *pc);
103 static void AnalyzeGOTO(pCode *pc);
104 static void AnalyzeSKIP(pCode *pc);
105 static void AnalyzeRETURN(pCode *pc);
106 #endif
107
108 static void genericDestruct(pCode *pc);
109 static void genericPrint(FILE *of,pCode *pc);
110
111 static void pCodePrintLabel(FILE *of, pCode *pc);
112 static void pCodePrintFunction(FILE *of, pCode *pc);
113 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
114 static char *get_op_from_instruction( pCodeInstruction *pcc);
115 char *get_op( pCodeOp *pcop);
116 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
117 int pCodePeepMatchRule(pCode *pc);
118 void pBlockStats(FILE *of, pBlock *pb);
119 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
120 extern pCodeOp *popCopyReg(pCodeOpReg *pc);
121 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
122
123 pCodeInstruction pciADDWF = {
124   {PC_OPCODE, NULL, NULL, 0, NULL, 
125    //   genericAnalyze,
126    genericDestruct,
127    genericPrint},
128   POC_ADDWF,
129   "ADDWF",
130   NULL, // from branch
131   NULL, // to branch
132   NULL, // label
133   NULL, // operand
134   NULL, // flow block
135   NULL, // C source 
136   2,    // num ops
137   1,0,  // dest, bit instruction
138   0,0,  // branch, skip
139   POC_NOP,
140   (PCC_W | PCC_REGISTER),   // inCond
141   (PCC_REGISTER | PCC_Z) // outCond
142 };
143
144 pCodeInstruction pciADDFW = {
145   {PC_OPCODE, NULL, NULL, 0, NULL, 
146    //   genericAnalyze,
147    genericDestruct,
148    genericPrint},
149   POC_ADDFW,
150   "ADDWF",
151   NULL, // from branch
152   NULL, // to branch
153   NULL, // label
154   NULL, // operand
155   NULL, // flow block
156   NULL, // C source 
157   2,    // num ops
158   0,0,  // dest, bit instruction
159   0,0,  // branch, skip
160   POC_NOP,
161   (PCC_W | PCC_REGISTER),   // inCond
162   (PCC_W | PCC_Z) // outCond
163 };
164
165 pCodeInstruction pciADDLW = {
166   {PC_OPCODE, NULL, NULL, 0, NULL, 
167    //   genericAnalyze,
168    genericDestruct,
169    genericPrint},
170   POC_ADDLW,
171   "ADDLW",
172   NULL, // from branch
173   NULL, // to branch
174   NULL, // label
175   NULL, // operand
176   NULL, // flow block
177   NULL, // C source 
178   1,    // num ops
179   0,0,  // dest, bit instruction
180   0,0,  // branch, skip
181   POC_NOP,
182   PCC_W,   // inCond
183   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
184 };
185
186 pCodeInstruction pciANDLW = {
187   {PC_OPCODE, NULL, NULL, 0, NULL, 
188    //   genericAnalyze,
189    genericDestruct,
190    genericPrint},
191   POC_ANDLW,
192   "ANDLW",
193   NULL, // from branch
194   NULL, // to branch
195   NULL, // label
196   NULL, // operand
197   NULL, // flow block
198   NULL, // C source 
199   1,    // num ops
200   0,0,  // dest, bit instruction
201   0,0,  // branch, skip
202   POC_NOP,
203   PCC_W,   // inCond
204   (PCC_W | PCC_Z) // outCond
205 };
206
207 pCodeInstruction pciANDWF = {
208   {PC_OPCODE, NULL, NULL, 0, NULL, 
209    //   genericAnalyze,
210    genericDestruct,
211    genericPrint},
212   POC_ANDWF,
213   "ANDWF",
214   NULL, // from branch
215   NULL, // to branch
216   NULL, // label
217   NULL, // operand
218   NULL, // flow block
219   NULL, // C source 
220   2,    // num ops
221   1,0,  // dest, bit instruction
222   0,0,  // branch, skip
223   POC_NOP,
224   (PCC_W | PCC_REGISTER),   // inCond
225   (PCC_REGISTER | PCC_Z) // outCond
226 };
227
228 pCodeInstruction pciANDFW = {
229   {PC_OPCODE, NULL, NULL, 0, NULL, 
230    //   genericAnalyze,
231    genericDestruct,
232    genericPrint},
233   POC_ANDFW,
234   "ANDWF",
235   NULL, // from branch
236   NULL, // to branch
237   NULL, // label
238   NULL, // operand
239   NULL, // flow block
240   NULL, // C source 
241   2,    // num ops
242   0,0,  // dest, bit instruction
243   0,0,  // branch, skip
244   POC_NOP,
245   (PCC_W | PCC_REGISTER),   // inCond
246   (PCC_W | PCC_Z) // outCond
247 };
248
249 pCodeInstruction pciBCF = {
250   {PC_OPCODE, NULL, NULL, 0, NULL, 
251    //   genericAnalyze,
252    genericDestruct,
253    genericPrint},
254   POC_BCF,
255   "BCF",
256   NULL, // from branch
257   NULL, // to branch
258   NULL, // label
259   NULL, // operand
260   NULL, // flow block
261   NULL, // C source 
262   2,    // num ops
263   1,1,  // dest, bit instruction
264   0,0,  // branch, skip
265   POC_BSF,
266   PCC_REGISTER,   // inCond
267   PCC_REGISTER // outCond
268 };
269
270 pCodeInstruction pciBSF = {
271   {PC_OPCODE, NULL, NULL, 0, NULL, 
272    //   genericAnalyze,
273    genericDestruct,
274    genericPrint},
275   POC_BSF,
276   "BSF",
277   NULL, // from branch
278   NULL, // to branch
279   NULL, // label
280   NULL, // operand
281   NULL, // flow block
282   NULL, // C source 
283   2,    // num ops
284   1,1,  // dest, bit instruction
285   0,0,  // branch, skip
286   POC_BCF,
287   PCC_REGISTER,   // inCond
288   PCC_REGISTER // outCond
289 };
290
291 pCodeInstruction pciBTFSC = {
292   {PC_OPCODE, NULL, NULL, 0, NULL, 
293    //   AnalyzeSKIP,
294    genericDestruct,
295    genericPrint},
296   POC_BTFSC,
297   "BTFSC",
298   NULL, // from branch
299   NULL, // to branch
300   NULL, // label
301   NULL, // operand
302   NULL, // flow block
303   NULL, // C source 
304   2,    // num ops
305   0,1,  // dest, bit instruction
306   1,1,  // branch, skip
307   POC_BTFSS,
308   PCC_REGISTER,   // inCond
309   PCC_NONE // outCond
310 };
311
312 pCodeInstruction pciBTFSS = {
313   {PC_OPCODE, NULL, NULL, 0, NULL, 
314    //   AnalyzeSKIP,
315    genericDestruct,
316    genericPrint},
317   POC_BTFSS,
318   "BTFSS",
319   NULL, // from branch
320   NULL, // to branch
321   NULL, // label
322   NULL, // operand
323   NULL, // flow block
324   NULL, // C source 
325   2,    // num ops
326   0,1,  // dest, bit instruction
327   1,1,  // branch, skip
328   POC_BTFSC,
329   PCC_REGISTER,   // inCond
330   PCC_NONE // outCond
331 };
332
333 pCodeInstruction pciCALL = {
334   {PC_OPCODE, NULL, NULL, 0, NULL, 
335    //   genericAnalyze,
336    genericDestruct,
337    genericPrint},
338   POC_CALL,
339   "CALL",
340   NULL, // from branch
341   NULL, // to branch
342   NULL, // label
343   NULL, // operand
344   NULL, // flow block
345   NULL, // C source 
346   1,    // num ops
347   0,0,  // dest, bit instruction
348   1,0,  // branch, skip
349   POC_NOP,
350   PCC_NONE, // inCond
351   PCC_NONE  // outCond
352 };
353
354 pCodeInstruction pciCOMF = {
355   {PC_OPCODE, NULL, NULL, 0, NULL, 
356    //   genericAnalyze,
357    genericDestruct,
358    genericPrint},
359   POC_COMF,
360   "COMF",
361   NULL, // from branch
362   NULL, // to branch
363   NULL, // label
364   NULL, // operand
365   NULL, // flow block
366   NULL, // C source 
367   2,    // num ops
368   1,0,  // dest, bit instruction
369   0,0,  // branch, skip
370   POC_NOP,
371   PCC_REGISTER,  // inCond
372   PCC_REGISTER   // outCond
373 };
374
375 pCodeInstruction pciCOMFW = {
376   {PC_OPCODE, NULL, NULL, 0, NULL, 
377    //   genericAnalyze,
378    genericDestruct,
379    genericPrint},
380   POC_COMFW,
381   "COMF",
382   NULL, // from branch
383   NULL, // to branch
384   NULL, // label
385   NULL, // operand
386   NULL, // flow block
387   NULL, // C source 
388   2,    // num ops
389   0,0,  // dest, bit instruction
390   0,0,  // branch, skip
391   POC_NOP,
392   PCC_REGISTER,  // inCond
393   PCC_W   // outCond
394 };
395
396 pCodeInstruction pciCLRF = {
397   {PC_OPCODE, NULL, NULL, 0, NULL, 
398    //   genericAnalyze,
399    genericDestruct,
400    genericPrint},
401   POC_CLRF,
402   "CLRF",
403   NULL, // from branch
404   NULL, // to branch
405   NULL, // label
406   NULL, // operand
407   NULL, // flow block
408   NULL, // C source 
409   1,    // num ops
410   0,0,  // dest, bit instruction
411   0,0,  // branch, skip
412   POC_NOP,
413   PCC_REGISTER, // inCond
414   PCC_REGISTER  // outCond
415 };
416
417 pCodeInstruction pciCLRW = {
418   {PC_OPCODE, NULL, NULL, 0, NULL, 
419    //   genericAnalyze,
420    genericDestruct,
421    genericPrint},
422   POC_CLRW,
423   "CLRW",
424   NULL, // from branch
425   NULL, // to branch
426   NULL, // label
427   NULL, // operand
428   NULL, // flow block
429   NULL, // C source 
430   0,    // num ops
431   0,0,  // dest, bit instruction
432   0,0,  // branch, skip
433   POC_NOP,
434   PCC_W, // inCond
435   PCC_W  // outCond
436 };
437
438 pCodeInstruction pciDECF = {
439   {PC_OPCODE, NULL, NULL, 0, NULL, 
440    //   genericAnalyze,
441    genericDestruct,
442    genericPrint},
443   POC_DECF,
444   "DECF",
445   NULL, // from branch
446   NULL, // to branch
447   NULL, // label
448   NULL, // operand
449   NULL, // flow block
450   NULL, // C source 
451   2,    // num ops
452   1,0,  // dest, bit instruction
453   0,0,  // branch, skip
454   POC_NOP,
455   PCC_REGISTER,   // inCond
456   PCC_REGISTER    // outCond
457 };
458
459 pCodeInstruction pciDECFW = {
460   {PC_OPCODE, NULL, NULL, 0, NULL, 
461    //   genericAnalyze,
462    genericDestruct,
463    genericPrint},
464   POC_DECFW,
465   "DECF",
466   NULL, // from branch
467   NULL, // to branch
468   NULL, // label
469   NULL, // operand
470   NULL, // flow block
471   NULL, // C source 
472   2,    // num ops
473   0,0,  // dest, bit instruction
474   0,0,  // branch, skip
475   POC_NOP,
476   PCC_REGISTER,   // inCond
477   PCC_W    // outCond
478 };
479
480 pCodeInstruction pciDECFSZ = {
481   {PC_OPCODE, NULL, NULL, 0, NULL, 
482    //   AnalyzeSKIP,
483    genericDestruct,
484    genericPrint},
485   POC_DECFSZ,
486   "DECFSZ",
487   NULL, // from branch
488   NULL, // to branch
489   NULL, // label
490   NULL, // operand
491   NULL, // flow block
492   NULL, // C source 
493   2,    // num ops
494   1,0,  // dest, bit instruction
495   1,1,  // branch, skip
496   POC_NOP,
497   PCC_REGISTER,   // inCond
498   PCC_REGISTER    // outCond
499 };
500
501 pCodeInstruction pciDECFSZW = {
502   {PC_OPCODE, NULL, NULL, 0, NULL, 
503    //   AnalyzeSKIP,
504    genericDestruct,
505    genericPrint},
506   POC_DECFSZW,
507   "DECFSZ",
508   NULL, // from branch
509   NULL, // to branch
510   NULL, // label
511   NULL, // operand
512   NULL, // flow block
513   NULL, // C source 
514   2,    // num ops
515   0,0,  // dest, bit instruction
516   1,1,  // branch, skip
517   POC_NOP,
518   PCC_REGISTER,   // inCond
519   PCC_W           // outCond
520 };
521
522 pCodeInstruction pciGOTO = {
523   {PC_OPCODE, NULL, NULL, 0, NULL, 
524    //   AnalyzeGOTO,
525    genericDestruct,
526    genericPrint},
527   POC_GOTO,
528   "GOTO",
529   NULL, // from branch
530   NULL, // to branch
531   NULL, // label
532   NULL, // operand
533   NULL, // flow block
534   NULL, // C source 
535   1,    // num ops
536   0,0,  // dest, bit instruction
537   1,0,  // branch, skip
538   POC_NOP,
539   PCC_NONE,   // inCond
540   PCC_NONE    // outCond
541 };
542
543 pCodeInstruction pciINCF = {
544   {PC_OPCODE, NULL, NULL, 0, NULL, 
545    //   genericAnalyze,
546    genericDestruct,
547    genericPrint},
548   POC_INCF,
549   "INCF",
550   NULL, // from branch
551   NULL, // to branch
552   NULL, // label
553   NULL, // operand
554   NULL, // flow block
555   NULL, // C source 
556   2,    // num ops
557   1,0,  // dest, bit instruction
558   0,0,  // branch, skip
559   POC_NOP,
560   PCC_REGISTER,   // inCond
561   PCC_REGISTER    // outCond
562 };
563
564 pCodeInstruction pciINCFW = {
565   {PC_OPCODE, NULL, NULL, 0, NULL, 
566    //   genericAnalyze,
567    genericDestruct,
568    genericPrint},
569   POC_INCFW,
570   "INCF",
571   NULL, // from branch
572   NULL, // to branch
573   NULL, // label
574   NULL, // operand
575   NULL, // flow block
576   NULL, // C source 
577   2,    // num ops
578   0,0,  // dest, bit instruction
579   0,0,  // branch, skip
580   POC_NOP,
581   PCC_REGISTER,   // inCond
582   PCC_W    // outCond
583 };
584
585 pCodeInstruction pciINCFSZ = {
586   {PC_OPCODE, NULL, NULL, 0, NULL, 
587    //   AnalyzeSKIP,
588    genericDestruct,
589    genericPrint},
590   POC_INCFSZ,
591   "INCFSZ",
592   NULL, // from branch
593   NULL, // to branch
594   NULL, // label
595   NULL, // operand
596   NULL, // flow block
597   NULL, // C source 
598   2,    // num ops
599   1,0,  // dest, bit instruction
600   1,1,  // branch, skip
601   POC_NOP,
602   PCC_REGISTER,   // inCond
603   PCC_REGISTER    // outCond
604 };
605
606 pCodeInstruction pciINCFSZW = {
607   {PC_OPCODE, NULL, NULL, 0, NULL, 
608    //   AnalyzeSKIP,
609    genericDestruct,
610    genericPrint},
611   POC_INCFSZW,
612   "INCFSZ",
613   NULL, // from branch
614   NULL, // to branch
615   NULL, // label
616   NULL, // operand
617   NULL, // flow block
618   NULL, // C source 
619   2,    // num ops
620   0,0,  // dest, bit instruction
621   1,1,  // branch, skip
622   POC_NOP,
623   PCC_REGISTER,   // inCond
624   PCC_W           // outCond
625 };
626
627 pCodeInstruction pciIORWF = {
628   {PC_OPCODE, NULL, NULL, 0, NULL, 
629    //   genericAnalyze,
630    genericDestruct,
631    genericPrint},
632   POC_IORWF,
633   "IORWF",
634   NULL, // from branch
635   NULL, // to branch
636   NULL, // label
637   NULL, // operand
638   NULL, // flow block
639   NULL, // C source 
640   2,    // num ops
641   1,0,  // dest, bit instruction
642   0,0,  // branch, skip
643   POC_NOP,
644   (PCC_W | PCC_REGISTER),   // inCond
645   (PCC_REGISTER | PCC_Z) // outCond
646 };
647
648 pCodeInstruction pciIORFW = {
649   {PC_OPCODE, NULL, NULL, 0, NULL, 
650    //   genericAnalyze,
651    genericDestruct,
652    genericPrint},
653   POC_IORFW,
654   "IORWF",
655   NULL, // from branch
656   NULL, // to branch
657   NULL, // label
658   NULL, // operand
659   NULL, // flow block
660   NULL, // C source 
661   2,    // num ops
662   0,0,  // dest, bit instruction
663   0,0,  // branch, skip
664   POC_NOP,
665   (PCC_W | PCC_REGISTER),   // inCond
666   (PCC_W | PCC_Z) // outCond
667 };
668
669 pCodeInstruction pciIORLW = {
670   {PC_OPCODE, NULL, NULL, 0, NULL, 
671    //   genericAnalyze,
672    genericDestruct,
673    genericPrint},
674   POC_IORLW,
675   "IORLW",
676   NULL, // from branch
677   NULL, // to branch
678   NULL, // label
679   NULL, // operand
680   NULL, // flow block
681   NULL, // C source 
682   1,    // num ops
683   0,0,  // dest, bit instruction
684   0,0,  // branch, skip
685   POC_NOP,
686   PCC_W,   // inCond
687   (PCC_W | PCC_Z) // outCond
688 };
689
690 pCodeInstruction pciMOVF = {
691   {PC_OPCODE, NULL, NULL, 0, NULL, 
692    //   genericAnalyze,
693    genericDestruct,
694    genericPrint},
695   POC_MOVF,
696   "MOVF",
697   NULL, // from branch
698   NULL, // to branch
699   NULL, // label
700   NULL, // operand
701   NULL, // flow block
702   NULL, // C source 
703   2,    // num ops
704   1,0,  // dest, bit instruction
705   0,0,  // branch, skip
706   POC_NOP,
707   PCC_REGISTER,   // inCond
708   PCC_Z // outCond
709 };
710
711 pCodeInstruction pciMOVFW = {
712   {PC_OPCODE, NULL, NULL, 0, NULL, 
713    //   genericAnalyze,
714    genericDestruct,
715    genericPrint},
716   POC_MOVFW,
717   "MOVF",
718   NULL, // from branch
719   NULL, // to branch
720   NULL, // label
721   NULL, // operand
722   NULL, // flow block
723   NULL, // C source 
724   2,    // num ops
725   0,0,  // dest, bit instruction
726   0,0,  // branch, skip
727   POC_NOP,
728   PCC_REGISTER,   // inCond
729   (PCC_W | PCC_Z) // outCond
730 };
731
732 pCodeInstruction pciMOVWF = {
733   {PC_OPCODE, NULL, NULL, 0, NULL, 
734    //   genericAnalyze,
735    genericDestruct,
736    genericPrint},
737   POC_MOVWF,
738   "MOVWF",
739   NULL, // from branch
740   NULL, // to branch
741   NULL, // label
742   NULL, // operand
743   NULL, // flow block
744   NULL, // C source 
745   1,    // num ops
746   0,0,  // dest, bit instruction
747   0,0,  // branch, skip
748   POC_NOP,
749   PCC_W,   // inCond
750   PCC_REGISTER // outCond
751 };
752
753 pCodeInstruction pciMOVLW = {
754   {PC_OPCODE, NULL, NULL, 0, NULL, 
755    //   genericAnalyze,
756    genericDestruct,
757    genericPrint},
758   POC_MOVLW,
759   "MOVLW",
760   NULL, // from branch
761   NULL, // to branch
762   NULL, // label
763   NULL, // operand
764   NULL, // flow block
765   NULL, // C source 
766   1,    // num ops
767   0,0,  // dest, bit instruction
768   0,0,  // branch, skip
769   POC_NOP,
770   PCC_NONE,   // inCond
771   PCC_W // outCond
772 };
773
774 pCodeInstruction pciNOP = {
775   {PC_OPCODE, NULL, NULL, 0, NULL, 
776    genericDestruct,
777    genericPrint},
778   POC_NOP,
779   "NOP",
780   NULL, // from branch
781   NULL, // to branch
782   NULL, // label
783   NULL, // operand
784   NULL, // flow block
785   NULL, // C source 
786   0,    // num ops
787   0,0,  // dest, bit instruction
788   0,0,  // branch, skip
789   POC_NOP,
790   PCC_NONE,   // inCond
791   PCC_NONE // outCond
792 };
793
794 pCodeInstruction pciRETFIE = {
795   {PC_OPCODE, NULL, NULL, 0, NULL, 
796    //   AnalyzeRETURN,
797    genericDestruct,
798    genericPrint},
799   POC_RETFIE,
800   "RETFIE",
801   NULL, // from branch
802   NULL, // to branch
803   NULL, // label
804   NULL, // operand
805   NULL, // flow block
806   NULL, // C source 
807   0,    // num ops
808   0,0,  // dest, bit instruction
809   1,0,  // branch, skip
810   POC_NOP,
811   PCC_NONE,   // inCond
812   PCC_NONE // outCond (not true... affects the GIE bit too)
813 };
814
815 pCodeInstruction pciRETLW = {
816   {PC_OPCODE, NULL, NULL, 0, NULL, 
817    //   AnalyzeRETURN,
818    genericDestruct,
819    genericPrint},
820   POC_RETLW,
821   "RETLW",
822   NULL, // from branch
823   NULL, // to branch
824   NULL, // label
825   NULL, // operand
826   NULL, // flow block
827   NULL, // C source 
828   1,    // num ops
829   0,0,  // dest, bit instruction
830   1,0,  // branch, skip
831   POC_NOP,
832   PCC_NONE,   // inCond
833   PCC_W // outCond
834 };
835
836 pCodeInstruction pciRETURN = {
837   {PC_OPCODE, NULL, NULL, 0, NULL, 
838    //   AnalyzeRETURN,
839    genericDestruct,
840    genericPrint},
841   POC_RETURN,
842   "RETURN",
843   NULL, // from branch
844   NULL, // to branch
845   NULL, // label
846   NULL, // operand
847   NULL, // flow block
848   NULL, // C source 
849   0,    // num ops
850   0,0,  // dest, bit instruction
851   1,0,  // branch, skip
852   POC_NOP,
853   PCC_NONE,   // inCond
854   PCC_NONE // outCond
855 };
856
857 pCodeInstruction pciRLF = {
858   {PC_OPCODE, NULL, NULL, 0, NULL, 
859    //   genericAnalyze,
860    genericDestruct,
861    genericPrint},
862   POC_RLF,
863   "RLF",
864   NULL, // from branch
865   NULL, // to branch
866   NULL, // label
867   NULL, // operand
868   NULL, // flow block
869   NULL, // C source 
870   2,    // num ops
871   1,0,  // dest, bit instruction
872   0,0,  // branch, skip
873   POC_NOP,
874   (PCC_C | PCC_REGISTER),   // inCond
875   (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
876 };
877
878 pCodeInstruction pciRLFW = {
879   {PC_OPCODE, NULL, NULL, 0, NULL, 
880    //   genericAnalyze,
881    genericDestruct,
882    genericPrint},
883   POC_RLFW,
884   "RLF",
885   NULL, // from branch
886   NULL, // to branch
887   NULL, // label
888   NULL, // operand
889   NULL, // flow block
890   NULL, // C source 
891   2,    // num ops
892   0,0,  // dest, bit instruction
893   0,0,  // branch, skip
894   POC_NOP,
895   (PCC_C | PCC_REGISTER),   // inCond
896   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
897 };
898
899 pCodeInstruction pciRRF = {
900   {PC_OPCODE, NULL, NULL, 0, NULL, 
901    //   genericAnalyze,
902    genericDestruct,
903    genericPrint},
904   POC_RRF,
905   "RRF",
906   NULL, // from branch
907   NULL, // to branch
908   NULL, // label
909   NULL, // operand
910   NULL, // flow block
911   NULL, // C source 
912   2,    // num ops
913   1,0,  // dest, bit instruction
914   0,0,  // branch, skip
915   POC_NOP,
916   (PCC_C | PCC_REGISTER),   // inCond
917   (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
918 };
919
920 pCodeInstruction pciRRFW = {
921   {PC_OPCODE, NULL, NULL, 0, NULL, 
922    //   genericAnalyze,
923    genericDestruct,
924    genericPrint},
925   POC_RRFW,
926   "RRF",
927   NULL, // from branch
928   NULL, // to branch
929   NULL, // label
930   NULL, // operand
931   NULL, // flow block
932   NULL, // C source 
933   2,    // num ops
934   0,0,  // dest, bit instruction
935   0,0,  // branch, skip
936   POC_NOP,
937   (PCC_C | PCC_REGISTER),   // inCond
938   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
939 };
940
941 pCodeInstruction pciSUBWF = {
942   {PC_OPCODE, NULL, NULL, 0, NULL, 
943    //   genericAnalyze,
944    genericDestruct,
945    genericPrint},
946   POC_SUBWF,
947   "SUBWF",
948   NULL, // from branch
949   NULL, // to branch
950   NULL, // label
951   NULL, // operand
952   NULL, // flow block
953   NULL, // C source 
954   2,    // num ops
955   1,0,  // dest, bit instruction
956   0,0,  // branch, skip
957   POC_NOP,
958   (PCC_W | PCC_REGISTER),   // inCond
959   (PCC_REGISTER | PCC_Z) // outCond
960 };
961
962 pCodeInstruction pciSUBFW = {
963   {PC_OPCODE, NULL, NULL, 0, NULL, 
964    //   genericAnalyze,
965    genericDestruct,
966    genericPrint},
967   POC_SUBFW,
968   "SUBWF",
969   NULL, // from branch
970   NULL, // to branch
971   NULL, // label
972   NULL, // operand
973   NULL, // flow block
974   NULL, // C source 
975   2,    // num ops
976   0,0,  // dest, bit instruction
977   0,0,  // branch, skip
978   POC_NOP,
979   (PCC_W | PCC_REGISTER),   // inCond
980   (PCC_W | PCC_Z) // outCond
981 };
982
983 pCodeInstruction pciSUBLW = {
984   {PC_OPCODE, NULL, NULL, 0, NULL, 
985    //   genericAnalyze,
986    genericDestruct,
987    genericPrint},
988   POC_SUBLW,
989   "SUBLW",
990   NULL, // from branch
991   NULL, // to branch
992   NULL, // label
993   NULL, // operand
994   NULL, // flow block
995   NULL, // C source 
996   1,    // num ops
997   0,0,  // dest, bit instruction
998   0,0,  // branch, skip
999   POC_NOP,
1000   PCC_W,   // inCond
1001   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1002 };
1003
1004 pCodeInstruction pciSWAPF = {
1005   {PC_OPCODE, NULL, NULL, 0, NULL, 
1006    //   genericAnalyze,
1007    genericDestruct,
1008    genericPrint},
1009   POC_SWAPF,
1010   "SWAPF",
1011   NULL, // from branch
1012   NULL, // to branch
1013   NULL, // label
1014   NULL, // operand
1015   NULL, // flow block
1016   NULL, // C source 
1017   2,    // num ops
1018   1,0,  // dest, bit instruction
1019   0,0,  // branch, skip
1020   POC_NOP,
1021   (PCC_REGISTER),   // inCond
1022   (PCC_REGISTER) // outCond
1023 };
1024
1025 pCodeInstruction pciSWAPFW = {
1026   {PC_OPCODE, NULL, NULL, 0, NULL, 
1027    //   genericAnalyze,
1028    genericDestruct,
1029    genericPrint},
1030   POC_SWAPFW,
1031   "SWAPF",
1032   NULL, // from branch
1033   NULL, // to branch
1034   NULL, // label
1035   NULL, // operand
1036   NULL, // flow block
1037   NULL, // C source 
1038   2,    // num ops
1039   0,0,  // dest, bit instruction
1040   0,0,  // branch, skip
1041   POC_NOP,
1042   (PCC_REGISTER),   // inCond
1043   (PCC_W) // outCond
1044 };
1045
1046 pCodeInstruction pciTRIS = {
1047   {PC_OPCODE, NULL, NULL, 0, NULL, 
1048    //   genericAnalyze,
1049    genericDestruct,
1050    genericPrint},
1051   POC_TRIS,
1052   "TRIS",
1053   NULL, // from branch
1054   NULL, // to branch
1055   NULL, // label
1056   NULL, // operand
1057   NULL, // flow block
1058   NULL, // C source 
1059   1,    // num ops
1060   0,0,  // dest, bit instruction
1061   0,0,  // branch, skip
1062   POC_NOP,
1063   PCC_NONE,   // inCond
1064   PCC_REGISTER // outCond
1065 };
1066
1067 pCodeInstruction pciXORWF = {
1068   {PC_OPCODE, NULL, NULL, 0, NULL, 
1069    //   genericAnalyze,
1070    genericDestruct,
1071    genericPrint},
1072   POC_XORWF,
1073   "XORWF",
1074   NULL, // from branch
1075   NULL, // to branch
1076   NULL, // label
1077   NULL, // operand
1078   NULL, // flow block
1079   NULL, // C source 
1080   2,    // num ops
1081   1,0,  // dest, bit instruction
1082   0,0,  // branch, skip
1083   POC_NOP,
1084   (PCC_W | PCC_REGISTER),   // inCond
1085   (PCC_REGISTER | PCC_Z) // outCond
1086 };
1087
1088 pCodeInstruction pciXORFW = {
1089   {PC_OPCODE, NULL, NULL, 0, NULL, 
1090    //   genericAnalyze,
1091    genericDestruct,
1092    genericPrint},
1093   POC_XORFW,
1094   "XORWF",
1095   NULL, // from branch
1096   NULL, // to branch
1097   NULL, // label
1098   NULL, // operand
1099   NULL, // flow block
1100   NULL, // C source 
1101   2,    // num ops
1102   0,0,  // dest, bit instruction
1103   0,0,  // branch, skip
1104   POC_NOP,
1105   (PCC_W | PCC_REGISTER),   // inCond
1106   (PCC_W | PCC_Z) // outCond
1107 };
1108
1109 pCodeInstruction pciXORLW = {
1110   {PC_OPCODE, NULL, NULL, 0, NULL, 
1111    //   genericAnalyze,
1112    genericDestruct,
1113    genericPrint},
1114   POC_XORLW,
1115   "XORLW",
1116   NULL, // from branch
1117   NULL, // to branch
1118   NULL, // label
1119   NULL, // operand
1120   NULL, // flow block
1121   NULL, // C source 
1122   1,    // num ops
1123   0,0,  // dest, bit instruction
1124   0,0,  // branch, skip
1125   POC_NOP,
1126   PCC_W,   // inCond
1127   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1128 };
1129
1130
1131 #define MAX_PIC14MNEMONICS 100
1132 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1133
1134 /* This definition needs to be part of configure.in */
1135 // #define USE_VSNPRINTF
1136
1137 #ifdef USE_VSNPRINTF
1138   // Alas, vsnprintf is not ANSI standard, and does not exist
1139   // on Solaris (and probably other non-Gnu flavored Unixes).
1140
1141 /*-----------------------------------------------------------------*/
1142 /* SAFE_snprintf - like snprintf except the string pointer is      */
1143 /*                 after the string has been printed to. This is   */
1144 /*                 useful for printing to string as though if it   */
1145 /*                 were a stream.                                  */
1146 /*-----------------------------------------------------------------*/
1147 void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
1148 {
1149   va_list val;
1150   int len;
1151
1152   if(!str || !*str)
1153     return;
1154
1155   va_start(val, format);
1156
1157   vsnprintf(*str, *size, format, val);
1158
1159   va_end (val);
1160
1161   len = strlen(*str);
1162   if(len > *size) {
1163     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1164   }
1165
1166   *str += len;
1167   *size -= len;
1168
1169 }
1170
1171 #else  //  USE_VSNPRINTF
1172
1173 // This version is *not* safe, despite the name.
1174
1175 void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
1176 {
1177   va_list val;
1178   int len;
1179   static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1180
1181   if(!str || !*str)
1182     return;
1183
1184   va_start(val, format);
1185
1186   vsprintf(buffer, format, val);
1187   va_end (val);
1188
1189   len = strlen(buffer);
1190   if(len > *size) {
1191     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1192   }
1193
1194   strcpy(*str, buffer);
1195   *str += len;
1196   *size -= len;
1197
1198 }
1199
1200 #endif    //  USE_VSNPRINTF
1201     
1202
1203 extern  void initStack(int base_address, int size);
1204 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1205 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1206 extern void init_pic(char *);
1207
1208 void  pCodeInitRegisters(void)
1209 {
1210
1211   initStack(0xfff, 8);
1212   init_pic(port->processor);
1213
1214   pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1215   pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1216   pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1217   pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1218   pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1219   pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1220
1221   pc_status.rIdx = IDX_STATUS;
1222   pc_fsr.rIdx = IDX_FSR;
1223   pc_indf.rIdx = IDX_INDF;
1224   pc_intcon.rIdx = IDX_INTCON;
1225   pc_pcl.rIdx = IDX_PCL;
1226   pc_pclath.rIdx = IDX_PCLATH;
1227
1228   pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1229   pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1230   pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1231
1232   pc_kzero.rIdx = IDX_KZ;
1233   pc_wsave.rIdx = IDX_WSAVE;
1234   pc_ssave.rIdx = IDX_SSAVE;
1235
1236 }
1237
1238 /*-----------------------------------------------------------------*/
1239 /*  mnem2key - convert a pic mnemonic into a hash key              */
1240 /*   (BTW - this spreads the mnemonics quite well)                 */
1241 /*                                                                 */
1242 /*-----------------------------------------------------------------*/
1243
1244 int mnem2key(char const *mnem)
1245 {
1246   int key = 0;
1247
1248   if(!mnem)
1249     return 0;
1250
1251   while(*mnem) {
1252
1253     key += toupper(*mnem++) +1;
1254
1255   }
1256
1257   return (key & 0x1f);
1258
1259 }
1260
1261 void pic14initMnemonics(void)
1262 {
1263   int i = 0;
1264   int key;
1265   //  char *str;
1266   pCodeInstruction *pci;
1267
1268   if(mnemonics_initialized)
1269     return;
1270
1271 //FIXME - probably should NULL out the array before making the assignments
1272 //since we check the array contents below this initialization.
1273
1274   pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1275   pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1276   pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1277   pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1278   pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1279   pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1280   pic14Mnemonics[POC_BCF] = &pciBCF;
1281   pic14Mnemonics[POC_BSF] = &pciBSF;
1282   pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1283   pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1284   pic14Mnemonics[POC_CALL] = &pciCALL;
1285   pic14Mnemonics[POC_COMF] = &pciCOMF;
1286   pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1287   pic14Mnemonics[POC_CLRF] = &pciCLRF;
1288   pic14Mnemonics[POC_CLRW] = &pciCLRW;
1289   pic14Mnemonics[POC_DECF] = &pciDECF;
1290   pic14Mnemonics[POC_DECFW] = &pciDECFW;
1291   pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1292   pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1293   pic14Mnemonics[POC_GOTO] = &pciGOTO;
1294   pic14Mnemonics[POC_INCF] = &pciINCF;
1295   pic14Mnemonics[POC_INCFW] = &pciINCFW;
1296   pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1297   pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1298   pic14Mnemonics[POC_IORLW] = &pciIORLW;
1299   pic14Mnemonics[POC_IORWF] = &pciIORWF;
1300   pic14Mnemonics[POC_IORFW] = &pciIORFW;
1301   pic14Mnemonics[POC_MOVF] = &pciMOVF;
1302   pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1303   pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1304   pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1305   pic14Mnemonics[POC_NOP] = &pciNOP;
1306   pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1307   pic14Mnemonics[POC_RETLW] = &pciRETLW;
1308   pic14Mnemonics[POC_RETURN] = &pciRETURN;
1309   pic14Mnemonics[POC_RLF] = &pciRLF;
1310   pic14Mnemonics[POC_RLFW] = &pciRLFW;
1311   pic14Mnemonics[POC_RRF] = &pciRRF;
1312   pic14Mnemonics[POC_RRFW] = &pciRRFW;
1313   pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1314   pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1315   pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1316   pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1317   pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1318   pic14Mnemonics[POC_TRIS] = &pciTRIS;
1319   pic14Mnemonics[POC_XORLW] = &pciXORLW;
1320   pic14Mnemonics[POC_XORWF] = &pciXORWF;
1321   pic14Mnemonics[POC_XORFW] = &pciXORFW;
1322
1323   for(i=0; i<MAX_PIC14MNEMONICS; i++)
1324     if(pic14Mnemonics[i])
1325       hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1326   pci = hTabFirstItem(pic14MnemonicsHash, &key);
1327
1328   while(pci) {
1329     DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1330     pci = hTabNextItem(pic14MnemonicsHash, &key);
1331   }
1332
1333   mnemonics_initialized = 1;
1334 }
1335
1336 int getpCodePeepCommand(char *cmd);
1337
1338 int getpCode(char *mnem,unsigned dest)
1339 {
1340
1341   pCodeInstruction *pci;
1342   int key = mnem2key(mnem);
1343
1344   if(!mnemonics_initialized)
1345     pic14initMnemonics();
1346
1347   pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1348
1349   while(pci) {
1350
1351     if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1352       if((pci->num_ops <= 1) || (pci->isModReg == dest))
1353         return(pci->op);
1354     }
1355
1356     pci = hTabNextItemWK (pic14MnemonicsHash);
1357   
1358   }
1359
1360   return -1;
1361 }
1362
1363 /*-----------------------------------------------------------------*
1364  * pic14initpCodePeepCommands
1365  *
1366  *-----------------------------------------------------------------*/
1367 void pic14initpCodePeepCommands(void)
1368 {
1369
1370   int key, i;
1371   peepCommand *pcmd;
1372
1373   i = 0;
1374   do {
1375     hTabAddItem(&pic14pCodePeepCommandsHash, 
1376                 mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1377     i++;
1378   } while (peepCommands[i].cmd);
1379
1380   pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1381
1382   while(pcmd) {
1383     //fprintf(stderr, "peep command %s  key %d\n",pcmd->cmd,pcmd->id);
1384     pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1385   }
1386
1387 }
1388
1389 /*-----------------------------------------------------------------
1390  *
1391  *
1392  *-----------------------------------------------------------------*/
1393
1394 int getpCodePeepCommand(char *cmd)
1395 {
1396
1397   peepCommand *pcmd;
1398   int key = mnem2key(cmd);
1399
1400
1401   pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1402
1403   while(pcmd) {
1404     // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1405     if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1406       return pcmd->id;
1407     }
1408
1409     pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1410   
1411   }
1412
1413   return -1;
1414 }
1415
1416 char getpBlock_dbName(pBlock *pb)
1417 {
1418   if(!pb)
1419     return 0;
1420
1421   if(pb->cmemmap)
1422     return pb->cmemmap->dbName;
1423
1424   return pb->dbName;
1425 }
1426 void pBlockConvert2ISR(pBlock *pb)
1427 {
1428   if(!pb)
1429     return;
1430
1431   if(pb->cmemmap)
1432     pb->cmemmap = NULL;
1433
1434   pb->dbName = 'I';
1435 }
1436
1437 /*-----------------------------------------------------------------*/
1438 /* movepBlock2Head - given the dbname of a pBlock, move all        */
1439 /*                   instances to the front of the doubly linked   */
1440 /*                   list of pBlocks                               */
1441 /*-----------------------------------------------------------------*/
1442
1443 void movepBlock2Head(char dbName)
1444 {
1445   pBlock *pb;
1446
1447   pb = the_pFile->pbHead;
1448
1449   while(pb) {
1450
1451     if(getpBlock_dbName(pb) == dbName) {
1452       pBlock *pbn = pb->next;
1453       pb->next = the_pFile->pbHead;
1454       the_pFile->pbHead->prev = pb;
1455       the_pFile->pbHead = pb;
1456
1457       if(pb->prev)
1458         pb->prev->next = pbn;
1459
1460       // If the pBlock that we just moved was the last
1461       // one in the link of all of the pBlocks, then we
1462       // need to point the tail to the block just before
1463       // the one we moved.
1464       // Note: if pb->next is NULL, then pb must have 
1465       // been the last pBlock in the chain.
1466
1467       if(pbn)
1468         pbn->prev = pb->prev;
1469       else
1470         the_pFile->pbTail = pb->prev;
1471
1472       pb = pbn;
1473
1474     } else
1475       pb = pb->next;
1476
1477   }
1478
1479 }
1480
1481 void copypCode(FILE *of, char dbName)
1482 {
1483   pBlock *pb;
1484
1485   if(!of || !the_pFile)
1486     return;
1487
1488   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1489     if(getpBlock_dbName(pb) == dbName) {
1490       pBlockStats(of,pb);
1491       printpBlock(of,pb);
1492     }
1493   }
1494
1495 }
1496 void pcode_test(void)
1497 {
1498
1499   DFPRINTF((stderr,"pcode is alive!\n"));
1500
1501   //initMnemonics();
1502
1503   if(the_pFile) {
1504
1505     pBlock *pb;
1506     FILE *pFile;
1507     char buffer[100];
1508
1509     /* create the file name */
1510     strcpy(buffer,srcFileName);
1511     strcat(buffer,".p");
1512
1513     if( !(pFile = fopen(buffer, "w" ))) {
1514       werror(E_FILE_OPEN_ERR,buffer);
1515       exit(1);
1516     }
1517
1518     fprintf(pFile,"pcode dump\n\n");
1519
1520     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1521       fprintf(pFile,"\n\tNew pBlock\n\n");
1522       if(pb->cmemmap)
1523         fprintf(pFile,"%s",pb->cmemmap->sname);
1524       else
1525         fprintf(pFile,"internal pblock");
1526
1527       fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1528       printpBlock(pFile,pb);
1529     }
1530   }
1531 }
1532 /*-----------------------------------------------------------------*/
1533 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg-  */
1534 /*      ister, RegCond will return the bit being referenced.       */
1535 /*                                                                 */
1536 /* fixme - why not just OR in the pcop bit field                   */
1537 /*-----------------------------------------------------------------*/
1538
1539 static int RegCond(pCodeOp *pcop)
1540 {
1541
1542   if(!pcop)
1543     return 0;
1544
1545   if(pcop->type == PO_GPR_BIT  && !strcmp(pcop->name, pc_status.pcop.name)) {
1546     switch(PCORB(pcop)->bit) {
1547     case PIC_C_BIT:
1548       return PCC_C;
1549     case PIC_DC_BIT:
1550         return PCC_DC;
1551     case PIC_Z_BIT:
1552       return PCC_Z;
1553     }
1554
1555   }
1556
1557   return 0;
1558 }
1559
1560 /*-----------------------------------------------------------------*/
1561 /* newpCode - create and return a newly initialized pCode          */
1562 /*                                                                 */
1563 /*  fixme - rename this                                            */
1564 /*                                                                 */
1565 /* The purpose of this routine is to create a new Instruction      */
1566 /* pCode. This is called by gen.c while the assembly code is being */
1567 /* generated.                                                      */
1568 /*                                                                 */
1569 /* Inouts:                                                         */
1570 /*  PIC_OPCODE op - the assembly instruction we wish to create.    */
1571 /*                  (note that the op is analogous to but not the  */
1572 /*                  same thing as the opcode of the instruction.)  */
1573 /*  pCdoeOp *pcop - pointer to the operand of the instruction.     */
1574 /*                                                                 */
1575 /* Outputs:                                                        */
1576 /*  a pointer to the new malloc'd pCode is returned.               */
1577 /*                                                                 */
1578 /*                                                                 */
1579 /*                                                                 */
1580 /*-----------------------------------------------------------------*/
1581 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1582 {
1583   pCodeInstruction *pci ;
1584
1585   if(!mnemonics_initialized)
1586     pic14initMnemonics();
1587     
1588   pci = Safe_calloc(1, sizeof(pCodeInstruction));
1589
1590   if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1591     memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1592     pci->pcop = pcop;
1593
1594     if(pci->inCond == PCC_EXAMINE_PCOP)
1595       pci->inCond   = RegCond(pcop);
1596
1597     if(pci->outCond == PCC_EXAMINE_PCOP)
1598       pci->outCond   = RegCond(pcop);
1599
1600     pci->pc.prev = pci->pc.next = NULL;
1601     return (pCode *)pci;
1602   }
1603
1604   fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1605   exit(1);
1606
1607   return NULL;
1608 }       
1609
1610 /*-----------------------------------------------------------------*/
1611 /* newpCodeWild - create a "wild" as in wild card pCode            */
1612 /*                                                                 */
1613 /* Wild pcodes are used during the peep hole optimizer to serve    */
1614 /* as place holders for any instruction. When a snippet of code is */
1615 /* compared to a peep hole rule, the wild card opcode will match   */
1616 /* any instruction. However, the optional operand and label are    */
1617 /* additional qualifiers that must also be matched before the      */
1618 /* line (of assembly code) is declared matched. Note that the      */
1619 /* operand may be wild too.                                        */
1620 /*                                                                 */
1621 /*   Note, a wild instruction is specified just like a wild var:   */
1622 /*      %4     ; A wild instruction,                               */
1623 /*  See the peeph.def file for additional examples                 */
1624 /*                                                                 */
1625 /*-----------------------------------------------------------------*/
1626
1627 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1628 {
1629
1630   pCodeWild *pcw;
1631     
1632   pcw = Safe_calloc(1,sizeof(pCodeWild));
1633
1634   pcw->pci.pc.type = PC_WILD;
1635   pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1636   pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1637   pcw->pci.pc.pb = NULL;
1638
1639   //  pcw->pci.pc.analyze = genericAnalyze;
1640   pcw->pci.pc.destruct = genericDestruct;
1641   pcw->pci.pc.print = genericPrint;
1642
1643   pcw->id = pCodeID;              // this is the 'n' in %n
1644   pcw->operand = optional_operand;
1645   pcw->label   = optional_label;
1646
1647   pcw->mustBeBitSkipInst = 0;
1648   pcw->mustNotBeBitSkipInst = 0;
1649   pcw->invertBitSkipInst = 0;
1650
1651   return ( (pCode *)pcw);
1652   
1653 }
1654
1655  /*-----------------------------------------------------------------*/
1656 /* newPcodeInlineP - create a new pCode from a char string           */
1657 /*-----------------------------------------------------------------*/
1658
1659
1660 pCode *newpCodeInlineP(char *cP)
1661 {
1662
1663   pCodeComment *pcc ;
1664     
1665   pcc = Safe_calloc(1,sizeof(pCodeComment));
1666
1667   pcc->pc.type = PC_INLINE;
1668   pcc->pc.prev = pcc->pc.next = NULL;
1669   //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1670   pcc->pc.pb = NULL;
1671
1672   //  pcc->pc.analyze = genericAnalyze;
1673   pcc->pc.destruct = genericDestruct;
1674   pcc->pc.print = genericPrint;
1675
1676   if(cP)
1677     pcc->comment = Safe_strdup(cP);
1678   else
1679     pcc->comment = NULL;
1680
1681   return ( (pCode *)pcc);
1682
1683 }
1684
1685 /*-----------------------------------------------------------------*/
1686 /* newPcodeCharP - create a new pCode from a char string           */
1687 /*-----------------------------------------------------------------*/
1688
1689 pCode *newpCodeCharP(char *cP)
1690 {
1691
1692   pCodeComment *pcc ;
1693     
1694   pcc = Safe_calloc(1,sizeof(pCodeComment));
1695
1696   pcc->pc.type = PC_COMMENT;
1697   pcc->pc.prev = pcc->pc.next = NULL;
1698   //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1699   pcc->pc.pb = NULL;
1700
1701   //  pcc->pc.analyze = genericAnalyze;
1702   pcc->pc.destruct = genericDestruct;
1703   pcc->pc.print = genericPrint;
1704
1705   if(cP)
1706     pcc->comment = Safe_strdup(cP);
1707   else
1708     pcc->comment = NULL;
1709
1710   return ( (pCode *)pcc);
1711
1712 }
1713
1714 /*-----------------------------------------------------------------*/
1715 /* newpCodeFunction -                                              */
1716 /*-----------------------------------------------------------------*/
1717
1718
1719 pCode *newpCodeFunction(char *mod,char *f)
1720 {
1721   pCodeFunction *pcf;
1722
1723   pcf = Safe_calloc(1,sizeof(pCodeFunction));
1724   //_ALLOC(pcf,sizeof(pCodeFunction));
1725
1726   pcf->pc.type = PC_FUNCTION;
1727   pcf->pc.prev = pcf->pc.next = NULL;
1728   //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1729   pcf->pc.pb = NULL;
1730
1731   //  pcf->pc.analyze = genericAnalyze;
1732   pcf->pc.destruct = genericDestruct;
1733   pcf->pc.print = pCodePrintFunction;
1734
1735   pcf->ncalled = 0;
1736
1737   if(mod) {
1738     //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1739     pcf->modname = Safe_calloc(1,strlen(mod)+1);
1740     strcpy(pcf->modname,mod);
1741   } else
1742     pcf->modname = NULL;
1743
1744   if(f) {
1745     //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1746     pcf->fname = Safe_calloc(1,strlen(f)+1);
1747     strcpy(pcf->fname,f);
1748   } else
1749     pcf->fname = NULL;
1750
1751   return ( (pCode *)pcf);
1752
1753 }
1754
1755 /*-----------------------------------------------------------------*/
1756 /* newpCodeFlow                                                    */
1757 /*-----------------------------------------------------------------*/
1758
1759 void destructpCodeFlow(pCode *pc)
1760 {
1761   if(!pc || !isPCFL(pc))
1762     return;
1763
1764   if(PCFL(pc)->uses)
1765     free(PCFL(pc)->uses);
1766 /*
1767   if(PCFL(pc)->from)
1768   if(PCFL(pc)->to)
1769 */
1770   free(pc);
1771 }
1772
1773 pCode *newpCodeFlow(void )
1774 {
1775   pCodeFlow *pcflow;
1776
1777   //_ALLOC(pcflow,sizeof(pCodeFlow));
1778   pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1779
1780   pcflow->pc.type = PC_FLOW;
1781   pcflow->pc.prev = pcflow->pc.next = NULL;
1782   //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
1783   pcflow->pc.pb = NULL;
1784
1785   //  pcflow->pc.analyze = genericAnalyze;
1786   pcflow->pc.destruct = destructpCodeFlow;
1787   pcflow->pc.print = genericPrint;
1788
1789   pcflow->pc.seq = GpcFlowSeq++;
1790
1791   pcflow->nuses = 7;
1792   pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
1793
1794   pcflow->from = pcflow->to = NULL;
1795
1796   pcflow->inCond = PCC_NONE;
1797   pcflow->outCond = PCC_NONE;
1798
1799   pcflow->firstBank = -1;
1800   pcflow->lastBank = -1;
1801
1802   pcflow->FromConflicts = 0;
1803   pcflow->ToConflicts = 0;
1804
1805   pcflow->end = NULL;
1806   return ( (pCode *)pcflow);
1807
1808 }
1809
1810 /*-----------------------------------------------------------------*/
1811 /*-----------------------------------------------------------------*/
1812 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1813 {
1814   pCodeFlowLink *pcflowLink;
1815
1816   pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1817
1818   pcflowLink->pcflow = pcflow;
1819   pcflowLink->bank_conflict = 0;
1820
1821   return pcflowLink;
1822 }
1823
1824 /*-----------------------------------------------------------------*/
1825 /* newpCodeCSource - create a new pCode Source Symbol              */
1826 /*-----------------------------------------------------------------*/
1827
1828 pCode *newpCodeCSource(int ln, char *f, char *l)
1829 {
1830
1831   pCodeCSource *pccs;
1832     
1833   pccs = Safe_calloc(1,sizeof(pCodeCSource));
1834
1835   pccs->pc.type = PC_CSOURCE;
1836   pccs->pc.prev = pccs->pc.next = NULL;
1837   pccs->pc.pb = NULL;
1838
1839   pccs->pc.destruct = genericDestruct;
1840   pccs->pc.print = genericPrint;
1841
1842   pccs->line_number = ln;
1843   if(l)
1844     pccs->line = Safe_strdup(l);
1845   else
1846     pccs->line = NULL;
1847
1848   if(f)
1849     pccs->file_name = Safe_strdup(f);
1850   else
1851     pccs->file_name = NULL;
1852
1853   return ( (pCode *)pccs);
1854
1855 }
1856 /*-----------------------------------------------------------------*/
1857 /* pCodeLabelDestruct - free memory used by a label.               */
1858 /*-----------------------------------------------------------------*/
1859 static void pCodeLabelDestruct(pCode *pc)
1860 {
1861
1862   if(!pc)
1863     return;
1864
1865   if((pc->type == PC_LABEL) && PCL(pc)->label)
1866     free(PCL(pc)->label);
1867
1868   free(pc);
1869
1870 }
1871
1872 pCode *newpCodeLabel(char *name, int key)
1873 {
1874
1875   char *s = buffer;
1876   pCodeLabel *pcl;
1877     
1878   pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1879
1880   pcl->pc.type = PC_LABEL;
1881   pcl->pc.prev = pcl->pc.next = NULL;
1882   //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1883   pcl->pc.pb = NULL;
1884
1885   //  pcl->pc.analyze = genericAnalyze;
1886   pcl->pc.destruct = pCodeLabelDestruct;
1887   pcl->pc.print = pCodePrintLabel;
1888
1889   pcl->key = key;
1890
1891   pcl->label = NULL;
1892   if(key>0) {
1893     sprintf(s,"_%05d_DS_",key);
1894   } else
1895     s = name;
1896
1897   if(s)
1898     pcl->label = Safe_strdup(s);
1899
1900
1901   return ( (pCode *)pcl);
1902
1903 }
1904
1905
1906 /*-----------------------------------------------------------------*/
1907 /* newpBlock - create and return a pointer to a new pBlock         */
1908 /*-----------------------------------------------------------------*/
1909 pBlock *newpBlock(void)
1910 {
1911
1912   pBlock *PpB;
1913
1914   PpB = Safe_calloc(1,sizeof(pBlock) );
1915   PpB->next = PpB->prev = NULL;
1916
1917   PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1918   PpB->tregisters = NULL;
1919   PpB->visited = 0;
1920
1921   return PpB;
1922
1923 }
1924
1925 /*-----------------------------------------------------------------*/
1926 /* newpCodeChain - create a new chain of pCodes                    */
1927 /*-----------------------------------------------------------------*
1928  *
1929  *  This function will create a new pBlock and the pointer to the
1930  *  pCode that is passed in will be the first pCode in the block.
1931  *-----------------------------------------------------------------*/
1932
1933
1934 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1935 {
1936
1937   pBlock *pB  = newpBlock();
1938
1939   pB->pcHead  = pB->pcTail = pc;
1940   pB->cmemmap = cm;
1941   pB->dbName  = c;
1942
1943   return pB;
1944 }
1945
1946 /*-----------------------------------------------------------------*/
1947 /* newpCodeOpLabel - Create a new label given the key              */
1948 /*  Note, a negative key means that the label is part of wild card */
1949 /*  (and hence a wild card label) used in the pCodePeep            */
1950 /*   optimizations).                                               */
1951 /*-----------------------------------------------------------------*/
1952
1953 pCodeOp *newpCodeOpLabel(char *name, int key)
1954 {
1955   char *s=NULL;
1956   static int label_key=-1;
1957
1958   pCodeOp *pcop;
1959
1960   pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1961   pcop->type = PO_LABEL;
1962
1963   pcop->name = NULL;
1964
1965   if(key>0)
1966     sprintf(s=buffer,"_%05d_DS_",key);
1967   else 
1968     s = name, key = label_key--;
1969
1970   if(s)
1971     pcop->name = Safe_strdup(s);
1972
1973   ((pCodeOpLabel *)pcop)->key = key;
1974
1975   return pcop;
1976 }
1977
1978 /*-----------------------------------------------------------------*/
1979 /*-----------------------------------------------------------------*/
1980 pCodeOp *newpCodeOpLit(int lit)
1981 {
1982   char *s = buffer;
1983   pCodeOp *pcop;
1984
1985
1986   pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1987   pcop->type = PO_LITERAL;
1988
1989   pcop->name = NULL;
1990   if(lit>=0) {
1991     sprintf(s,"0x%02x",lit);
1992     if(s)
1993       pcop->name = Safe_strdup(s);
1994   }
1995
1996   ((pCodeOpLit *)pcop)->lit = lit;
1997
1998   return pcop;
1999 }
2000
2001 /*-----------------------------------------------------------------*/
2002 /*-----------------------------------------------------------------*/
2003 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space)
2004 {
2005   pCodeOp *pcop;
2006
2007   pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2008   pcop->type = PO_IMMEDIATE;
2009   if(name) {
2010     pcop->name = Safe_strdup(name);
2011     //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2012   } else {
2013     pcop->name = NULL;
2014   }
2015
2016
2017   PCOI(pcop)->index = index;
2018   PCOI(pcop)->offset = offset;
2019   PCOI(pcop)->_const = code_space;
2020
2021   return pcop;
2022 }
2023
2024 /*-----------------------------------------------------------------*/
2025 /*-----------------------------------------------------------------*/
2026 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2027 {
2028   char *s = buffer;
2029   pCodeOp *pcop;
2030
2031
2032   if(!pcwb || !subtype) {
2033     fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2034     exit(1);
2035   }
2036
2037   pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2038   pcop->type = PO_WILD;
2039   sprintf(s,"%%%d",id);
2040   pcop->name = Safe_strdup(s);
2041
2042   PCOW(pcop)->id = id;
2043   PCOW(pcop)->pcwb = pcwb;
2044   PCOW(pcop)->subtype = subtype;
2045   PCOW(pcop)->matched = NULL;
2046
2047   return pcop;
2048 }
2049
2050 /*-----------------------------------------------------------------*/
2051 /*-----------------------------------------------------------------*/
2052 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
2053 {
2054   pCodeOp *pcop;
2055
2056   pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2057   pcop->type = PO_GPR_BIT;
2058   if(s)
2059     pcop->name = Safe_strdup(s);   
2060   else
2061     pcop->name = NULL;
2062
2063   PCORB(pcop)->bit = bit;
2064   PCORB(pcop)->inBitSpace = inBitSpace;
2065
2066   return pcop;
2067 }
2068
2069 /*-----------------------------------------------------------------*
2070  * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2071  *
2072  * If rIdx >=0 then a specific register from the set of registers
2073  * will be selected. If rIdx <0, then a new register will be searched
2074  * for.
2075  *-----------------------------------------------------------------*/
2076
2077 pCodeOp *newpCodeOpReg(int rIdx)
2078 {
2079   pCodeOp *pcop;
2080
2081   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2082
2083   pcop->name = NULL;
2084
2085   if(rIdx >= 0) {
2086     PCOR(pcop)->rIdx = rIdx;
2087     PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2088   } else {
2089     PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2090
2091     if(PCOR(pcop)->r)
2092       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2093     //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2094   }
2095
2096   pcop->type = PCOR(pcop)->r->pc_type;
2097
2098   return pcop;
2099 }
2100
2101 pCodeOp *newpCodeOpRegFromStr(char *name)
2102 {
2103   pCodeOp *pcop;
2104
2105   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2106   PCOR(pcop)->r = allocRegByName(name, 1);
2107   PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2108   pcop->type = PCOR(pcop)->r->pc_type;
2109   pcop->name = PCOR(pcop)->r->name;
2110
2111   return pcop;
2112 }
2113
2114 /*-----------------------------------------------------------------*/
2115 /*-----------------------------------------------------------------*/
2116
2117 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2118 {
2119   pCodeOp *pcop;
2120
2121   switch(type) {
2122   case PO_BIT:
2123   case PO_GPR_BIT:
2124     pcop = newpCodeOpBit(name, -1,0);
2125     break;
2126
2127   case PO_LITERAL:
2128     pcop = newpCodeOpLit(-1);
2129     break;
2130
2131   case PO_LABEL:
2132     pcop = newpCodeOpLabel(NULL,-1);
2133     break;
2134   case PO_GPR_TEMP:
2135     pcop = newpCodeOpReg(-1);
2136     break;
2137
2138   default:
2139     pcop = Safe_calloc(1,sizeof(pCodeOp) );
2140     pcop->type = type;
2141     if(name)
2142       pcop->name = Safe_strdup(name);   
2143     else
2144       pcop->name = NULL;
2145   }
2146
2147   return pcop;
2148 }
2149
2150 /*-----------------------------------------------------------------*/
2151 /*-----------------------------------------------------------------*/
2152 void pCodeConstString(char *name, char *value)
2153 {
2154   pBlock *pb;
2155
2156   //  fprintf(stderr, " %s  %s  %s\n",__FUNCTION__,name,value);
2157
2158   if(!name || !value)
2159     return;
2160
2161   pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2162
2163   addpBlock(pb);
2164
2165   sprintf(buffer,"; %s = %s",name,value);
2166   
2167   addpCode2pBlock(pb,newpCodeCharP(buffer));
2168   addpCode2pBlock(pb,newpCodeLabel(name,-1));
2169
2170   do {
2171     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2172   }while (*value++);
2173
2174
2175 }
2176
2177 /*-----------------------------------------------------------------*/
2178 /*-----------------------------------------------------------------*/
2179 void pCodeReadCodeTable(void)
2180 {
2181   pBlock *pb;
2182
2183   fprintf(stderr, " %s\n",__FUNCTION__);
2184
2185   pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2186
2187   addpBlock(pb);
2188
2189   addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2190   addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2191   addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2192   addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2193
2194   addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2195   addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2196   addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2197   addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2198
2199
2200 }
2201
2202 /*-----------------------------------------------------------------*/
2203 /* addpCode2pBlock - place the pCode into the pBlock linked list   */
2204 /*-----------------------------------------------------------------*/
2205 void addpCode2pBlock(pBlock *pb, pCode *pc)
2206 {
2207   if(!pb->pcHead) {
2208     /* If this is the first pcode to be added to a block that
2209      * was initialized with a NULL pcode, then go ahead and
2210      * make this pcode the head and tail */
2211     pb->pcHead  = pb->pcTail = pc;
2212   } else {
2213     pb->pcTail->next = pc;
2214     pc->prev = pb->pcTail;
2215     //pc->next = NULL;
2216     pc->pb = pb;
2217     pb->pcTail = pc;
2218   }
2219 }
2220
2221 /*-----------------------------------------------------------------*/
2222 /* addpBlock - place a pBlock into the pFile                       */
2223 /*-----------------------------------------------------------------*/
2224 void addpBlock(pBlock *pb)
2225 {
2226   // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2227
2228   if(!the_pFile) {
2229     /* First time called, we'll pass through here. */
2230     //_ALLOC(the_pFile,sizeof(pFile));
2231     the_pFile = Safe_calloc(1,sizeof(pFile));
2232     the_pFile->pbHead = the_pFile->pbTail = pb;
2233     the_pFile->functions = NULL;
2234     return;
2235   }
2236
2237   the_pFile->pbTail->next = pb;
2238   pb->prev = the_pFile->pbTail;
2239   pb->next = NULL;
2240   the_pFile->pbTail = pb;
2241 }
2242
2243 /*-----------------------------------------------------------------*/
2244 /* removepBlock - remove a pBlock from the pFile                   */
2245 /*-----------------------------------------------------------------*/
2246 void removepBlock(pBlock *pb)
2247 {
2248   pBlock *pbs;
2249
2250   if(!the_pFile)
2251     return;
2252
2253
2254   //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2255
2256   for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2257     if(pbs == pb) {
2258
2259       if(pbs == the_pFile->pbHead)
2260         the_pFile->pbHead = pbs->next;
2261
2262       if (pbs == the_pFile->pbTail) 
2263         the_pFile->pbTail = pbs->prev;
2264
2265       if(pbs->next)
2266         pbs->next->prev = pbs->prev;
2267
2268       if(pbs->prev)
2269         pbs->prev->next = pbs->next;
2270
2271       return;
2272
2273     }
2274   }
2275
2276   fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2277
2278 }
2279
2280 /*-----------------------------------------------------------------*/
2281 /* printpCode - write the contents of a pCode to a file            */
2282 /*-----------------------------------------------------------------*/
2283 void printpCode(FILE *of, pCode *pc)
2284 {
2285
2286   if(!pc || !of)
2287     return;
2288
2289   if(pc->print) {
2290     pc->print(of,pc);
2291     return;
2292   }
2293
2294   fprintf(of,"warning - unable to print pCode\n");
2295 }
2296
2297 /*-----------------------------------------------------------------*/
2298 /* printpBlock - write the contents of a pBlock to a file          */
2299 /*-----------------------------------------------------------------*/
2300 void printpBlock(FILE *of, pBlock *pb)
2301 {
2302   pCode *pc;
2303
2304   if(!pb)
2305     return;
2306
2307   if(!of)
2308     of = stderr;
2309
2310   for(pc = pb->pcHead; pc; pc = pc->next)
2311     printpCode(of,pc);
2312
2313 }
2314
2315 /*-----------------------------------------------------------------*/
2316 /*                                                                 */
2317 /*       pCode processing                                          */
2318 /*                                                                 */
2319 /*                                                                 */
2320 /*                                                                 */
2321 /*-----------------------------------------------------------------*/
2322
2323 static void unlinkPC(pCode *pc)
2324 {
2325
2326
2327   if(pc) {
2328 #ifdef PCODE_DEBUG
2329     fprintf(stderr,"Unlinking: ");
2330     printpCode(stderr, pc);
2331 #endif
2332     if(pc->prev) 
2333       pc->prev->next = pc->next;
2334     if(pc->next)
2335       pc->next->prev = pc->prev;
2336
2337     pc->prev = pc->next = NULL;
2338   }
2339 }
2340 static void genericDestruct(pCode *pc)
2341 {
2342   //fprintf(stderr,"warning, calling default pCode destructor\n");
2343
2344   unlinkPC(pc);
2345
2346   free(pc);
2347
2348 }
2349
2350
2351 /*-----------------------------------------------------------------*/
2352 /*-----------------------------------------------------------------*/
2353 void pBlockRegs(FILE *of, pBlock *pb)
2354 {
2355
2356   regs  *r;
2357
2358   r = setFirstItem(pb->tregisters);
2359   while (r) {
2360     r = setNextItem(pb->tregisters);
2361   }
2362 }
2363
2364
2365 /*-----------------------------------------------------------------*/
2366 /*-----------------------------------------------------------------*/
2367 char *get_op(pCodeOp *pcop)
2368 {
2369   regs *r;
2370   static char buffer[50];
2371   char *s;
2372   int size;
2373
2374
2375   if(pcop) {
2376     switch(pcop->type) {
2377     case PO_INDF:
2378     case PO_FSR:
2379       //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
2380       //r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
2381       //return r->name;
2382       return PCOR(pcop)->r->name;
2383       break;
2384     case PO_GPR_TEMP:
2385       r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2386       //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
2387       return r->name;
2388
2389       //    case PO_GPR_BIT:
2390       //      return PCOR(pcc->pcop)->r)->name;
2391     case PO_IMMEDIATE:
2392       s = buffer;
2393       size = sizeof(buffer);
2394       //fprintf(stderr,"PO_IMMEDIATE name = %s  offset = %d\n",pcc->pcop->name,PCOI(pcc->pcop)->offset);
2395       if(PCOI(pcop)->_const) {
2396
2397         if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2398           SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2399                         pcop->name,
2400                         PCOI(pcop)->index,
2401                         8 * PCOI(pcop)->offset );
2402         } else
2403           SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2404       } else {
2405       
2406         if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2407           SAFE_snprintf(&s,&size,"(%s + %d)",
2408                         pcop->name,
2409                         PCOI(pcop)->index );
2410         } else
2411           SAFE_snprintf(&s,&size,"%s",pcop->name);
2412       }
2413
2414       return buffer;
2415
2416     case PO_DIR:
2417       s = buffer;
2418       size = sizeof(buffer);
2419       if( PCOR(pcop)->instance) {
2420         SAFE_snprintf(&s,&size,"(%s + %d)",
2421                       pcop->name,
2422                       PCOR(pcop)->instance );
2423         //fprintf(stderr,"PO_DIR %s\n",buffer);
2424       } else
2425         SAFE_snprintf(&s,&size,"%s",pcop->name);
2426       return buffer;
2427
2428     default:
2429       if  (pcop->name)
2430         return pcop->name;
2431
2432     }
2433   }
2434
2435   return "NO operand";
2436
2437 }
2438
2439 /*-----------------------------------------------------------------*/
2440 /*-----------------------------------------------------------------*/
2441 static char *get_op_from_instruction( pCodeInstruction *pcc)
2442 {
2443
2444   if(pcc )
2445     return get_op(pcc->pcop);
2446   
2447   return ("ERROR Null: "__FUNCTION__);
2448
2449 }
2450
2451 /*-----------------------------------------------------------------*/
2452 /*-----------------------------------------------------------------*/
2453 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2454 {
2455
2456   fprintf(of,"pcodeopprint- not implemented\n");
2457 }
2458
2459 /*-----------------------------------------------------------------*/
2460 /*-----------------------------------------------------------------*/
2461 char *pCode2str(char *str, int size, pCode *pc)
2462 {
2463   char *s = str;
2464
2465   switch(pc->type) {
2466
2467   case PC_OPCODE:
2468
2469     SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2470
2471     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2472
2473       if(PCI(pc)->isBitInst) {
2474         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2475           if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2476             SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
2477                           PCI(pc)->pcop->name ,
2478                           PCI(pc)->pcop->name );
2479           else
2480             SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)), 
2481                           (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2482         } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2483           SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2484         }else
2485           SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2486         //PCI(pc)->pcop->t.bit );
2487       } else {
2488
2489         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2490           if( PCI(pc)->num_ops == 2)
2491             SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2492           else
2493             SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2494
2495         }else {
2496           SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2497
2498           if( PCI(pc)->num_ops == 2)
2499             SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2500         }
2501       }
2502
2503     }
2504     break;
2505
2506   case PC_COMMENT:
2507     /* assuming that comment ends with a \n */
2508     SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2509     break;
2510
2511   case PC_INLINE:
2512     /* assuming that inline code ends with a \n */
2513     SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2514     break;
2515
2516   case PC_LABEL:
2517     SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2518     break;
2519   case PC_FUNCTION:
2520     SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2521     break;
2522   case PC_WILD:
2523     SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2524     break;
2525   case PC_FLOW:
2526     SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2527     break;
2528   case PC_CSOURCE:
2529   SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2530     break;
2531
2532   }
2533
2534   return str;
2535
2536 }
2537
2538 /*-----------------------------------------------------------------*/
2539 /* genericPrint - the contents of a pCode to a file                */
2540 /*-----------------------------------------------------------------*/
2541 static void genericPrint(FILE *of, pCode *pc)
2542 {
2543
2544   if(!pc || !of)
2545     return;
2546
2547   switch(pc->type) {
2548   case PC_COMMENT:
2549     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2550     break;
2551
2552   case PC_INLINE:
2553     fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2554      break;
2555
2556   case PC_OPCODE:
2557     // If the opcode has a label, print that first
2558     {
2559       pBranch *pbl = PCI(pc)->label;
2560       while(pbl && pbl->pc) {
2561         if(pbl->pc->type == PC_LABEL)
2562           pCodePrintLabel(of, pbl->pc);
2563         pbl = pbl->next;
2564       }
2565     }
2566
2567     if(PCI(pc)->cline) 
2568       genericPrint(of,PCODE(PCI(pc)->cline));
2569
2570     {
2571       char str[256];
2572       
2573       pCode2str(str, 256, pc);
2574
2575       fprintf(of,"%s",str);
2576
2577       /* Debug */
2578       fprintf(of, "\t;key=%03x",pc->seq);
2579       if(PCI(pc)->pcflow)
2580         fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2581     }
2582 #if 0
2583     {
2584       pBranch *dpb = pc->to;   // debug
2585       while(dpb) {
2586         switch ( dpb->pc->type) {
2587         case PC_OPCODE:
2588           fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2589           break;
2590         case PC_LABEL:
2591           fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2592           break;
2593         case PC_FUNCTION:
2594           fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2595           break;
2596         case PC_FLOW:
2597           fprintf(of, "\t;flow");
2598           break;
2599         case PC_COMMENT:
2600         case PC_WILD:
2601           break;
2602         }
2603         dpb = dpb->next;
2604       }
2605     }
2606 #endif
2607     fprintf(of,"\n");
2608     break;
2609
2610   case PC_WILD:
2611     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2612     if(PCW(pc)->pci.label)
2613       pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2614
2615     if(PCW(pc)->operand) {
2616       fprintf(of,";\toperand  ");
2617       pCodeOpPrint(of,PCW(pc)->operand );
2618     }
2619     break;
2620
2621   case PC_FLOW:
2622     fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
2623     break;
2624
2625   case PC_CSOURCE:
2626     fprintf(of,";#CSRC\t%s %d\n;  %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2627     break;
2628   case PC_LABEL:
2629   default:
2630     fprintf(of,"unknown pCode type %d\n",pc->type);
2631   }
2632
2633 }
2634
2635 /*-----------------------------------------------------------------*/
2636 /* pCodePrintFunction - prints function begin/end                  */
2637 /*-----------------------------------------------------------------*/
2638
2639 static void pCodePrintFunction(FILE *of, pCode *pc)
2640 {
2641
2642   if(!pc || !of)
2643     return;
2644
2645   if( ((pCodeFunction *)pc)->modname) 
2646     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2647
2648   if(PCF(pc)->fname) {
2649     pBranch *exits = PCF(pc)->to;
2650     int i=0;
2651     fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2652     while(exits) {
2653       i++;
2654       exits = exits->next;
2655     }
2656     //if(i) i--;
2657     fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2658     
2659   }else {
2660     if((PCF(pc)->from && 
2661         PCF(pc)->from->pc->type == PC_FUNCTION &&
2662         PCF(PCF(pc)->from->pc)->fname) )
2663       fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2664     else
2665       fprintf(of,"; exit point [can't find entry point]\n");
2666   }
2667 }
2668 /*-----------------------------------------------------------------*/
2669 /* pCodePrintLabel - prints label                                  */
2670 /*-----------------------------------------------------------------*/
2671
2672 static void pCodePrintLabel(FILE *of, pCode *pc)
2673 {
2674
2675   if(!pc || !of)
2676     return;
2677
2678   if(PCL(pc)->label) 
2679     fprintf(of,"%s\n",PCL(pc)->label);
2680   else if (PCL(pc)->key >=0) 
2681     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2682   else
2683     fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2684
2685 }
2686 /*-----------------------------------------------------------------*/
2687 /* unlinkpCodeFromBranch - Search for a label in a pBranch and     */
2688 /*                         remove it if it is found.               */
2689 /*-----------------------------------------------------------------*/
2690 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2691 {
2692   pBranch *b, *bprev;
2693
2694
2695   bprev = NULL;
2696
2697   if(pcl->type == PC_OPCODE)
2698     b = PCI(pcl)->label;
2699   else {
2700     fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2701     exit(1);
2702
2703   }
2704
2705   //fprintf (stderr, "%s \n",__FUNCTION__);
2706   //pcl->print(stderr,pcl);
2707   //pc->print(stderr,pc);
2708   while(b) {
2709     if(b->pc == pc) {
2710       //fprintf (stderr, "found label\n");
2711
2712       /* Found a label */
2713       if(bprev) {
2714         bprev->next = b->next;  /* Not first pCode in chain */
2715         free(b);
2716       } else {
2717         pc->destruct(pc);
2718         PCI(pcl)->label = b->next;   /* First pCode in chain */
2719         free(b);
2720       }
2721       return;  /* A label can't occur more than once */
2722     }
2723     bprev = b;
2724     b = b->next;
2725   }
2726
2727 }
2728
2729 /*-----------------------------------------------------------------*/
2730 /*-----------------------------------------------------------------*/
2731 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
2732 {
2733   pBranch *b;
2734
2735   if(!h)
2736     return n;
2737
2738   b = h;
2739   while(b->next)
2740     b = b->next;
2741
2742   b->next = n;
2743
2744   return h;
2745   
2746 }  
2747 /*-----------------------------------------------------------------*/
2748 /* pBranchLink - given two pcodes, this function will link them    */
2749 /*               together through their pBranches                  */
2750 /*-----------------------------------------------------------------*/
2751 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2752 {
2753   pBranch *b;
2754
2755   // Declare a new branch object for the 'from' pCode.
2756
2757   //_ALLOC(b,sizeof(pBranch));
2758   b = Safe_calloc(1,sizeof(pBranch));
2759   b->pc = PCODE(t);             // The link to the 'to' pCode.
2760   b->next = NULL;
2761
2762   f->to = pBranchAppend(f->to,b);
2763
2764   // Now do the same for the 'to' pCode.
2765
2766   //_ALLOC(b,sizeof(pBranch));
2767   b = Safe_calloc(1,sizeof(pBranch));
2768   b->pc = PCODE(f);
2769   b->next = NULL;
2770
2771   t->from = pBranchAppend(t->from,b);
2772   
2773 }
2774
2775 #if 0
2776 /*-----------------------------------------------------------------*/
2777 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2778 /*               a pCode                                           */
2779 /*-----------------------------------------------------------------*/
2780 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2781 {
2782   while(pb) {
2783
2784     if(pb->pc == pc)
2785       return pb;
2786
2787     pb = pb->next;
2788   }
2789
2790   return NULL;
2791 }
2792
2793 /*-----------------------------------------------------------------*/
2794 /* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
2795 /*-----------------------------------------------------------------*/
2796 static void pCodeUnlink(pCode *pc)
2797 {
2798   pBranch *pb1,*pb2;
2799   pCode *pc1;
2800
2801   if(!pc->prev || !pc->next) {
2802     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2803     exit(1);
2804   }
2805
2806   /* first remove the pCode from the chain */
2807   pc->prev->next = pc->next;
2808   pc->next->prev = pc->prev;
2809
2810   /* Now for the hard part... */
2811
2812   /* Remove the branches */
2813
2814   pb1 = pc->from;
2815   while(pb1) {
2816     pc1 = pb1->pc;    /* Get the pCode that branches to the
2817                        * one we're unlinking */
2818
2819     /* search for the link back to this pCode (the one we're
2820      * unlinking) */
2821     if(pb2 = pBranchFind(pc1->to,pc)) {
2822       pb2->pc = pc->to->pc;  // make the replacement
2823
2824       /* if the pCode we're unlinking contains multiple 'to'
2825        * branches (e.g. this a skip instruction) then we need
2826        * to copy these extra branches to the chain. */
2827       if(pc->to->next)
2828         pBranchAppend(pb2, pc->to->next);
2829     }
2830     
2831     pb1 = pb1->next;
2832   }
2833
2834
2835 }
2836 #endif
2837 /*-----------------------------------------------------------------*/
2838 /*-----------------------------------------------------------------*/
2839 #if 0
2840 static void genericAnalyze(pCode *pc)
2841 {
2842   switch(pc->type) {
2843   case PC_WILD:
2844   case PC_COMMENT:
2845     return;
2846   case PC_LABEL:
2847   case PC_FUNCTION:
2848   case PC_OPCODE:
2849     {
2850       // Go through the pCodes that are in pCode chain and link
2851       // them together through the pBranches. Note, the pCodes
2852       // are linked together as a contiguous stream like the 
2853       // assembly source code lines. The linking here mimics this
2854       // except that comments are not linked in.
2855       // 
2856       pCode *npc = pc->next;
2857       while(npc) {
2858         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2859           pBranchLink(pc,npc);
2860           return;
2861         } else
2862           npc = npc->next;
2863       }
2864       /* reached the end of the pcode chain without finding
2865        * an instruction we could link to. */
2866     }
2867     break;
2868   case PC_FLOW:
2869     fprintf(stderr,"analyze PC_FLOW\n");
2870
2871     return;
2872   }
2873 }
2874 #endif
2875
2876 /*-----------------------------------------------------------------*/
2877 /*-----------------------------------------------------------------*/
2878 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2879 {
2880   pBranch *pbr;
2881
2882   if(pc->type == PC_LABEL) {
2883     if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
2884       return TRUE;
2885   }
2886   if(pc->type == PC_OPCODE) {
2887     pbr = PCI(pc)->label;
2888     while(pbr) {
2889       if(pbr->pc->type == PC_LABEL) {
2890         if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
2891           return TRUE;
2892       }
2893       pbr = pbr->next;
2894     }
2895   }
2896
2897   return FALSE;
2898 }
2899
2900 /*-----------------------------------------------------------------*/
2901 /*-----------------------------------------------------------------*/
2902 int checkLabel(pCode *pc)
2903 {
2904   pBranch *pbr;
2905
2906   if(pc && isPCI(pc)) {
2907     pbr = PCI(pc)->label;
2908     while(pbr) {
2909       if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
2910         return TRUE;
2911
2912       pbr = pbr->next;
2913     }
2914   }
2915
2916   return FALSE;
2917 }
2918
2919 /*-----------------------------------------------------------------*/
2920 /* findLabelinpBlock - Search the pCode for a particular label     */
2921 /*-----------------------------------------------------------------*/
2922 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
2923 {
2924   pCode  *pc;
2925
2926   if(!pb)
2927     return NULL;
2928
2929   for(pc = pb->pcHead; pc; pc = pc->next) 
2930     if(compareLabel(pc,pcop_label))
2931       return pc;
2932     
2933   return NULL;
2934 }
2935
2936 /*-----------------------------------------------------------------*/
2937 /* findLabel - Search the pCode for a particular label             */
2938 /*-----------------------------------------------------------------*/
2939 pCode * findLabel(pCodeOpLabel *pcop_label)
2940 {
2941   pBlock *pb;
2942   pCode  *pc;
2943
2944   if(!the_pFile)
2945     return NULL;
2946
2947   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2948     if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
2949       return pc;
2950   }
2951
2952   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
2953   return NULL;
2954 }
2955
2956 /*-----------------------------------------------------------------*/
2957 /* findNextpCode - given a pCode, find the next of type 'pct'      */
2958 /*                 in the linked list                              */
2959 /*-----------------------------------------------------------------*/
2960 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
2961 {
2962
2963   while(pc) {
2964     if(pc->type == pct)
2965       return pc;
2966
2967     pc = pc->next;
2968   }
2969
2970   return NULL;
2971 }
2972
2973 /*-----------------------------------------------------------------*/
2974 /* findPrevpCode - given a pCode, find the previous of type 'pct'  */
2975 /*                 in the linked list                              */
2976 /*-----------------------------------------------------------------*/
2977 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
2978 {
2979
2980   while(pc) {
2981     if(pc->type == pct)
2982       return pc;
2983
2984     pc = pc->prev;
2985   }
2986
2987   return NULL;
2988 }
2989 /*-----------------------------------------------------------------*/
2990 /* findNextInstruction - given a pCode, find the next instruction  */
2991 /*                       in the linked list                        */
2992 /*-----------------------------------------------------------------*/
2993 pCode * findNextInstruction(pCode *pci)
2994 {
2995   pCode *pc = pci;
2996
2997   while(pc) {
2998     if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
2999       return pc;
3000
3001 #ifdef PCODE_DEBUG
3002     fprintf(stderr,"findNextInstruction:  ");
3003     printpCode(stderr, pc);
3004 #endif
3005     pc = pc->next;
3006   }
3007
3008   //fprintf(stderr,"Couldn't find instruction\n");
3009   return NULL;
3010 }
3011
3012 /*-----------------------------------------------------------------*/
3013 /* findNextInstruction - given a pCode, find the next instruction  */
3014 /*                       in the linked list                        */
3015 /*-----------------------------------------------------------------*/
3016 pCode * findPrevInstruction(pCode *pci)
3017 {
3018   return findPrevpCode(pci, PC_OPCODE);
3019 }
3020
3021 /*-----------------------------------------------------------------*/
3022 /* findFunctionEnd - given a pCode find the end of the function    */
3023 /*                   that contains it                              */
3024 /*-----------------------------------------------------------------*/
3025 pCode * findFunctionEnd(pCode *pc)
3026 {
3027
3028   while(pc) {
3029     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
3030       return pc;
3031
3032     pc = pc->next;
3033   }
3034
3035   fprintf(stderr,"Couldn't find function end\n");
3036   return NULL;
3037 }
3038
3039 #if 0
3040 /*-----------------------------------------------------------------*/
3041 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
3042 /*                instruction with which it is associated.         */
3043 /*-----------------------------------------------------------------*/
3044 static void AnalyzeLabel(pCode *pc)
3045 {
3046
3047   pCodeUnlink(pc);
3048
3049 }
3050 #endif
3051
3052 #if 0
3053 static void AnalyzeGOTO(pCode *pc)
3054 {
3055
3056   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3057
3058 }
3059
3060 static void AnalyzeSKIP(pCode *pc)
3061 {
3062
3063   pBranchLink(pc,findNextInstruction(pc->next));
3064   pBranchLink(pc,findNextInstruction(pc->next->next));
3065
3066 }
3067
3068 static void AnalyzeRETURN(pCode *pc)
3069 {
3070
3071   //  branch_link(pc,findFunctionEnd(pc->next));
3072
3073 }
3074
3075 #endif
3076
3077 /*-----------------------------------------------------------------*/
3078 /*-----------------------------------------------------------------*/
3079 regs * getRegFromInstruction(pCode *pc)
3080 {
3081   if(!pc                   || 
3082      !isPCI(pc)            ||
3083      !PCI(pc)->pcop        ||
3084      PCI(pc)->num_ops == 0 )
3085     return NULL;
3086
3087   switch(PCI(pc)->pcop->type) {
3088   case PO_INDF:
3089   case PO_FSR:
3090     return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
3091
3092   case PO_BIT:
3093   case PO_GPR_TEMP:
3094     //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3095     return PCOR(PCI(pc)->pcop)->r;
3096
3097   case PO_IMMEDIATE:
3098     //fprintf(stderr, "getRegFromInstruction - immediate\n");
3099     return NULL; // PCOR(PCI(pc)->pcop)->r;
3100
3101   case PO_GPR_BIT:
3102     return PCOR(PCI(pc)->pcop)->r;
3103
3104   case PO_DIR:
3105     //fprintf(stderr, "getRegFromInstruction - dir\n");
3106     return PCOR(PCI(pc)->pcop)->r;
3107   case PO_LITERAL:
3108     //fprintf(stderr, "getRegFromInstruction - literal\n");
3109     break;
3110
3111   default:
3112     //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3113     //genericPrint(stderr, pc);
3114     break;
3115   }
3116
3117   return NULL;
3118
3119 }
3120
3121 /*-----------------------------------------------------------------*/
3122 /*-----------------------------------------------------------------*/
3123
3124 void AnalyzepBlock(pBlock *pb)
3125 {
3126   pCode *pc;
3127
3128   if(!pb)
3129     return;
3130
3131   /* Find all of the registers used in this pBlock 
3132    * by looking at each instruction and examining it's
3133    * operands
3134    */
3135   for(pc = pb->pcHead; pc; pc = pc->next) {
3136
3137     /* Is this an instruction with operands? */
3138     if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3139
3140       if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3141
3142         /* Loop through all of the registers declared so far in
3143            this block and see if we find this one there */
3144
3145         regs *r = setFirstItem(pb->tregisters);
3146
3147         while(r) {
3148           if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3149             PCOR(PCI(pc)->pcop)->r = r;
3150             break;
3151           }
3152           r = setNextItem(pb->tregisters);
3153         }
3154
3155         if(!r) {
3156           /* register wasn't found */
3157           r = Safe_calloc(1, sizeof(regs));
3158           memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3159           addSet(&pb->tregisters, r);
3160           PCOR(PCI(pc)->pcop)->r = r;
3161           //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3162         }/* else 
3163           fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3164          */
3165       }
3166       if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3167         if(PCOR(PCI(pc)->pcop)->r) {
3168           pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3169           DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3170         } else {
3171           if(PCI(pc)->pcop->name)
3172             fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3173           else
3174             fprintf(stderr,"ERROR: NULL register\n");
3175         }
3176       }
3177     }
3178
3179
3180   }
3181 }
3182
3183 /*-----------------------------------------------------------------*/
3184 /* */
3185 /*-----------------------------------------------------------------*/
3186 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3187
3188 void InsertpFlow(pCode *pc, pCode **pflow)
3189 {
3190   PCFL(*pflow)->end = pc;
3191
3192   if(!pc || !pc->next)
3193     return;
3194
3195   *pflow = newpCodeFlow();
3196   pCodeInsertAfter(pc, *pflow);
3197 }
3198
3199 /*-----------------------------------------------------------------*/
3200 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
3201 /*                         the flow blocks.                        */
3202 /*
3203  * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3204  * point the instruction flow changes. 
3205  */
3206 /*-----------------------------------------------------------------*/
3207 void BuildFlow(pBlock *pb)
3208 {
3209   pCode *pc;
3210   pCode *last_pci=NULL;
3211   pCode *pflow;
3212   int seq = 0;
3213
3214   if(!pb)
3215     return;
3216
3217   //fprintf (stderr,"build flow start seq %d  ",GpcFlowSeq);
3218   /* Insert a pCodeFlow object at the beginning of a pBlock */
3219
3220   pflow = newpCodeFlow();    /* Create a new Flow object */
3221   pflow->next = pb->pcHead;  /* Make the current head the next object */
3222   pb->pcHead->prev = pflow;  /* let the current head point back to the flow object */
3223   pb->pcHead = pflow;        /* Make the Flow object the head */
3224   pflow->pb = pb;
3225
3226   for( pc = findNextInstruction(pb->pcHead);
3227        pc != NULL;
3228        pc=findNextInstruction(pc)) { 
3229
3230     pc->seq = seq++;
3231     PCI(pc)->pcflow = PCFL(pflow);
3232
3233     //fprintf(stderr," build: ");
3234     //pflow->print(stderr,pflow);
3235
3236     if( PCI(pc)->isSkip) {
3237
3238       /* The two instructions immediately following this one 
3239        * mark the beginning of a new flow segment */
3240
3241       while(pc && PCI(pc)->isSkip) {
3242
3243         PCI(pc)->pcflow = PCFL(pflow);
3244         pc->seq = seq-1;
3245         seq = 1;
3246
3247         InsertpFlow(pc, &pflow);
3248         pc=findNextInstruction(pc->next);
3249       }
3250
3251       seq = 0;
3252
3253       if(!pc)
3254         break;
3255
3256       PCI(pc)->pcflow = PCFL(pflow);
3257       pc->seq = 0;
3258       InsertpFlow(pc, &pflow);
3259
3260     } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next)))  {
3261
3262       InsertpFlow(pc, &pflow);
3263       seq = 0;
3264
3265     } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
3266
3267       /* This instruction marks the beginning of a
3268        * new flow segment */
3269
3270       pc->seq = 0;
3271       seq = 1; 
3272       InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3273
3274       PCI(pc)->pcflow = PCFL(pflow);
3275       
3276     }
3277     last_pci = pc;
3278     pc = pc->next;
3279   }
3280
3281   //fprintf (stderr,",end seq %d",GpcFlowSeq);
3282   PCFL(pflow)->end = pb->pcTail;
3283 }
3284
3285 /*-------------------------------------------------------------------*/
3286 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
3287 /*                           the flow blocks.                        */
3288 /*
3289  * unBuildFlow removes pCodeFlow objects from a pCode chain
3290  */
3291 /*-----------------------------------------------------------------*/
3292 void unBuildFlow(pBlock *pb)
3293 {
3294   pCode *pc;
3295
3296   if(!pb)
3297     return;
3298
3299   pc = pb->pcHead;
3300   while(pc) {
3301     pCode *pcn = pc->next;
3302
3303     if(isPCI(pc)) {
3304       pc->seq = 0;
3305       PCI(pc)->pcflow = NULL;
3306       pc = pcn;
3307     } else if(isPCFL(pc)) {
3308       unlinkPC(pc);
3309       pc->destruct(pc);
3310     } else 
3311       pc = pcn;
3312
3313   }
3314
3315 }
3316
3317 /*-----------------------------------------------------------------*/
3318 /*-----------------------------------------------------------------*/
3319 void dumpCond(int cond)
3320 {
3321
3322   static char *pcc_str[] = {
3323     //"PCC_NONE",
3324     "PCC_REGISTER",
3325     "PCC_C",
3326     "PCC_Z",
3327     "PCC_DC",
3328     "PCC_W",
3329     "PCC_EXAMINE_PCOP",
3330     "PCC_REG_BANK0",
3331     "PCC_REG_BANK1",
3332     "PCC_REG_BANK2",
3333     "PCC_REG_BANK3"
3334   };
3335
3336   int ncond = sizeof(pcc_str) / sizeof(char *);
3337   int i,j;
3338
3339   fprintf(stderr, "0x%04X\n",cond);
3340
3341   for(i=0,j=1; i<ncond; i++, j<<=1)
3342     if(cond & j)
3343       fprintf(stderr, "  %s\n",pcc_str[i]);
3344
3345 }
3346
3347 /*-----------------------------------------------------------------*/
3348 /*-----------------------------------------------------------------*/
3349 void FlowStats(pCodeFlow *pcflow)
3350 {
3351
3352   pCode *pc;
3353
3354   if(!isPCFL(pcflow))
3355     return;
3356
3357   fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3358
3359   pc = findNextpCode(PCODE(pcflow), PC_OPCODE); 
3360
3361   if(!pc) {
3362     fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3363     return;
3364   }
3365
3366
3367   fprintf(stderr, "  FlowStats inCond: ");
3368   dumpCond(pcflow->inCond);
3369   fprintf(stderr, "  FlowStats outCond: ");
3370   dumpCond(pcflow->outCond);
3371
3372 }
3373
3374 /*-----------------------------------------------------------------*
3375  * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3376  *    if it affects the banking bits. 
3377  * 
3378  * return: -1 == Banking bits are unaffected by this pCode.
3379  *
3380  * return: > 0 == Banking bits are affected.
3381  *
3382  *  If the banking bits are affected, then the returned value describes
3383  * which bits are affected and how they're affected. The lower half
3384  * of the integer maps to the bits that are affected, the upper half
3385  * to whether they're set or cleared.
3386  *
3387  *-----------------------------------------------------------------*/
3388 #define SET_BANK_BIT (1 << 16)
3389 #define CLR_BANK_BIT 0
3390
3391 int isBankInstruction(pCode *pc)
3392 {
3393   regs *reg;
3394   int bank = -1;
3395
3396   if(!isPCI(pc))
3397     return -1;
3398
3399   if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3400
3401     /* Check to see if the register banks are changing */
3402     if(PCI(pc)->isModReg) {
3403
3404       pCodeOp *pcop = PCI(pc)->pcop;
3405       switch(PCI(pc)->op) {
3406
3407       case POC_BSF:
3408         if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3409           //fprintf(stderr, "  isBankInstruction - Set RP0\n");
3410           return  SET_BANK_BIT | PIC_RP0_BIT;
3411         }
3412
3413         if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3414           //fprintf(stderr, "  isBankInstruction - Set RP1\n");
3415           return  CLR_BANK_BIT | PIC_RP0_BIT;
3416         }
3417         break;
3418
3419       case POC_BCF:
3420         if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3421           //fprintf(stderr, "  isBankInstruction - Clr RP0\n");
3422           return  CLR_BANK_BIT | PIC_RP1_BIT;
3423         }
3424         if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3425           //fprintf(stderr, "  isBankInstruction - Clr RP1\n");
3426           return  CLR_BANK_BIT | PIC_RP1_BIT;
3427         }
3428         break;
3429       default:
3430         //fprintf(stderr, "  isBankInstruction - Status register is getting Modified by:\n");
3431         //genericPrint(stderr, pc);
3432         ;
3433       }
3434     }
3435
3436   }
3437
3438   return bank;
3439 }
3440
3441
3442 /*-----------------------------------------------------------------*/
3443 /*-----------------------------------------------------------------*/
3444 void FillFlow(pCodeFlow *pcflow)
3445 {
3446
3447   pCode *pc;
3448   int cur_bank;
3449
3450   if(!isPCFL(pcflow))
3451     return;
3452
3453   //  fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3454
3455   pc = findNextpCode(PCODE(pcflow), PC_OPCODE); 
3456
3457   if(!pc) {
3458     //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3459     return;
3460   }
3461
3462   cur_bank = -1;
3463
3464   do {
3465     isBankInstruction(pc);
3466     pc = pc->next;
3467   } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3468
3469 /*
3470   if(!pc ) {
3471     fprintf(stderr, "  FillFlow - Bad end of flow\n");
3472   } else {
3473     fprintf(stderr, "  FillFlow - Ending flow with\n  ");
3474     pc->print(stderr,pc);
3475   }
3476
3477   fprintf(stderr, "  FillFlow inCond: ");
3478   dumpCond(pcflow->inCond);
3479   fprintf(stderr, "  FillFlow outCond: ");
3480   dumpCond(pcflow->outCond);
3481 */
3482 }
3483
3484 /*-----------------------------------------------------------------*/
3485 /*-----------------------------------------------------------------*/
3486 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3487 {
3488   pCodeFlowLink *fromLink, *toLink;
3489
3490   if(!from || !to || !to->pcflow || !from->pcflow)
3491     return;
3492
3493   fromLink = newpCodeFlowLink(from->pcflow);
3494   toLink   = newpCodeFlowLink(to->pcflow);
3495
3496   addSetIfnotP(&(from->pcflow->to), toLink);   //to->pcflow);
3497   addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3498
3499 }
3500
3501 /*-----------------------------------------------------------------*/
3502 /*-----------------------------------------------------------------*/
3503 void LinkFlow(pBlock *pb)
3504 {
3505   pCode *pc=NULL;
3506   pCode *pcflow;
3507   pCode *pct;
3508
3509   //fprintf(stderr,"linkflow \n");
3510
3511   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
3512        pcflow != NULL;
3513        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3514
3515     if(!isPCFL(pcflow))
3516       fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3517
3518     //fprintf(stderr," link: ");
3519     //pcflow->print(stderr,pcflow);
3520
3521     //FillFlow(PCFL(pcflow));
3522
3523     pc = PCFL(pcflow)->end;
3524
3525     //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3526     if(isPCI_SKIP(pc)) {
3527       //fprintf(stderr, "ends with skip\n");
3528       //pc->print(stderr,pc);
3529       pct=findNextInstruction(pc->next);
3530       LinkFlow_pCode(PCI(pc),PCI(pct));
3531       pct=findNextInstruction(pct->next);
3532       LinkFlow_pCode(PCI(pc),PCI(pct));
3533       continue;
3534     }
3535
3536     if(isPCI_BRANCH(pc)) {
3537       pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3538
3539       //fprintf(stderr, "ends with branch\n  ");
3540       //pc->print(stderr,pc);
3541
3542       if(!(pcol && isPCOLAB(pcol))) {
3543         if((PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
3544           pc->print(stderr,pc);
3545           fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3546         }
3547         continue;
3548       }
3549
3550       if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3551         LinkFlow_pCode(PCI(pc),PCI(pct));
3552       else
3553         fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
3554
3555       continue;
3556     }
3557
3558     if(isPCI(pc)) {
3559       //fprintf(stderr, "ends with non-branching instruction:\n");
3560       //pc->print(stderr,pc);
3561
3562       LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3563
3564       continue;
3565     }
3566
3567     if(pc) {
3568       //fprintf(stderr, "ends with unknown\n");
3569       //pc->print(stderr,pc);
3570       continue;
3571     }
3572
3573     //fprintf(stderr, "ends with nothing: ERROR\n");
3574     
3575   }
3576 }
3577
3578 /*-----------------------------------------------------------------*/
3579 /*-----------------------------------------------------------------*/
3580 int isPCinFlow(pCode *pc, pCode *pcflow)
3581 {
3582
3583   if(!pc || !pcflow)
3584     return 0;
3585
3586   if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3587     return 0;
3588
3589   if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3590     return 1;
3591
3592   return 0;
3593 }
3594
3595 /*-----------------------------------------------------------------*/
3596 /*-----------------------------------------------------------------*/
3597 void BanksUsedFlow2(pCode *pcflow)
3598 {
3599   pCode *pc=NULL;
3600
3601   int bank = -1;
3602   bool RegUsed = 0;
3603
3604   regs *reg;
3605
3606   if(!isPCFL(pcflow)) {
3607     fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3608     return;
3609   }
3610
3611   pc = findNextInstruction(pcflow->next);
3612
3613   PCFL(pcflow)->lastBank = -1;
3614
3615   while(isPCinFlow(pc,pcflow)) {
3616
3617     int bank_selected = isBankInstruction(pc);
3618
3619     //if(PCI(pc)->pcflow) 
3620     //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3621
3622     if(bank_selected > 0) {
3623       //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3624
3625       /* This instruction is modifying banking bits before accessing registers */
3626       if(!RegUsed)
3627         PCFL(pcflow)->firstBank = -1;
3628
3629       if(PCFL(pcflow)->lastBank == -1)
3630         PCFL(pcflow)->lastBank = 0;
3631
3632       bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3633       if(bank_selected & SET_BANK_BIT)
3634         PCFL(pcflow)->lastBank |= bank;
3635                                  
3636
3637     } else { 
3638       reg = getRegFromInstruction(pc);
3639
3640       if(reg && !isREGinBank(reg, bank)) {
3641         int allbanks = REGallBanks(reg);
3642         if(bank == -1)
3643           PCFL(pcflow)->firstBank = allbanks;
3644
3645         PCFL(pcflow)->lastBank = allbanks;
3646
3647         bank = allbanks;
3648       }
3649       RegUsed = 1;
3650     }
3651
3652     pc = findNextInstruction(pc->next);
3653   }
3654
3655 //  fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3656 //        pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3657
3658
3659
3660 }
3661 /*-----------------------------------------------------------------*/
3662 /*-----------------------------------------------------------------*/
3663 void BanksUsedFlow(pBlock *pb)
3664 {
3665   pCode *pcflow;
3666
3667
3668   //pb->pcHead->print(stderr, pb->pcHead);
3669
3670   pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3671   //pcflow->print(stderr,pcflow);
3672
3673   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
3674        pcflow != NULL;
3675        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3676
3677     BanksUsedFlow2(pcflow);
3678   }
3679
3680 }
3681
3682
3683 /*-----------------------------------------------------------------*/
3684 /*-----------------------------------------------------------------*/
3685 void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
3686 {
3687   pCode *new_pc;
3688
3689   if(!pc)
3690     return;
3691
3692   if(RP_BankBit < 0) 
3693     new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3694   else
3695     new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3696                       popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3697
3698   pCodeInsertAfter(pc->prev, new_pc);
3699
3700   /* Move the label, if there is one */
3701
3702   if(PCI(pc)->label) {
3703     PCI(new_pc)->label = PCI(pc)->label;
3704     PCI(pc)->label = NULL;
3705   }
3706
3707   /* The new instruction has the same pcflow block */
3708   PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3709
3710 }
3711 /*-----------------------------------------------------------------*/
3712 /*-----------------------------------------------------------------*/
3713 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3714 {
3715   pCode *pc=NULL;
3716   pCode *pcprev=NULL;
3717   pCode *new_pc;
3718
3719   regs *reg;
3720
3721   if(!pcfl)
3722     return;
3723
3724   pc = findNextInstruction(pcfl->pc.next);
3725
3726   while(isPCinFlow(pc,PCODE(pcfl))) {
3727
3728
3729     reg = getRegFromInstruction(pc);
3730 #if 0
3731     if(reg) {
3732       fprintf(stderr, "  %s  ",reg->name);
3733       fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3734
3735     }
3736 #endif
3737
3738     if(reg && REG_BANK(reg)!=cur_bank) {
3739       /* Examine the instruction before this one to make sure it is
3740        * not a skip type instruction */
3741       pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3742       if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3743         int b = cur_bank ^ REG_BANK(reg);
3744
3745         //fprintf(stderr, "Cool! can switch banks\n");
3746         cur_bank = REG_BANK(reg);
3747         switch(b & 3) {
3748         case 0:
3749           break;
3750         case 1:
3751           insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3752           break;
3753         case 2:
3754           insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3755           insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3756           break;
3757         case 3:
3758           if(cur_bank & 3) {
3759             insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3760             insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3761           } else
3762             insertBankSwitch(pc, -1, -1);
3763           break;
3764           /*
3765             new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3766             popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3767             pCodeInsertAfter(pc->prev, new_pc);
3768             if(PCI(pc)->label) { 
3769             PCI(new_pc)->label = PCI(pc)->label;
3770             PCI(pc)->label = NULL;
3771             }
3772           */
3773           /*
3774             new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3775             popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3776             pCodeInsertAfter(pc, new_pc);
3777           */
3778
3779         }
3780
3781       } else {
3782         //fprintf(stderr, "Bummer can't switch banks\n");
3783         ;
3784       }
3785     }
3786
3787     pcprev = pc;
3788     pc = findNextInstruction(pc->next);
3789
3790   }
3791
3792   if(pcprev && cur_bank) {
3793     /* Brute force - make sure that we point to bank 0 at the
3794      * end of each flow block */
3795     new_pc = newpCode(POC_BCF,
3796                       popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3797     pCodeInsertAfter(pcprev, new_pc);
3798       cur_bank = 0;
3799   }
3800
3801 }
3802
3803 /*-----------------------------------------------------------------*/
3804 /*int compareBankFlow - compare the banking requirements between   */
3805 /*  flow objects. */
3806 /*-----------------------------------------------------------------*/
3807 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3808 {
3809
3810   if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3811     return 0;
3812
3813   if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3814     return 0;
3815
3816   if(pcflow->firstBank == -1)
3817     return 0;
3818
3819
3820   if(pcflowLink->pcflow->firstBank == -1) {
3821     pCodeFlowLink *pctl = setFirstItem( toORfrom ? 
3822                                         pcflowLink->pcflow->to : 
3823                                         pcflowLink->pcflow->from);
3824     return compareBankFlow(pcflow, pctl, toORfrom);
3825   }
3826
3827   if(toORfrom) {
3828     if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3829       return 0;
3830
3831     pcflowLink->bank_conflict++;
3832     pcflowLink->pcflow->FromConflicts++;
3833     pcflow->ToConflicts++;
3834   } else {
3835     
3836     if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3837       return 0;
3838
3839     pcflowLink->bank_conflict++;
3840     pcflowLink->pcflow->ToConflicts++;
3841     pcflow->FromConflicts++;
3842
3843   }
3844   /*
3845   fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3846           pcflowLink->pcflow->pc.seq,
3847           pcflowLink->pcflow->FromConflicts,
3848           pcflowLink->pcflow->ToConflicts);
3849   */
3850   return 1;
3851
3852 }
3853 /*-----------------------------------------------------------------*/
3854 /*-----------------------------------------------------------------*/
3855 void FixBankFlow(pBlock *pb)
3856 {
3857   pCode *pc=NULL;
3858   pCode *pcflow;
3859   pCodeFlowLink *pcfl;
3860
3861   pCode *pcflow_max_To=NULL;
3862   pCode *pcflow_max_From=NULL;
3863   int max_ToConflicts=0;
3864   int max_FromConflicts=0;
3865
3866   //fprintf(stderr,"Fix Bank flow \n");
3867   pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3868
3869
3870   /*
3871     First loop through all of the flow objects in this pcode block
3872     and fix the ones that have banking conflicts between the 
3873     entry and exit.
3874   */
3875
3876   //fprintf(stderr, "FixBankFlow - Phase 1\n");
3877
3878   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
3879        pcflow != NULL;
3880        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3881
3882     if(!isPCFL(pcflow)) {
3883       fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3884       continue;
3885     }
3886
3887     if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank  &&
3888        PCFL(pcflow)->firstBank >= 0 &&
3889        PCFL(pcflow)->lastBank >= 0 ) {
3890
3891       int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
3892         PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
3893
3894       FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
3895       BanksUsedFlow2(pcflow);
3896
3897     }
3898   }
3899
3900   //fprintf(stderr, "FixBankFlow - Phase 2\n");
3901
3902   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
3903        pcflow != NULL;
3904        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3905
3906     int nFlows;
3907     int nConflicts;
3908
3909     if(!isPCFL(pcflow)) {
3910       fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
3911       continue;
3912     }
3913
3914     PCFL(pcflow)->FromConflicts = 0;
3915     PCFL(pcflow)->ToConflicts = 0;
3916
3917     nFlows = 0;
3918     nConflicts = 0;
3919
3920     //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
3921     pcfl = setFirstItem(PCFL(pcflow)->from);
3922     while (pcfl) {
3923
3924       pc = PCODE(pcfl->pcflow);
3925
3926       if(!isPCFL(pc)) {
3927         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
3928         pc->print(stderr,pc);
3929       }
3930
3931       nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
3932       nFlows++;
3933
3934       pcfl=setNextItem(PCFL(pcflow)->from);
3935     }
3936
3937     if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
3938       //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
3939
3940       FixRegisterBankingInFlow(PCFL(pcflow),0);
3941       BanksUsedFlow2(pcflow);
3942
3943       continue;  /* Don't need to check the flow from here - it's already been fixed */
3944
3945     }
3946
3947     nFlows = 0;
3948     nConflicts = 0;
3949
3950     pcfl = setFirstItem(PCFL(pcflow)->to);
3951     while (pcfl) {
3952
3953       pc = PCODE(pcfl->pcflow);
3954       if(!isPCFL(pc)) {
3955         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
3956         pc->print(stderr,pc);
3957       }
3958
3959       nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
3960       nFlows++;
3961
3962       pcfl=setNextItem(PCFL(pcflow)->to);
3963     }
3964
3965     if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
3966       //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
3967
3968       FixRegisterBankingInFlow(PCFL(pcflow),0);
3969       BanksUsedFlow2(pcflow);
3970     }
3971   }
3972
3973   /*
3974     Loop through the flow objects again and find the ones with the 
3975     maximum conflicts
3976   */
3977
3978   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
3979        pcflow != NULL;
3980        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3981
3982     if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
3983       pcflow_max_To = pcflow;
3984
3985     if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
3986       pcflow_max_From = pcflow;
3987   }
3988 /*
3989   if(pcflow_max_To)
3990     fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
3991             PCFL(pcflow_max_To)->pc.seq,
3992             PCFL(pcflow_max_To)->ToConflicts);
3993
3994   if(pcflow_max_From)
3995     fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
3996             PCFL(pcflow_max_From)->pc.seq,
3997             PCFL(pcflow_max_From)->FromConflicts);
3998 */
3999 }
4000
4001 /*-----------------------------------------------------------------*/
4002 /*-----------------------------------------------------------------*/
4003 void DumpFlow(pBlock *pb)
4004 {
4005   pCode *pc=NULL;
4006   pCode *pcflow;
4007   pCodeFlowLink *pcfl;
4008
4009
4010   fprintf(stderr,"Dump flow \n");
4011   pb->pcHead->print(stderr, pb->pcHead);
4012
4013   pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4014   pcflow->print(stderr,pcflow);
4015
4016   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4017        pcflow != NULL;
4018        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4019
4020     if(!isPCFL(pcflow)) {
4021       fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4022       continue;
4023     }
4024     fprintf(stderr,"dumping: ");
4025     pcflow->print(stderr,pcflow);
4026     FlowStats(PCFL(pcflow));
4027
4028     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4029
4030       pc = PCODE(pcfl->pcflow);
4031
4032       fprintf(stderr, "    from seq %d:\n",pc->seq);
4033       if(!isPCFL(pc)) {
4034         fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4035         pc->print(stderr,pc);
4036       }
4037
4038     }
4039
4040     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4041
4042       pc = PCODE(pcfl->pcflow);
4043
4044       fprintf(stderr, "    to seq %d:\n",pc->seq);
4045       if(!isPCFL(pc)) {
4046         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4047         pc->print(stderr,pc);
4048       }
4049
4050     }
4051
4052   }
4053
4054 }
4055
4056 /*-----------------------------------------------------------------*/
4057 /*-----------------------------------------------------------------*/
4058 int OptimizepBlock(pBlock *pb)
4059 {
4060   pCode *pc, *pcprev;
4061   int matches =0;
4062
4063   if(!pb || !peepOptimizing)
4064     return 0;
4065
4066   DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4067 /*
4068   for(pc = pb->pcHead; pc; pc = pc->next)
4069     matches += pCodePeepMatchRule(pc);
4070 */
4071
4072   pc = findNextInstruction(pb->pcHead);
4073   pcprev = pc->prev;
4074   do {
4075
4076
4077     if(pCodePeepMatchRule(pc)) {
4078
4079       matches++;
4080
4081       if(pcprev)
4082         pc = findNextInstruction(pcprev->next);
4083       else 
4084         pc = findNextInstruction(pb->pcHead);
4085     } else
4086       pc = findNextInstruction(pc->next);
4087   } while(pc);
4088
4089   if(matches)
4090     DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4091   return matches;
4092
4093 }
4094
4095 /*-----------------------------------------------------------------*/
4096 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
4097 /*-----------------------------------------------------------------*/
4098 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4099 {
4100   pCode *pc;
4101
4102   for(pc = pcs; pc; pc = pc->next) {
4103
4104     if((pc->type == PC_OPCODE) && 
4105        (PCI(pc)->pcop) && 
4106        (PCI(pc)->pcop->type == PO_LABEL) &&
4107        (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4108       return pc;
4109   }
4110  
4111
4112   return NULL;
4113 }
4114
4115 /*-----------------------------------------------------------------*/
4116 /*-----------------------------------------------------------------*/
4117 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4118 {
4119
4120   if(isPCI(pc) && 
4121      (PCI(pc)->pcop) && 
4122      (PCI(pc)->pcop->type == PO_LABEL)) {
4123
4124     pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4125
4126     //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4127     if(pcol->pcop.name)
4128       free(pcol->pcop.name);
4129
4130     sprintf(buffer,"_%05d_DS_",pcl->key);
4131
4132     pcol->pcop.name = Safe_strdup(buffer);
4133     pcol->key = pcl->key;
4134     //pc->print(stderr,pc);
4135
4136   }
4137
4138
4139 }
4140
4141 /*-----------------------------------------------------------------*/
4142 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
4143 /*                            pCode chain if they're not used.     */
4144 /*-----------------------------------------------------------------*/
4145 void pBlockRemoveUnusedLabels(pBlock *pb)
4146 {
4147   pCode *pc; pCodeLabel *pcl;
4148
4149   if(!pb)
4150     return;
4151
4152   for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4153
4154     pBranch *pbr = PCI(pc)->label;
4155     if(pbr && pbr->next) {
4156       pCode *pcd = pb->pcHead;
4157
4158       //fprintf(stderr, "multiple labels\n");
4159       //pc->print(stderr,pc);
4160
4161       pbr = pbr->next;
4162       while(pbr) {
4163
4164         while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4165           //fprintf(stderr,"Used by:\n");
4166           //pcd->print(stderr,pcd);
4167
4168           exchangeLabels(PCL(pbr->pc),pcd);
4169
4170           pcd = pcd->next;
4171         }
4172         pbr = pbr->next;
4173       }
4174     }
4175   }
4176
4177   for(pc = pb->pcHead; pc; pc = pc->next) {
4178
4179     if(isPCL(pc)) // pc->type == PC_LABEL)
4180       pcl = PCL(pc);
4181     else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4182       pcl = PCL(PCI(pc)->label->pc);
4183     else continue;
4184
4185     //fprintf(stderr," found  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4186
4187     /* This pCode is a label, so search the pBlock to see if anyone
4188      * refers to it */
4189
4190     if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4191     //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4192       /* Couldn't find an instruction that refers to this label
4193        * So, unlink the pCode label from it's pCode chain
4194        * and destroy the label */
4195       //fprintf(stderr," removed  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4196
4197       DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4198       if(pc->type == PC_LABEL) {
4199         unlinkPC(pc);
4200         pCodeLabelDestruct(pc);
4201       } else {
4202         unlinkpCodeFromBranch(pc, PCODE(pcl));
4203         /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4204           free(pc->label);
4205         }*/
4206       }
4207
4208     }
4209   }
4210
4211 }
4212
4213
4214 /*-----------------------------------------------------------------*/
4215 /* pBlockMergeLabels - remove the pCode labels from the pCode      */
4216 /*                     chain and put them into pBranches that are  */
4217 /*                     associated with the appropriate pCode       */
4218 /*                     instructions.                               */
4219 /*-----------------------------------------------------------------*/
4220 void pBlockMergeLabels(pBlock *pb)
4221 {
4222   pBranch *pbr;
4223   pCode *pc, *pcnext=NULL;
4224
4225   if(!pb)
4226     return;
4227
4228   /* First, Try to remove any unused labels */
4229   //pBlockRemoveUnusedLabels(pb);
4230
4231   /* Now loop through the pBlock and merge the labels with the opcodes */
4232
4233   for(pc = pb->pcHead; pc; pc = pc->next) {
4234
4235     if(pc->type == PC_LABEL) {
4236
4237       //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4238       //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4239       if((pcnext = findNextInstruction(pc) )) {
4240
4241         pCode *pcn = pc->next;
4242
4243         // Unlink the pCode label from it's pCode chain
4244         unlinkPC(pc);
4245         
4246         //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4247         // And link it into the instruction's pBranch labels. (Note, since
4248         // it's possible to have multiple labels associated with one instruction
4249         // we must provide a means to accomodate the additional labels. Thus
4250         // the labels are placed into the singly-linked list "label" as 
4251         // opposed to being a single member of the pCodeInstruction.)
4252
4253         //_ALLOC(pbr,sizeof(pBranch));
4254         pbr = Safe_calloc(1,sizeof(pBranch));
4255         pbr->pc = pc;
4256         pbr->next = NULL;
4257
4258
4259         PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4260       
4261         pc = pcn;
4262
4263       } else {
4264         fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4265       }
4266     } else if(pc->type == PC_CSOURCE) {
4267
4268       /* merge the source line symbolic info into the next instruction */
4269       if((pcnext = findNextInstruction(pc) )) {
4270
4271         pCode *pcn = pc->next;
4272
4273         // Unlink the pCode label from it's pCode chain
4274         unlinkPC(pc);
4275         PCI(pcnext)->cline = PCCS(pc);
4276         //fprintf(stderr, "merging CSRC\n");
4277         //genericPrint(stderr,pcnext);
4278         pc = pcn;
4279       }
4280
4281     }
4282
4283   }
4284   pBlockRemoveUnusedLabels(pb);
4285
4286 }
4287
4288 /*-----------------------------------------------------------------*/
4289 /*-----------------------------------------------------------------*/
4290 int OptimizepCode(char dbName)
4291 {
4292 #define MAX_PASSES 4
4293
4294   int matches = 0;
4295   int passes = 0;
4296   pBlock *pb;
4297
4298   if(!the_pFile)
4299     return 0;
4300
4301   DFPRINTF((stderr," Optimizing pCode\n"));
4302
4303   do {
4304     matches = 0;
4305     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4306       if('*' == dbName || getpBlock_dbName(pb) == dbName)
4307         matches += OptimizepBlock(pb);
4308     }
4309   }
4310   while(matches && ++passes < MAX_PASSES);
4311
4312   return matches;
4313 }
4314
4315 /*-----------------------------------------------------------------*/
4316 /* popCopyGPR2Bit - copy a pcode operator                          */
4317 /*-----------------------------------------------------------------*/
4318
4319 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4320 {
4321   pCodeOp *pcop;
4322
4323   pcop = newpCodeOpBit(pc->name, bitval, 0);
4324
4325   if( !( (pcop->type == PO_LABEL) ||
4326          (pcop->type == PO_LITERAL) ||
4327          (pcop->type == PO_STR) ))
4328     PCOR(pcop)->r = PCOR(pc)->r;  /* This is dangerous... */
4329
4330   return pcop;
4331 }
4332
4333
4334
4335 #if 0
4336 /*-----------------------------------------------------------------*/
4337 /*-----------------------------------------------------------------*/
4338 int InstructionRegBank(pCode *pc)
4339 {
4340   regs *reg;
4341
4342   if( (reg = getRegFromInstruction(pc)) == NULL)
4343     return -1;
4344
4345   return REG_BANK(reg);
4346
4347 }
4348 #endif
4349
4350 /*-----------------------------------------------------------------*/
4351 /*-----------------------------------------------------------------*/
4352 void FixRegisterBanking(pBlock *pb)
4353 {
4354   pCode *pc=NULL;
4355   pCode *pcprev=NULL;
4356   pCode *new_pc;
4357
4358   int cur_bank;
4359   regs *reg;
4360   //  return;
4361   if(!pb)
4362     return;
4363
4364   //pc = findNextpCode(pb->pcHead, PC_FLOW);
4365   pc = findNextpCode(pb->pcHead, PC_OPCODE);
4366   if(!pc)
4367     return;
4368   /* loop through all of the flow blocks with in one pblock */
4369
4370   //fprintf(stderr,"Register banking\n");
4371   cur_bank = 0;
4372   do {
4373     /* at this point, pc should point to a PC_FLOW object */
4374
4375
4376     /* for each flow block, determine the register banking 
4377        requirements */
4378
4379     //    do {
4380       if(isPCI(pc)) {
4381         //genericPrint(stderr, pc);
4382
4383         reg = getRegFromInstruction(pc);
4384         #if 0
4385         if(reg) {
4386           fprintf(stderr, "  %s  ",reg->name);
4387           fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4388
4389         }
4390         #endif
4391         if(reg && REG_BANK(reg)!=cur_bank) {
4392           /* Examine the instruction before this one to make sure it is
4393            * not a skip type instruction */
4394           pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4395           if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4396             int b = cur_bank ^ REG_BANK(reg);
4397
4398             //fprintf(stderr, "Cool! can switch banks\n");
4399             cur_bank = REG_BANK(reg);
4400             if(b & 1) {
4401               new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
4402                                 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4403               pCodeInsertAfter(pc->prev, new_pc);
4404               if(PCI(pc)->label) { 
4405                 PCI(new_pc)->label = PCI(pc)->label;
4406                 PCI(pc)->label = NULL;
4407               }
4408               /*
4409                 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
4410                 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4411                 pCodeInsertAfter(pc, new_pc);
4412               */
4413
4414             }
4415
4416           } else {
4417             //fprintf(stderr, "Bummer can't switch banks\n");
4418             ;
4419           }
4420         }
4421       }
4422
4423       pcprev = pc;
4424       pc = pc->next;
4425       // } while(pc && !(isPCFL(pc))); 
4426
4427
4428   }while (pc);
4429
4430     if(pcprev && cur_bank) {
4431       /* Brute force - make sure that we point to bank 0 at the
4432        * end of each flow block */
4433       new_pc = newpCode(POC_BCF,
4434                         popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4435       pCodeInsertAfter(pcprev, new_pc);
4436       cur_bank = 0;
4437     }
4438
4439 }
4440
4441 void pBlockDestruct(pBlock *pb)
4442 {
4443
4444   if(!pb)
4445     return;
4446
4447
4448   free(pb);
4449
4450 }
4451
4452 /*-----------------------------------------------------------------*/
4453 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4454 /*                                  name dbName and combine them   */
4455 /*                                  into one block                 */
4456 /*-----------------------------------------------------------------*/
4457 void mergepBlocks(char dbName)
4458 {
4459
4460   pBlock *pb, *pbmerged = NULL,*pbn;
4461
4462   pb = the_pFile->pbHead;
4463
4464   //fprintf(stderr," merging blocks named %c\n",dbName);
4465   while(pb) {
4466
4467     pbn = pb->next;
4468     //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4469     if( getpBlock_dbName(pb) == dbName) {
4470
4471       //fprintf(stderr," merged block %c\n",dbName);
4472
4473       if(!pbmerged) {
4474         pbmerged = pb;
4475       } else {
4476         addpCode2pBlock(pbmerged, pb->pcHead);
4477         /* addpCode2pBlock doesn't handle the tail: */
4478         pbmerged->pcTail = pb->pcTail;
4479
4480         pb->prev->next = pbn;
4481         if(pbn) 
4482           pbn->prev = pb->prev;
4483
4484
4485         pBlockDestruct(pb);
4486       }
4487       //printpBlock(stderr, pbmerged);
4488     } 
4489     pb = pbn;
4490   }
4491
4492 }
4493
4494 /*-----------------------------------------------------------------*/
4495 /* AnalyzeBanking - Called after the memory addresses have been    */
4496 /*                  assigned to the registers.                     */
4497 /*                                                                 */
4498 /*-----------------------------------------------------------------*/
4499 void AnalyzeBanking(void)
4500 {
4501
4502   pBlock *pb;
4503
4504   if(!the_pFile)
4505     return;
4506
4507
4508   /* Phase 2 - Flow Analysis - Register Banking
4509    *
4510    * In this phase, the individual flow blocks are examined
4511    * and register banking is fixed.
4512    */
4513
4514   //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4515   //FixRegisterBanking(pb);
4516
4517   /* Phase 2 - Flow Analysis
4518    *
4519    * In this phase, the pCode is partition into pCodeFlow 
4520    * blocks. The flow blocks mark the points where a continuous
4521    * stream of instructions changes flow (e.g. because of
4522    * a call or goto or whatever).
4523    */
4524
4525   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4526     BuildFlow(pb);
4527
4528
4529   /* Phase 2 - Flow Analysis - linking flow blocks
4530    *
4531    * In this phase, the individual flow blocks are examined
4532    * to determine their order of excution.
4533    */
4534
4535   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4536     LinkFlow(pb);
4537
4538
4539   /* Phase x - Flow Analysis - Used Banks
4540    *
4541    * In this phase, the individual flow blocks are examined
4542    * to determine the Register Banks they use
4543    */
4544
4545   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4546     BanksUsedFlow(pb);
4547
4548   /* Phase x - Flow Analysis - Used Banks
4549    *
4550    * In this phase, the individual flow blocks are examined
4551    * to determine the Register Banks they use
4552    */
4553
4554   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4555     FixBankFlow(pb);
4556
4557 /*
4558   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4559     DumpFlow(pb);
4560 */
4561   /* debug stuff */ 
4562   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4563     pCode *pcflow;
4564     for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4565          (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4566          pcflow = pcflow->next) {
4567
4568       FillFlow(PCFL(pcflow));
4569     }
4570   }
4571 /*
4572   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4573     pCode *pcflow;
4574     for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4575          (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4576          pcflow = pcflow->next) {
4577
4578       FlowStats(PCFL(pcflow));
4579     }
4580   }
4581 */
4582 }
4583
4584 /*-----------------------------------------------------------------*/
4585 /* buildCallTree - look at the flow and extract all of the calls   */
4586 /*                                                                 */
4587 /*-----------------------------------------------------------------*/
4588 set *register_usage(pBlock *pb);
4589
4590 void buildCallTree(void    )
4591 {
4592   pBranch *pbr;
4593   pBlock  *pb;
4594   pCode   *pc;
4595
4596   if(!the_pFile)
4597     return;
4598
4599
4600
4601   /* Now build the call tree.
4602      First we examine all of the pCodes for functions.
4603      Keep in mind that the function boundaries coincide
4604      with pBlock boundaries. 
4605
4606      The algorithm goes something like this:
4607      We have two nested loops. The outer loop iterates
4608      through all of the pBlocks/functions. The inner
4609      loop iterates through all of the pCodes for
4610      a given pBlock. When we begin iterating through
4611      a pBlock, the variable pc_fstart, pCode of the start
4612      of a function, is cleared. We then search for pCodes
4613      of type PC_FUNCTION. When one is encountered, we
4614      initialize pc_fstart to this and at the same time
4615      associate a new pBranch object that signifies a 
4616      branch entry. If a return is found, then this signifies
4617      a function exit point. We'll link the pCodes of these
4618      returns to the matching pc_fstart.
4619
4620      When we're done, a doubly linked list of pBranches
4621      will exist. The head of this list is stored in
4622      `the_pFile', which is the meta structure for all
4623      of the pCode. Look at the printCallTree function
4624      on how the pBranches are linked together.
4625
4626    */
4627   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4628     pCode *pc_fstart=NULL;
4629     for(pc = pb->pcHead; pc; pc = pc->next) {
4630       if(isPCF(pc)) {
4631         if (PCF(pc)->fname) {
4632
4633           if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4634             //fprintf(stderr," found main \n");
4635             pb->cmemmap = NULL;  /* FIXME do we need to free ? */
4636             pb->dbName = 'M';
4637           }
4638
4639           pbr = Safe_calloc(1,sizeof(pBranch));
4640           pbr->pc = pc_fstart = pc;
4641           pbr->next = NULL;
4642
4643           the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4644
4645           // Here's a better way of doing the same:
4646           addSet(&pb->function_entries, pc);
4647
4648         } else {
4649           // Found an exit point in a function, e.g. return
4650           // (Note, there may be more than one return per function)
4651           if(pc_fstart)
4652             pBranchLink(PCF(pc_fstart), PCF(pc));
4653
4654           addSet(&pb->function_exits, pc);
4655         }
4656       } else if(isCALL(pc)) {
4657         addSet(&pb->function_calls,pc);
4658       }
4659     }
4660   }
4661
4662   /* Re-allocate the registers so that there are no collisions
4663    * between local variables when one function call another */
4664
4665   pic14_deallocateAllRegs();
4666
4667   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4668     if(!pb->visited)
4669       register_usage(pb);
4670   }
4671
4672 }
4673
4674 /*-----------------------------------------------------------------*/
4675 /* AnalyzepCode - parse the pCode that has been generated and form */
4676 /*                all of the logical connections.                  */
4677 /*                                                                 */
4678 /* Essentially what's done here is that the pCode flow is          */
4679 /* determined.                                                     */
4680 /*-----------------------------------------------------------------*/
4681
4682 void AnalyzepCode(char dbName)
4683 {
4684   pBlock *pb;
4685   int i,changes;
4686
4687   if(!the_pFile)
4688     return;
4689
4690   mergepBlocks('D');
4691
4692
4693   /* Phase 1 - Register allocation and peep hole optimization
4694    *
4695    * The first part of the analysis is to determine the registers
4696    * that are used in the pCode. Once that is done, the peep rules
4697    * are applied to the code. We continue to loop until no more
4698    * peep rule optimizations are found (or until we exceed the
4699    * MAX_PASSES threshold). 
4700    *
4701    * When done, the required registers will be determined.
4702    *
4703    */
4704   i = 0;
4705   do {
4706
4707     DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4708     //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4709
4710     /* First, merge the labels with the instructions */
4711     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4712       if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4713
4714         DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4715         //fprintf(stderr," analyze and merging block %c\n",dbName);
4716         pBlockMergeLabels(pb);
4717         AnalyzepBlock(pb);
4718       } else {
4719         DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4720       }
4721     }
4722
4723     changes = OptimizepCode(dbName);
4724
4725   } while(changes && (i++ < MAX_PASSES));
4726
4727   buildCallTree();
4728 }
4729
4730 /*-----------------------------------------------------------------*/
4731 /* ispCodeFunction - returns true if *pc is the pCode of a         */
4732 /*                   function                                      */
4733 /*-----------------------------------------------------------------*/
4734 bool ispCodeFunction(pCode *pc)
4735 {
4736
4737   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
4738     return 1;
4739
4740   return 0;
4741 }
4742
4743 /*-----------------------------------------------------------------*/
4744 /* findFunction - Search for a function by name (given the name)   */
4745 /*                in the set of all functions that are in a pBlock */
4746 /* (note - I expect this to change because I'm planning to limit   */
4747 /*  pBlock's to just one function declaration                      */
4748 /*-----------------------------------------------------------------*/
4749 pCode *findFunction(char *fname)
4750 {
4751   pBlock *pb;
4752   pCode *pc;
4753   if(!fname)
4754     return NULL;
4755
4756   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4757
4758     pc = setFirstItem(pb->function_entries);
4759     while(pc) {
4760     
4761       if((pc->type == PC_FUNCTION) &&
4762          (PCF(pc)->fname) && 
4763          (strcmp(fname, PCF(pc)->fname)==0))
4764         return pc;
4765
4766       pc = setNextItem(pb->function_entries);
4767
4768     }
4769
4770   }
4771   return NULL;
4772 }
4773
4774 void MarkUsedRegisters(set *regset)
4775 {
4776
4777   regs *r1,*r2;
4778
4779   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4780     r2 = pic14_regWithIdx(r1->rIdx);
4781     r2->isFree = 0;
4782     r2->wasUsed = 1;
4783   }
4784 }
4785
4786 void pBlockStats(FILE *of, pBlock *pb)
4787 {
4788
4789   pCode *pc;
4790   regs  *r;
4791
4792   fprintf(of,";***\n;  pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4793
4794   // for now just print the first element of each set
4795   pc = setFirstItem(pb->function_entries);
4796   if(pc) {
4797     fprintf(of,";entry:  ");
4798     pc->print(of,pc);
4799   }
4800   pc = setFirstItem(pb->function_exits);
4801   if(pc) {
4802     fprintf(of,";has an exit\n");
4803     //pc->print(of,pc);
4804   }
4805
4806   pc = setFirstItem(pb->function_calls);
4807   if(pc) {
4808     fprintf(of,";functions called:\n");
4809
4810     while(pc) {
4811       if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4812         fprintf(of,";   %s\n",get_op_from_instruction(PCI(pc)));
4813       }
4814       pc = setNextItem(pb->function_calls);
4815     }
4816   }
4817
4818   r = setFirstItem(pb->tregisters);
4819   if(r) {
4820     int n = elementsInSet(pb->tregisters);
4821
4822     fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
4823
4824     while (r) {
4825       fprintf(of,";   %s\n",r->name);
4826       r = setNextItem(pb->tregisters);
4827     }
4828   }
4829 }
4830
4831 /*-----------------------------------------------------------------*/
4832 /*-----------------------------------------------------------------*/
4833 #if 0
4834 static void sequencepCode(void)
4835 {
4836   pBlock *pb;
4837   pCode *pc;
4838
4839
4840   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4841
4842     pb->seq = GpCodeSequenceNumber+1;
4843
4844     for( pc = pb->pcHead; pc; pc = pc->next)
4845       pc->seq = ++GpCodeSequenceNumber;
4846   }
4847
4848 }
4849 #endif
4850
4851 /*-----------------------------------------------------------------*/
4852 /*-----------------------------------------------------------------*/
4853 set *register_usage(pBlock *pb)
4854 {
4855   pCode *pc,*pcn;
4856   set *registers=NULL;
4857   set *registersInCallPath = NULL;
4858
4859   /* check recursion */
4860
4861   pc = setFirstItem(pb->function_entries);
4862
4863   if(!pc)
4864     return registers;
4865
4866   pb->visited = 1;
4867
4868   if(pc->type != PC_FUNCTION)
4869     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
4870
4871   pc = setFirstItem(pb->function_calls);
4872   for( ; pc; pc = setNextItem(pb->function_calls)) {
4873
4874     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4875       char *dest = get_op_from_instruction(PCI(pc));
4876
4877       pcn = findFunction(dest);
4878       if(pcn) 
4879         registersInCallPath = register_usage(pcn->pb);
4880     } else
4881       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
4882
4883   }
4884
4885 #ifdef PCODE_DEBUG
4886   pBlockStats(stderr,pb);  // debug
4887 #endif
4888
4889   // Mark the registers in this block as used.
4890
4891   MarkUsedRegisters(pb->tregisters);
4892   if(registersInCallPath) {
4893     /* registers were used in the functions this pBlock has called */
4894     /* so now, we need to see if these collide with the ones we are */
4895     /* using here */
4896
4897     regs *r1,*r2, *newreg;
4898
4899     DFPRINTF((stderr,"comparing registers\n"));
4900
4901     r1 = setFirstItem(registersInCallPath);
4902     while(r1) {
4903
4904       r2 = setFirstItem(pb->tregisters);
4905
4906       while(r2 && (r1->type != REG_STK)) {
4907
4908         if(r2->rIdx == r1->rIdx) {
4909           newreg = pic14_findFreeReg(REG_GPR);
4910
4911
4912           if(!newreg) {
4913             DFPRINTF((stderr,"Bummer, no more registers.\n"));
4914             exit(1);
4915           }
4916
4917           DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
4918                   r1->rIdx, newreg->rIdx));
4919           r2->rIdx = newreg->rIdx;
4920           //if(r2->name) free(r2->name);
4921           if(newreg->name)
4922             r2->name = Safe_strdup(newreg->name);
4923           else
4924             r2->name = NULL;
4925           newreg->isFree = 0;
4926           newreg->wasUsed = 1;
4927         }
4928         r2 = setNextItem(pb->tregisters);
4929       }
4930
4931       r1 = setNextItem(registersInCallPath);
4932     }
4933
4934     /* Collisions have been resolved. Now free the registers in the call path */
4935     r1 = setFirstItem(registersInCallPath);
4936     while(r1) {
4937       if(r1->type != REG_STK) {
4938         newreg = pic14_regWithIdx(r1->rIdx);
4939         newreg->isFree = 1;
4940       }
4941       r1 = setNextItem(registersInCallPath);
4942     }
4943
4944   }// else
4945   //    MarkUsedRegisters(pb->registers);
4946
4947   registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
4948 #ifdef PCODE_DEBUG
4949   if(registers) 
4950     DFPRINTF((stderr,"returning regs\n"));
4951   else
4952     DFPRINTF((stderr,"not returning regs\n"));
4953
4954   DFPRINTF((stderr,"pBlock after register optim.\n"));
4955   pBlockStats(stderr,pb);  // debug
4956 #endif
4957
4958   return registers;
4959 }
4960
4961 /*-----------------------------------------------------------------*/
4962 /* printCallTree - writes the call tree to a file                  */
4963 /*                                                                 */
4964 /*-----------------------------------------------------------------*/
4965 void pct2(FILE *of,pBlock *pb,int indent)
4966 {
4967   pCode *pc,*pcn;
4968   int i;
4969   //  set *registersInCallPath = NULL;
4970
4971   if(!of)
4972     return;
4973
4974   if(indent > 10)
4975     return; //recursion ?
4976
4977   pc = setFirstItem(pb->function_entries);
4978
4979   if(!pc)
4980     return;
4981
4982   pb->visited = 0;
4983
4984   for(i=0;i<indent;i++)   // Indentation
4985     fputc(' ',of);
4986
4987   if(pc->type == PC_FUNCTION)
4988     fprintf(of,"%s\n",PCF(pc)->fname);
4989   else
4990     return;  // ???
4991
4992
4993   pc = setFirstItem(pb->function_calls);
4994   for( ; pc; pc = setNextItem(pb->function_calls)) {
4995
4996     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4997       char *dest = get_op_from_instruction(PCI(pc));
4998
4999       pcn = findFunction(dest);
5000       if(pcn) 
5001         pct2(of,pcn->pb,indent+1);
5002     } else
5003       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5004
5005   }
5006
5007
5008 }
5009
5010
5011 /*-----------------------------------------------------------------*/
5012 /* printCallTree - writes the call tree to a file                  */
5013 /*                                                                 */
5014 /*-----------------------------------------------------------------*/
5015
5016 void printCallTree(FILE *of)
5017 {
5018   pBranch *pbr;
5019   pBlock  *pb;
5020   pCode   *pc;
5021
5022   if(!the_pFile)
5023     return;
5024
5025   if(!of)
5026     of = stderr;
5027
5028   fprintf(of, "\npBlock statistics\n");
5029   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
5030     pBlockStats(of,pb);
5031
5032
5033
5034   fprintf(of,"Call Tree\n");
5035   pbr = the_pFile->functions;
5036   while(pbr) {
5037     if(pbr->pc) {
5038       pc = pbr->pc;
5039       if(!ispCodeFunction(pc))
5040         fprintf(of,"bug in call tree");
5041
5042
5043       fprintf(of,"Function: %s\n", PCF(pc)->fname);
5044
5045       while(pc->next && !ispCodeFunction(pc->next)) {
5046         pc = pc->next;
5047         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5048           fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5049       }
5050     }
5051
5052     pbr = pbr->next;
5053   }
5054
5055
5056   fprintf(of,"\n**************\n\na better call tree\n");
5057   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5058     if(pb->visited)
5059       pct2(of,pb,0);
5060   }
5061
5062   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5063     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5064   }
5065 }
5066
5067
5068
5069 /*-----------------------------------------------------------------*/
5070 /*                                                                 */
5071 /*-----------------------------------------------------------------*/
5072
5073 void InlineFunction(pBlock *pb)
5074 {
5075   pCode *pc;
5076   pCode *pc_call;
5077
5078   if(!pb)
5079     return;
5080
5081   pc = setFirstItem(pb->function_calls);
5082
5083   for( ; pc; pc = setNextItem(pb->function_calls)) {
5084
5085     if(isCALL(pc)) {
5086       pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5087       pCode *pct;
5088       pCode *pce;
5089
5090       pBranch *pbr;
5091
5092       if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5093         
5094         //fprintf(stderr,"Cool can inline:\n");
5095         //pcn->print(stderr,pcn);
5096
5097         //fprintf(stderr,"recursive call Inline\n");
5098         InlineFunction(pcn->pb);
5099         //fprintf(stderr,"return from recursive call Inline\n");
5100
5101         /*
5102           At this point, *pc points to a CALL mnemonic, and
5103           *pcn points to the function that is being called.
5104
5105           To in-line this call, we need to remove the CALL
5106           and RETURN(s), and link the function pCode in with
5107           the CALLee pCode.
5108
5109         */
5110
5111
5112         /* Remove the CALL */
5113         pc_call = pc;
5114         pc = pc->prev;
5115
5116         /* remove callee pBlock from the pBlock linked list */
5117         removepBlock(pcn->pb);
5118
5119         pce = pcn;
5120         while(pce) {
5121           pce->pb = pb;
5122           pce = pce->next;
5123         }
5124
5125         /* Remove the Function pCode */
5126         pct = findNextInstruction(pcn->next);
5127
5128         /* Link the function with the callee */
5129         pc->next = pcn->next;
5130         pcn->next->prev = pc;
5131         
5132         /* Convert the function name into a label */
5133
5134         pbr = Safe_calloc(1,sizeof(pBranch));
5135         pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5136         pbr->next = NULL;
5137         PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5138         PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5139
5140         /* turn all of the return's except the last into goto's */
5141         /* check case for 2 instruction pBlocks */
5142         pce = findNextInstruction(pcn->next);
5143         while(pce) {
5144           pCode *pce_next = findNextInstruction(pce->next);
5145
5146           if(pce_next == NULL) {
5147             /* found the last return */
5148             pCode *pc_call_next =  findNextInstruction(pc_call->next);
5149
5150             //fprintf(stderr,"found last return\n");
5151             //pce->print(stderr,pce);
5152             pce->prev->next = pc_call->next;
5153             pc_call->next->prev = pce->prev;
5154             PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5155                                                       PCI(pce)->label);
5156           }
5157
5158           pce = pce_next;
5159         }
5160
5161
5162       }
5163     } else
5164       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5165
5166   }
5167
5168 }
5169
5170 /*-----------------------------------------------------------------*/
5171 /*                                                                 */
5172 /*-----------------------------------------------------------------*/
5173
5174 void InlinepCode(void)
5175 {
5176
5177   pBlock  *pb;
5178   pCode   *pc;
5179
5180   if(!the_pFile)
5181     return;
5182
5183   if(!functionInlining)
5184     return;
5185
5186   /* Loop through all of the function definitions and count the
5187    * number of times each one is called */
5188   //fprintf(stderr,"inlining %d\n",__LINE__);
5189
5190   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5191
5192     pc = setFirstItem(pb->function_calls);
5193
5194     for( ; pc; pc = setNextItem(pb->function_calls)) {
5195
5196       if(isCALL(pc)) {
5197         pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5198         if(pcn && isPCF(pcn)) {
5199           PCF(pcn)->ncalled++;
5200         }
5201       } else
5202         fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5203
5204     }
5205   }
5206
5207   //fprintf(stderr,"inlining %d\n",__LINE__);
5208
5209   /* Now, Loop through the function definitions again, but this
5210    * time inline those functions that have only been called once. */
5211   
5212   InlineFunction(the_pFile->pbHead);
5213   //fprintf(stderr,"inlining %d\n",__LINE__);
5214
5215   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5216     unBuildFlow(pb);
5217
5218 }