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