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