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