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