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