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