Added CLRWDT instruction again (this time 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 = 0;                /* Set true to inundate .asm file */
79
80 static int GpCodeSequenceNumber = 1;
81 int GpcFlowSeq = 1;
82
83 extern void RemoveUnusedRegisters(void);
84 extern void RegsUnMapLiveRanges(void);
85 extern void BuildFlowTree(pBlock *pb);
86 extern void pCodeRegOptimizeRegUsage(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))
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   return pcop;
2110 }
2111
2112 /*-----------------------------------------------------------------*
2113  * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2114  *
2115  * If rIdx >=0 then a specific register from the set of registers
2116  * will be selected. If rIdx <0, then a new register will be searched
2117  * for.
2118  *-----------------------------------------------------------------*/
2119
2120 pCodeOp *newpCodeOpReg(int rIdx)
2121 {
2122   pCodeOp *pcop;
2123
2124   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2125
2126   pcop->name = NULL;
2127
2128   if(rIdx >= 0) {
2129     PCOR(pcop)->rIdx = rIdx;
2130     PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2131   } else {
2132     PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2133
2134     if(PCOR(pcop)->r)
2135       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2136     //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2137   }
2138
2139   pcop->type = PCOR(pcop)->r->pc_type;
2140
2141   return pcop;
2142 }
2143
2144 pCodeOp *newpCodeOpRegFromStr(char *name)
2145 {
2146   pCodeOp *pcop;
2147
2148   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2149   PCOR(pcop)->r = allocRegByName(name, 1);
2150   PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2151   pcop->type = PCOR(pcop)->r->pc_type;
2152   pcop->name = PCOR(pcop)->r->name;
2153
2154   return pcop;
2155 }
2156
2157 /*-----------------------------------------------------------------*/
2158 /*-----------------------------------------------------------------*/
2159
2160 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2161 {
2162   pCodeOp *pcop;
2163
2164   switch(type) {
2165   case PO_BIT:
2166   case PO_GPR_BIT:
2167     pcop = newpCodeOpBit(name, -1,0);
2168     break;
2169
2170   case PO_LITERAL:
2171     pcop = newpCodeOpLit(-1);
2172     break;
2173
2174   case PO_LABEL:
2175     pcop = newpCodeOpLabel(NULL,-1);
2176     break;
2177   case PO_GPR_TEMP:
2178     pcop = newpCodeOpReg(-1);
2179     break;
2180
2181   default:
2182     pcop = Safe_calloc(1,sizeof(pCodeOp) );
2183     pcop->type = type;
2184     if(name)
2185       pcop->name = Safe_strdup(name);   
2186     else
2187       pcop->name = NULL;
2188   }
2189
2190   return pcop;
2191 }
2192
2193 /*-----------------------------------------------------------------*/
2194 /*-----------------------------------------------------------------*/
2195 void pCodeConstString(char *name, char *value)
2196 {
2197   pBlock *pb;
2198
2199   //  fprintf(stderr, " %s  %s  %s\n",__FUNCTION__,name,value);
2200
2201   if(!name || !value)
2202     return;
2203
2204   pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2205
2206   addpBlock(pb);
2207
2208   sprintf(buffer,"; %s = %s",name,value);
2209   
2210   addpCode2pBlock(pb,newpCodeCharP(buffer));
2211   addpCode2pBlock(pb,newpCodeLabel(name,-1));
2212
2213   do {
2214     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2215   }while (*value++);
2216
2217
2218 }
2219
2220 /*-----------------------------------------------------------------*/
2221 /*-----------------------------------------------------------------*/
2222 void pCodeReadCodeTable(void)
2223 {
2224   pBlock *pb;
2225
2226   fprintf(stderr, " %s\n",__FUNCTION__);
2227
2228   pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2229
2230   addpBlock(pb);
2231
2232   addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2233   addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2234   addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2235   addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2236
2237   addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2238   addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2239   addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2240   addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2241
2242
2243 }
2244
2245 /*-----------------------------------------------------------------*/
2246 /* addpCode2pBlock - place the pCode into the pBlock linked list   */
2247 /*-----------------------------------------------------------------*/
2248 void addpCode2pBlock(pBlock *pb, pCode *pc)
2249 {
2250
2251   if(!pc)
2252     return;
2253
2254   if(!pb->pcHead) {
2255     /* If this is the first pcode to be added to a block that
2256      * was initialized with a NULL pcode, then go ahead and
2257      * make this pcode the head and tail */
2258     pb->pcHead  = pb->pcTail = pc;
2259   } else {
2260     //    if(pb->pcTail)
2261     pb->pcTail->next = pc;
2262
2263     pc->prev = pb->pcTail;
2264     pc->pb = pb;
2265
2266     pb->pcTail = pc;
2267   }
2268 }
2269
2270 /*-----------------------------------------------------------------*/
2271 /* addpBlock - place a pBlock into the pFile                       */
2272 /*-----------------------------------------------------------------*/
2273 void addpBlock(pBlock *pb)
2274 {
2275   // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2276
2277   if(!the_pFile) {
2278     /* First time called, we'll pass through here. */
2279     //_ALLOC(the_pFile,sizeof(pFile));
2280     the_pFile = Safe_calloc(1,sizeof(pFile));
2281     the_pFile->pbHead = the_pFile->pbTail = pb;
2282     the_pFile->functions = NULL;
2283     return;
2284   }
2285
2286   the_pFile->pbTail->next = pb;
2287   pb->prev = the_pFile->pbTail;
2288   pb->next = NULL;
2289   the_pFile->pbTail = pb;
2290 }
2291
2292 /*-----------------------------------------------------------------*/
2293 /* removepBlock - remove a pBlock from the pFile                   */
2294 /*-----------------------------------------------------------------*/
2295 void removepBlock(pBlock *pb)
2296 {
2297   pBlock *pbs;
2298
2299   if(!the_pFile)
2300     return;
2301
2302
2303   //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2304
2305   for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2306     if(pbs == pb) {
2307
2308       if(pbs == the_pFile->pbHead)
2309         the_pFile->pbHead = pbs->next;
2310
2311       if (pbs == the_pFile->pbTail) 
2312         the_pFile->pbTail = pbs->prev;
2313
2314       if(pbs->next)
2315         pbs->next->prev = pbs->prev;
2316
2317       if(pbs->prev)
2318         pbs->prev->next = pbs->next;
2319
2320       return;
2321
2322     }
2323   }
2324
2325   fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2326
2327 }
2328
2329 /*-----------------------------------------------------------------*/
2330 /* printpCode - write the contents of a pCode to a file            */
2331 /*-----------------------------------------------------------------*/
2332 void printpCode(FILE *of, pCode *pc)
2333 {
2334
2335   if(!pc || !of)
2336     return;
2337
2338   if(pc->print) {
2339     pc->print(of,pc);
2340     return;
2341   }
2342
2343   fprintf(of,"warning - unable to print pCode\n");
2344 }
2345
2346 /*-----------------------------------------------------------------*/
2347 /* printpBlock - write the contents of a pBlock to a file          */
2348 /*-----------------------------------------------------------------*/
2349 void printpBlock(FILE *of, pBlock *pb)
2350 {
2351   pCode *pc;
2352
2353   if(!pb)
2354     return;
2355
2356   if(!of)
2357     of = stderr;
2358
2359   for(pc = pb->pcHead; pc; pc = pc->next)
2360     printpCode(of,pc);
2361
2362 }
2363
2364 /*-----------------------------------------------------------------*/
2365 /*                                                                 */
2366 /*       pCode processing                                          */
2367 /*                                                                 */
2368 /*                                                                 */
2369 /*                                                                 */
2370 /*-----------------------------------------------------------------*/
2371
2372 void unlinkpCode(pCode *pc)
2373 {
2374
2375
2376   if(pc) {
2377 #ifdef PCODE_DEBUG
2378     fprintf(stderr,"Unlinking: ");
2379     printpCode(stderr, pc);
2380 #endif
2381     if(pc->prev) 
2382       pc->prev->next = pc->next;
2383     if(pc->next)
2384       pc->next->prev = pc->prev;
2385
2386     pc->prev = pc->next = NULL;
2387   }
2388 }
2389
2390 /*-----------------------------------------------------------------*/
2391 /*-----------------------------------------------------------------*/
2392
2393 static void genericDestruct(pCode *pc)
2394 {
2395
2396   unlinkpCode(pc);
2397
2398   if(isPCI(pc)) {
2399     /* For instructions, tell the register (if there's one used)
2400      * that it's no longer needed */
2401     regs *reg = getRegFromInstruction(pc);
2402     if(reg)
2403       deleteSetItem (&(reg->reglives.usedpCodes),pc);
2404   }
2405
2406   /* Instead of deleting the memory used by this pCode, mark
2407    * the object as bad so that if there's a pointer to this pCode
2408    * dangling around somewhere then (hopefully) when the type is
2409    * checked we'll catch it.
2410    */
2411
2412   pc->type = PC_BAD;
2413
2414   addpCode2pBlock(pb_dead_pcodes, pc);
2415
2416   //free(pc);
2417
2418 }
2419
2420
2421 /*-----------------------------------------------------------------*/
2422 /*-----------------------------------------------------------------*/
2423 void pBlockRegs(FILE *of, pBlock *pb)
2424 {
2425
2426   regs  *r;
2427
2428   r = setFirstItem(pb->tregisters);
2429   while (r) {
2430     r = setNextItem(pb->tregisters);
2431   }
2432 }
2433
2434
2435 /*-----------------------------------------------------------------*/
2436 /*-----------------------------------------------------------------*/
2437 char *get_op(pCodeOp *pcop,char *buffer, int size)
2438 {
2439   regs *r;
2440   static char b[50];
2441   char *s;
2442   int use_buffer = 1;    // copy the string to the passed buffer pointer
2443
2444   if(!buffer) {
2445     buffer = b;
2446     size = sizeof(b);
2447     use_buffer = 0;     // Don't bother copying the string to the buffer.
2448   } 
2449
2450   if(pcop) {
2451     switch(pcop->type) {
2452     case PO_INDF:
2453     case PO_FSR:
2454       if(use_buffer) {
2455         SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2456         return buffer;
2457       }
2458       return PCOR(pcop)->r->name;
2459       break;
2460     case PO_GPR_TEMP:
2461       r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2462
2463       if(use_buffer) {
2464         SAFE_snprintf(&buffer,&size,"%s",r->name);
2465         return buffer;
2466       }
2467
2468       return r->name;
2469
2470
2471     case PO_IMMEDIATE:
2472       s = buffer;
2473
2474       if(PCOI(pcop)->_const) {
2475
2476         if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2477           SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2478                         pcop->name,
2479                         PCOI(pcop)->index,
2480                         8 * PCOI(pcop)->offset );
2481         } else
2482           SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2483       } else {
2484       
2485         if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2486           SAFE_snprintf(&s,&size,"(%s + %d)",
2487                         pcop->name,
2488                         PCOI(pcop)->index );
2489         } else
2490           SAFE_snprintf(&s,&size,"%s",pcop->name);
2491       }
2492
2493       return buffer;
2494
2495     case PO_DIR:
2496       s = buffer;
2497       //size = sizeof(buffer);
2498       if( PCOR(pcop)->instance) {
2499         SAFE_snprintf(&s,&size,"(%s + %d)",
2500                       pcop->name,
2501                       PCOR(pcop)->instance );
2502         //fprintf(stderr,"PO_DIR %s\n",buffer);
2503       } else
2504         SAFE_snprintf(&s,&size,"%s",pcop->name);
2505       return buffer;
2506
2507     default:
2508       if  (pcop->name) {
2509         if(use_buffer) {
2510           SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2511           return buffer;
2512         }
2513         return pcop->name;
2514       }
2515
2516     }
2517   }
2518
2519   return "NO operand";
2520
2521 }
2522
2523 /*-----------------------------------------------------------------*/
2524 /*-----------------------------------------------------------------*/
2525 static char *get_op_from_instruction( pCodeInstruction *pcc)
2526 {
2527
2528   if(pcc )
2529     return get_op(pcc->pcop,NULL,0);
2530   
2531   return ("ERROR Null: "__FUNCTION__);
2532
2533 }
2534
2535 /*-----------------------------------------------------------------*/
2536 /*-----------------------------------------------------------------*/
2537 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2538 {
2539
2540   fprintf(of,"pcodeopprint- not implemented\n");
2541 }
2542
2543 /*-----------------------------------------------------------------*/
2544 /*-----------------------------------------------------------------*/
2545 char *pCode2str(char *str, int size, pCode *pc)
2546 {
2547   char *s = str;
2548
2549   switch(pc->type) {
2550
2551   case PC_OPCODE:
2552
2553     SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2554
2555     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2556
2557       if(PCI(pc)->isBitInst) {
2558         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2559           if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2560             SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
2561                           PCI(pc)->pcop->name ,
2562                           PCI(pc)->pcop->name );
2563           else
2564             SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)), 
2565                           (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2566         } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2567           SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2568         }else
2569           SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2570         //PCI(pc)->pcop->t.bit );
2571       } else {
2572
2573         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2574           if( PCI(pc)->num_ops == 2)
2575             SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2576           else
2577             SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2578
2579         }else {
2580           SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2581
2582           if( PCI(pc)->num_ops == 2)
2583             SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2584         }
2585       }
2586
2587     }
2588     break;
2589
2590   case PC_COMMENT:
2591     /* assuming that comment ends with a \n */
2592     SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2593     break;
2594
2595   case PC_INLINE:
2596     /* assuming that inline code ends with a \n */
2597     SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2598     break;
2599
2600   case PC_LABEL:
2601     SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2602     break;
2603   case PC_FUNCTION:
2604     SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2605     break;
2606   case PC_WILD:
2607     SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2608     break;
2609   case PC_FLOW:
2610     SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2611     break;
2612   case PC_CSOURCE:
2613     SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2614     break;
2615
2616   case PC_BAD:
2617     SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2618   }
2619
2620   return str;
2621
2622 }
2623
2624 /*-----------------------------------------------------------------*/
2625 /* genericPrint - the contents of a pCode to a file                */
2626 /*-----------------------------------------------------------------*/
2627 static void genericPrint(FILE *of, pCode *pc)
2628 {
2629
2630   if(!pc || !of)
2631     return;
2632
2633   switch(pc->type) {
2634   case PC_COMMENT:
2635     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2636     break;
2637
2638   case PC_INLINE:
2639     fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2640      break;
2641
2642   case PC_OPCODE:
2643     // If the opcode has a label, print that first
2644     {
2645       pBranch *pbl = PCI(pc)->label;
2646       while(pbl && pbl->pc) {
2647         if(pbl->pc->type == PC_LABEL)
2648           pCodePrintLabel(of, pbl->pc);
2649         pbl = pbl->next;
2650       }
2651     }
2652
2653     if(PCI(pc)->cline) 
2654       genericPrint(of,PCODE(PCI(pc)->cline));
2655
2656     {
2657       char str[256];
2658       
2659       pCode2str(str, 256, pc);
2660
2661       fprintf(of,"%s",str);
2662
2663       /* Debug */
2664       if(debug_verbose) {
2665         fprintf(of, "\t;key=%03x",pc->seq);
2666         if(PCI(pc)->pcflow)
2667           fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2668       }
2669     }
2670 #if 0
2671     {
2672       pBranch *dpb = pc->to;   // debug
2673       while(dpb) {
2674         switch ( dpb->pc->type) {
2675         case PC_OPCODE:
2676           fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2677           break;
2678         case PC_LABEL:
2679           fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2680           break;
2681         case PC_FUNCTION:
2682           fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2683           break;
2684         case PC_FLOW:
2685           fprintf(of, "\t;flow");
2686           break;
2687         case PC_COMMENT:
2688         case PC_WILD:
2689           break;
2690         }
2691         dpb = dpb->next;
2692       }
2693     }
2694 #endif
2695     fprintf(of,"\n");
2696     break;
2697
2698   case PC_WILD:
2699     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2700     if(PCW(pc)->pci.label)
2701       pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2702
2703     if(PCW(pc)->operand) {
2704       fprintf(of,";\toperand  ");
2705       pCodeOpPrint(of,PCW(pc)->operand );
2706     }
2707     break;
2708
2709   case PC_FLOW:
2710     if(debug_verbose)
2711       fprintf(of,";<>Start of new flow, seq=%d\n",pc->seq);
2712     break;
2713
2714   case PC_CSOURCE:
2715     fprintf(of,";#CSRC\t%s %d\n;  %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2716     break;
2717   case PC_LABEL:
2718   default:
2719     fprintf(of,"unknown pCode type %d\n",pc->type);
2720   }
2721
2722 }
2723
2724 /*-----------------------------------------------------------------*/
2725 /* pCodePrintFunction - prints function begin/end                  */
2726 /*-----------------------------------------------------------------*/
2727
2728 static void pCodePrintFunction(FILE *of, pCode *pc)
2729 {
2730
2731   if(!pc || !of)
2732     return;
2733
2734   if( ((pCodeFunction *)pc)->modname) 
2735     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2736
2737   if(PCF(pc)->fname) {
2738     pBranch *exits = PCF(pc)->to;
2739     int i=0;
2740     fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2741     while(exits) {
2742       i++;
2743       exits = exits->next;
2744     }
2745     //if(i) i--;
2746     fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2747     
2748   }else {
2749     if((PCF(pc)->from && 
2750         PCF(pc)->from->pc->type == PC_FUNCTION &&
2751         PCF(PCF(pc)->from->pc)->fname) )
2752       fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2753     else
2754       fprintf(of,"; exit point [can't find entry point]\n");
2755   }
2756 }
2757 /*-----------------------------------------------------------------*/
2758 /* pCodePrintLabel - prints label                                  */
2759 /*-----------------------------------------------------------------*/
2760
2761 static void pCodePrintLabel(FILE *of, pCode *pc)
2762 {
2763
2764   if(!pc || !of)
2765     return;
2766
2767   if(PCL(pc)->label) 
2768     fprintf(of,"%s\n",PCL(pc)->label);
2769   else if (PCL(pc)->key >=0) 
2770     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2771   else
2772     fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2773
2774 }
2775 /*-----------------------------------------------------------------*/
2776 /* unlinkpCodeFromBranch - Search for a label in a pBranch and     */
2777 /*                         remove it if it is found.               */
2778 /*-----------------------------------------------------------------*/
2779 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2780 {
2781   pBranch *b, *bprev;
2782
2783
2784   bprev = NULL;
2785
2786   if(pcl->type == PC_OPCODE)
2787     b = PCI(pcl)->label;
2788   else {
2789     fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2790     exit(1);
2791
2792   }
2793
2794   //fprintf (stderr, "%s \n",__FUNCTION__);
2795   //pcl->print(stderr,pcl);
2796   //pc->print(stderr,pc);
2797   while(b) {
2798     if(b->pc == pc) {
2799       //fprintf (stderr, "found label\n");
2800
2801       /* Found a label */
2802       if(bprev) {
2803         bprev->next = b->next;  /* Not first pCode in chain */
2804         free(b);
2805       } else {
2806         pc->destruct(pc);
2807         PCI(pcl)->label = b->next;   /* First pCode in chain */
2808         free(b);
2809       }
2810       return;  /* A label can't occur more than once */
2811     }
2812     bprev = b;
2813     b = b->next;
2814   }
2815
2816 }
2817
2818 /*-----------------------------------------------------------------*/
2819 /*-----------------------------------------------------------------*/
2820 pBranch * pBranchAppend(pBranch *h, pBranch *n)
2821 {
2822   pBranch *b;
2823
2824   if(!h)
2825     return n;
2826
2827   if(h == n)
2828     return n;
2829
2830   b = h;
2831   while(b->next)
2832     b = b->next;
2833
2834   b->next = n;
2835
2836   return h;
2837   
2838 }  
2839 /*-----------------------------------------------------------------*/
2840 /* pBranchLink - given two pcodes, this function will link them    */
2841 /*               together through their pBranches                  */
2842 /*-----------------------------------------------------------------*/
2843 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2844 {
2845   pBranch *b;
2846
2847   // Declare a new branch object for the 'from' pCode.
2848
2849   //_ALLOC(b,sizeof(pBranch));
2850   b = Safe_calloc(1,sizeof(pBranch));
2851   b->pc = PCODE(t);             // The link to the 'to' pCode.
2852   b->next = NULL;
2853
2854   f->to = pBranchAppend(f->to,b);
2855
2856   // Now do the same for the 'to' pCode.
2857
2858   //_ALLOC(b,sizeof(pBranch));
2859   b = Safe_calloc(1,sizeof(pBranch));
2860   b->pc = PCODE(f);
2861   b->next = NULL;
2862
2863   t->from = pBranchAppend(t->from,b);
2864   
2865 }
2866
2867 #if 0
2868 /*-----------------------------------------------------------------*/
2869 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2870 /*               a pCode                                           */
2871 /*-----------------------------------------------------------------*/
2872 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2873 {
2874   while(pb) {
2875
2876     if(pb->pc == pc)
2877       return pb;
2878
2879     pb = pb->next;
2880   }
2881
2882   return NULL;
2883 }
2884
2885 /*-----------------------------------------------------------------*/
2886 /* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
2887 /*-----------------------------------------------------------------*/
2888 static void pCodeUnlink(pCode *pc)
2889 {
2890   pBranch *pb1,*pb2;
2891   pCode *pc1;
2892
2893   if(!pc->prev || !pc->next) {
2894     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2895     exit(1);
2896   }
2897
2898   /* first remove the pCode from the chain */
2899   pc->prev->next = pc->next;
2900   pc->next->prev = pc->prev;
2901
2902   /* Now for the hard part... */
2903
2904   /* Remove the branches */
2905
2906   pb1 = pc->from;
2907   while(pb1) {
2908     pc1 = pb1->pc;    /* Get the pCode that branches to the
2909                        * one we're unlinking */
2910
2911     /* search for the link back to this pCode (the one we're
2912      * unlinking) */
2913     if(pb2 = pBranchFind(pc1->to,pc)) {
2914       pb2->pc = pc->to->pc;  // make the replacement
2915
2916       /* if the pCode we're unlinking contains multiple 'to'
2917        * branches (e.g. this a skip instruction) then we need
2918        * to copy these extra branches to the chain. */
2919       if(pc->to->next)
2920         pBranchAppend(pb2, pc->to->next);
2921     }
2922     
2923     pb1 = pb1->next;
2924   }
2925
2926
2927 }
2928 #endif
2929 /*-----------------------------------------------------------------*/
2930 /*-----------------------------------------------------------------*/
2931 #if 0
2932 static void genericAnalyze(pCode *pc)
2933 {
2934   switch(pc->type) {
2935   case PC_WILD:
2936   case PC_COMMENT:
2937     return;
2938   case PC_LABEL:
2939   case PC_FUNCTION:
2940   case PC_OPCODE:
2941     {
2942       // Go through the pCodes that are in pCode chain and link
2943       // them together through the pBranches. Note, the pCodes
2944       // are linked together as a contiguous stream like the 
2945       // assembly source code lines. The linking here mimics this
2946       // except that comments are not linked in.
2947       // 
2948       pCode *npc = pc->next;
2949       while(npc) {
2950         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2951           pBranchLink(pc,npc);
2952           return;
2953         } else
2954           npc = npc->next;
2955       }
2956       /* reached the end of the pcode chain without finding
2957        * an instruction we could link to. */
2958     }
2959     break;
2960   case PC_FLOW:
2961     fprintf(stderr,"analyze PC_FLOW\n");
2962
2963     return;
2964   case PC_BAD:
2965     fprintf(stderr,,";A bad pCode is being used\n");
2966
2967   }
2968 }
2969 #endif
2970
2971 /*-----------------------------------------------------------------*/
2972 /*-----------------------------------------------------------------*/
2973 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2974 {
2975   pBranch *pbr;
2976
2977   if(pc->type == PC_LABEL) {
2978     if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
2979       return TRUE;
2980   }
2981   if(pc->type == PC_OPCODE) {
2982     pbr = PCI(pc)->label;
2983     while(pbr) {
2984       if(pbr->pc->type == PC_LABEL) {
2985         if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
2986           return TRUE;
2987       }
2988       pbr = pbr->next;
2989     }
2990   }
2991
2992   return FALSE;
2993 }
2994
2995 /*-----------------------------------------------------------------*/
2996 /*-----------------------------------------------------------------*/
2997 int checkLabel(pCode *pc)
2998 {
2999   pBranch *pbr;
3000
3001   if(pc && isPCI(pc)) {
3002     pbr = PCI(pc)->label;
3003     while(pbr) {
3004       if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3005         return TRUE;
3006
3007       pbr = pbr->next;
3008     }
3009   }
3010
3011   return FALSE;
3012 }
3013
3014 /*-----------------------------------------------------------------*/
3015 /* findLabelinpBlock - Search the pCode for a particular label     */
3016 /*-----------------------------------------------------------------*/
3017 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3018 {
3019   pCode  *pc;
3020
3021   if(!pb)
3022     return NULL;
3023
3024   for(pc = pb->pcHead; pc; pc = pc->next) 
3025     if(compareLabel(pc,pcop_label))
3026       return pc;
3027     
3028   return NULL;
3029 }
3030
3031 /*-----------------------------------------------------------------*/
3032 /* findLabel - Search the pCode for a particular label             */
3033 /*-----------------------------------------------------------------*/
3034 pCode * findLabel(pCodeOpLabel *pcop_label)
3035 {
3036   pBlock *pb;
3037   pCode  *pc;
3038
3039   if(!the_pFile)
3040     return NULL;
3041
3042   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3043     if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3044       return pc;
3045   }
3046
3047   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3048   return NULL;
3049 }
3050
3051 /*-----------------------------------------------------------------*/
3052 /* findNextpCode - given a pCode, find the next of type 'pct'      */
3053 /*                 in the linked list                              */
3054 /*-----------------------------------------------------------------*/
3055 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3056 {
3057
3058   while(pc) {
3059     if(pc->type == pct)
3060       return pc;
3061
3062     pc = pc->next;
3063   }
3064
3065   return NULL;
3066 }
3067
3068 /*-----------------------------------------------------------------*/
3069 /* findPrevpCode - given a pCode, find the previous of type 'pct'  */
3070 /*                 in the linked list                              */
3071 /*-----------------------------------------------------------------*/
3072 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3073 {
3074
3075   while(pc) {
3076     if(pc->type == pct)
3077       return pc;
3078
3079     pc = pc->prev;
3080   }
3081
3082   return NULL;
3083 }
3084 /*-----------------------------------------------------------------*/
3085 /* findNextInstruction - given a pCode, find the next instruction  */
3086 /*                       in the linked list                        */
3087 /*-----------------------------------------------------------------*/
3088 pCode * findNextInstruction(pCode *pci)
3089 {
3090   pCode *pc = pci;
3091
3092   while(pc) {
3093     if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3094       return pc;
3095
3096 #ifdef PCODE_DEBUG
3097     fprintf(stderr,"findNextInstruction:  ");
3098     printpCode(stderr, pc);
3099 #endif
3100     pc = pc->next;
3101   }
3102
3103   //fprintf(stderr,"Couldn't find instruction\n");
3104   return NULL;
3105 }
3106
3107 /*-----------------------------------------------------------------*/
3108 /* findNextInstruction - given a pCode, find the next instruction  */
3109 /*                       in the linked list                        */
3110 /*-----------------------------------------------------------------*/
3111 pCode * findPrevInstruction(pCode *pci)
3112 {
3113   return findPrevpCode(pci, PC_OPCODE);
3114 }
3115
3116 /*-----------------------------------------------------------------*/
3117 /* findFunctionEnd - given a pCode find the end of the function    */
3118 /*                   that contains it                              */
3119 /*-----------------------------------------------------------------*/
3120 pCode * findFunctionEnd(pCode *pc)
3121 {
3122
3123   while(pc) {
3124     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
3125       return pc;
3126
3127     pc = pc->next;
3128   }
3129
3130   fprintf(stderr,"Couldn't find function end\n");
3131   return NULL;
3132 }
3133
3134 #if 0
3135 /*-----------------------------------------------------------------*/
3136 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
3137 /*                instruction with which it is associated.         */
3138 /*-----------------------------------------------------------------*/
3139 static void AnalyzeLabel(pCode *pc)
3140 {
3141
3142   pCodeUnlink(pc);
3143
3144 }
3145 #endif
3146
3147 #if 0
3148 static void AnalyzeGOTO(pCode *pc)
3149 {
3150
3151   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3152
3153 }
3154
3155 static void AnalyzeSKIP(pCode *pc)
3156 {
3157
3158   pBranchLink(pc,findNextInstruction(pc->next));
3159   pBranchLink(pc,findNextInstruction(pc->next->next));
3160
3161 }
3162
3163 static void AnalyzeRETURN(pCode *pc)
3164 {
3165
3166   //  branch_link(pc,findFunctionEnd(pc->next));
3167
3168 }
3169
3170 #endif
3171
3172 /*-----------------------------------------------------------------*/
3173 /*-----------------------------------------------------------------*/
3174 regs * getRegFromInstruction(pCode *pc)
3175 {
3176
3177   if(!pc                   || 
3178      !isPCI(pc)            ||
3179      !PCI(pc)->pcop        ||
3180      PCI(pc)->num_ops == 0 )
3181     return NULL;
3182
3183   switch(PCI(pc)->pcop->type) {
3184   case PO_INDF:
3185   case PO_FSR:
3186     return PCOR(PCI(pc)->pcop)->r;
3187
3188     //    return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3189
3190   case PO_BIT:
3191   case PO_GPR_TEMP:
3192     //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3193     return PCOR(PCI(pc)->pcop)->r;
3194
3195   case PO_IMMEDIATE:
3196     if(PCOI(PCI(pc)->pcop)->r)
3197       return (PCOI(PCI(pc)->pcop)->r);
3198
3199     //fprintf(stderr, "getRegFromInstruction - immediate\n");
3200     return dirregWithName(PCI(pc)->pcop->name);
3201     //return NULL; // PCOR(PCI(pc)->pcop)->r;
3202
3203   case PO_GPR_BIT:
3204     return PCOR(PCI(pc)->pcop)->r;
3205
3206   case PO_DIR:
3207     //fprintf(stderr, "getRegFromInstruction - dir\n");
3208     return PCOR(PCI(pc)->pcop)->r;
3209   case PO_LITERAL:
3210     //fprintf(stderr, "getRegFromInstruction - literal\n");
3211     break;
3212
3213   default:
3214     //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3215     //genericPrint(stderr, pc);
3216     break;
3217   }
3218
3219   return NULL;
3220
3221 }
3222
3223 /*-----------------------------------------------------------------*/
3224 /*-----------------------------------------------------------------*/
3225
3226 void AnalyzepBlock(pBlock *pb)
3227 {
3228   pCode *pc;
3229
3230   if(!pb)
3231     return;
3232
3233   /* Find all of the registers used in this pBlock 
3234    * by looking at each instruction and examining it's
3235    * operands
3236    */
3237   for(pc = pb->pcHead; pc; pc = pc->next) {
3238
3239     /* Is this an instruction with operands? */
3240     if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3241
3242       if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3243
3244         /* Loop through all of the registers declared so far in
3245            this block and see if we find this one there */
3246
3247         regs *r = setFirstItem(pb->tregisters);
3248
3249         while(r) {
3250           if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3251             PCOR(PCI(pc)->pcop)->r = r;
3252             break;
3253           }
3254           r = setNextItem(pb->tregisters);
3255         }
3256
3257         if(!r) {
3258           /* register wasn't found */
3259           //r = Safe_calloc(1, sizeof(regs));
3260           //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3261           //addSet(&pb->tregisters, r);
3262           addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3263           //PCOR(PCI(pc)->pcop)->r = r;
3264           //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3265         }/* else 
3266           fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3267          */
3268       }
3269       if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3270         if(PCOR(PCI(pc)->pcop)->r) {
3271           pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3272           DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3273         } else {
3274           if(PCI(pc)->pcop->name)
3275             fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3276           else
3277             fprintf(stderr,"ERROR: NULL register\n");
3278         }
3279       }
3280     }
3281
3282
3283   }
3284 }
3285
3286 /*-----------------------------------------------------------------*/
3287 /* */
3288 /*-----------------------------------------------------------------*/
3289 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3290
3291 void InsertpFlow(pCode *pc, pCode **pflow)
3292 {
3293   if(*pflow)
3294     PCFL(*pflow)->end = pc;
3295
3296   if(!pc || !pc->next)
3297     return;
3298
3299   *pflow = newpCodeFlow();
3300   pCodeInsertAfter(pc, *pflow);
3301 }
3302
3303 /*-----------------------------------------------------------------*/
3304 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
3305 /*                         the flow blocks.                        */
3306 /*
3307  * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3308  * point the instruction flow changes. 
3309  */
3310 /*-----------------------------------------------------------------*/
3311 void BuildFlow(pBlock *pb)
3312 {
3313   pCode *pc;
3314   pCode *last_pci=NULL;
3315   pCode *pflow=NULL;
3316   int seq = 0;
3317
3318   if(!pb)
3319     return;
3320
3321   //fprintf (stderr,"build flow start seq %d  ",GpcFlowSeq);
3322   /* Insert a pCodeFlow object at the beginning of a pBlock */
3323
3324   InsertpFlow(pb->pcHead, &pflow);
3325
3326   //pflow = newpCodeFlow();    /* Create a new Flow object */
3327   //pflow->next = pb->pcHead;  /* Make the current head the next object */
3328   //pb->pcHead->prev = pflow;  /* let the current head point back to the flow object */
3329   //pb->pcHead = pflow;        /* Make the Flow object the head */
3330   //pflow->pb = pb;
3331
3332   for( pc = findNextInstruction(pb->pcHead);
3333        pc != NULL;
3334        pc=findNextInstruction(pc)) { 
3335
3336     pc->seq = seq++;
3337     PCI(pc)->pcflow = PCFL(pflow);
3338
3339     //fprintf(stderr," build: ");
3340     //pflow->print(stderr,pflow);
3341
3342     if( PCI(pc)->isSkip) {
3343
3344       /* The two instructions immediately following this one 
3345        * mark the beginning of a new flow segment */
3346
3347       while(pc && PCI(pc)->isSkip) {
3348
3349         PCI(pc)->pcflow = PCFL(pflow);
3350         pc->seq = seq-1;
3351         seq = 1;
3352
3353         InsertpFlow(pc, &pflow);
3354         pc=findNextInstruction(pc->next);
3355       }
3356
3357       seq = 0;
3358
3359       if(!pc)
3360         break;
3361
3362       PCI(pc)->pcflow = PCFL(pflow);
3363       pc->seq = 0;
3364       InsertpFlow(pc, &pflow);
3365
3366     } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next)))  {
3367
3368       InsertpFlow(pc, &pflow);
3369       seq = 0;
3370
3371     } else if (checkLabel(pc)) { //(PCI_HAS_LABEL(pc)) {
3372
3373       /* This instruction marks the beginning of a
3374        * new flow segment */
3375
3376       pc->seq = 0;
3377       seq = 1; 
3378       InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3379
3380       PCI(pc)->pcflow = PCFL(pflow);
3381       
3382     }
3383     last_pci = pc;
3384     pc = pc->next;
3385   }
3386
3387   //fprintf (stderr,",end seq %d",GpcFlowSeq);
3388   if(pflow)
3389     PCFL(pflow)->end = pb->pcTail;
3390 }
3391
3392 /*-------------------------------------------------------------------*/
3393 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
3394 /*                           the flow blocks.                        */
3395 /*
3396  * unBuildFlow removes pCodeFlow objects from a pCode chain
3397  */
3398 /*-----------------------------------------------------------------*/
3399 void unBuildFlow(pBlock *pb)
3400 {
3401   pCode *pc,*pcnext;
3402
3403   if(!pb)
3404     return;
3405
3406   pc = pb->pcHead;
3407
3408   while(pc) {
3409     pcnext = pc->next;
3410
3411     if(isPCI(pc)) {
3412
3413       pc->seq = 0;
3414       if(PCI(pc)->pcflow) {
3415         //free(PCI(pc)->pcflow);
3416         PCI(pc)->pcflow = NULL;
3417       }
3418
3419     } else if(isPCFL(pc) )
3420       pc->destruct(pc);
3421
3422     pc = pcnext;
3423   }
3424
3425
3426 }
3427
3428 /*-----------------------------------------------------------------*/
3429 /*-----------------------------------------------------------------*/
3430 void dumpCond(int cond)
3431 {
3432
3433   static char *pcc_str[] = {
3434     //"PCC_NONE",
3435     "PCC_REGISTER",
3436     "PCC_C",
3437     "PCC_Z",
3438     "PCC_DC",
3439     "PCC_W",
3440     "PCC_EXAMINE_PCOP",
3441     "PCC_REG_BANK0",
3442     "PCC_REG_BANK1",
3443     "PCC_REG_BANK2",
3444     "PCC_REG_BANK3"
3445   };
3446
3447   int ncond = sizeof(pcc_str) / sizeof(char *);
3448   int i,j;
3449
3450   fprintf(stderr, "0x%04X\n",cond);
3451
3452   for(i=0,j=1; i<ncond; i++, j<<=1)
3453     if(cond & j)
3454       fprintf(stderr, "  %s\n",pcc_str[i]);
3455
3456 }
3457
3458 /*-----------------------------------------------------------------*/
3459 /*-----------------------------------------------------------------*/
3460 void FlowStats(pCodeFlow *pcflow)
3461 {
3462
3463   pCode *pc;
3464
3465   if(!isPCFL(pcflow))
3466     return;
3467
3468   fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3469
3470   pc = findNextpCode(PCODE(pcflow), PC_OPCODE); 
3471
3472   if(!pc) {
3473     fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3474     return;
3475   }
3476
3477
3478   fprintf(stderr, "  FlowStats inCond: ");
3479   dumpCond(pcflow->inCond);
3480   fprintf(stderr, "  FlowStats outCond: ");
3481   dumpCond(pcflow->outCond);
3482
3483 }
3484
3485 /*-----------------------------------------------------------------*
3486  * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3487  *    if it affects the banking bits. 
3488  * 
3489  * return: -1 == Banking bits are unaffected by this pCode.
3490  *
3491  * return: > 0 == Banking bits are affected.
3492  *
3493  *  If the banking bits are affected, then the returned value describes
3494  * which bits are affected and how they're affected. The lower half
3495  * of the integer maps to the bits that are affected, the upper half
3496  * to whether they're set or cleared.
3497  *
3498  *-----------------------------------------------------------------*/
3499 #define SET_BANK_BIT (1 << 16)
3500 #define CLR_BANK_BIT 0
3501
3502 int isBankInstruction(pCode *pc)
3503 {
3504   regs *reg;
3505   int bank = -1;
3506
3507   if(!isPCI(pc))
3508     return -1;
3509
3510   if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3511
3512     /* Check to see if the register banks are changing */
3513     if(PCI(pc)->isModReg) {
3514
3515       pCodeOp *pcop = PCI(pc)->pcop;
3516       switch(PCI(pc)->op) {
3517
3518       case POC_BSF:
3519         if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3520           //fprintf(stderr, "  isBankInstruction - Set RP0\n");
3521           return  SET_BANK_BIT | PIC_RP0_BIT;
3522         }
3523
3524         if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3525           //fprintf(stderr, "  isBankInstruction - Set RP1\n");
3526           return  CLR_BANK_BIT | PIC_RP0_BIT;
3527         }
3528         break;
3529
3530       case POC_BCF:
3531         if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3532           //fprintf(stderr, "  isBankInstruction - Clr RP0\n");
3533           return  CLR_BANK_BIT | PIC_RP1_BIT;
3534         }
3535         if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3536           //fprintf(stderr, "  isBankInstruction - Clr RP1\n");
3537           return  CLR_BANK_BIT | PIC_RP1_BIT;
3538         }
3539         break;
3540       default:
3541         //fprintf(stderr, "  isBankInstruction - Status register is getting Modified by:\n");
3542         //genericPrint(stderr, pc);
3543         ;
3544       }
3545     }
3546
3547   }
3548
3549   return bank;
3550 }
3551
3552
3553 /*-----------------------------------------------------------------*/
3554 /*-----------------------------------------------------------------*/
3555 void FillFlow(pCodeFlow *pcflow)
3556 {
3557
3558   pCode *pc;
3559   int cur_bank;
3560
3561   if(!isPCFL(pcflow))
3562     return;
3563
3564   //  fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3565
3566   pc = findNextpCode(PCODE(pcflow), PC_OPCODE); 
3567
3568   if(!pc) {
3569     //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3570     return;
3571   }
3572
3573   cur_bank = -1;
3574
3575   do {
3576     isBankInstruction(pc);
3577     pc = pc->next;
3578   } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3579
3580 /*
3581   if(!pc ) {
3582     fprintf(stderr, "  FillFlow - Bad end of flow\n");
3583   } else {
3584     fprintf(stderr, "  FillFlow - Ending flow with\n  ");
3585     pc->print(stderr,pc);
3586   }
3587
3588   fprintf(stderr, "  FillFlow inCond: ");
3589   dumpCond(pcflow->inCond);
3590   fprintf(stderr, "  FillFlow outCond: ");
3591   dumpCond(pcflow->outCond);
3592 */
3593 }
3594
3595 /*-----------------------------------------------------------------*/
3596 /*-----------------------------------------------------------------*/
3597 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3598 {
3599   pCodeFlowLink *fromLink, *toLink;
3600
3601   if(!from || !to || !to->pcflow || !from->pcflow)
3602     return;
3603
3604   fromLink = newpCodeFlowLink(from->pcflow);
3605   toLink   = newpCodeFlowLink(to->pcflow);
3606
3607   addSetIfnotP(&(from->pcflow->to), toLink);   //to->pcflow);
3608   addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3609
3610 }
3611
3612 /*-----------------------------------------------------------------*
3613  * void LinkFlow(pBlock *pb)
3614  *
3615  * In BuildFlow, the PIC code has been partitioned into contiguous
3616  * non-branching segments. In LinkFlow, we determine the execution
3617  * order of these segments. For example, if one of the segments ends
3618  * with a skip, then we know that there are two possible flow segments
3619  * to which control may be passed.
3620  *-----------------------------------------------------------------*/
3621 void LinkFlow(pBlock *pb)
3622 {
3623   pCode *pc=NULL;
3624   pCode *pcflow;
3625   pCode *pct;
3626
3627   //fprintf(stderr,"linkflow \n");
3628
3629   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
3630        pcflow != NULL;
3631        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3632
3633     if(!isPCFL(pcflow))
3634       fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3635
3636     //fprintf(stderr," link: ");
3637     //pcflow->print(stderr,pcflow);
3638
3639     //FillFlow(PCFL(pcflow));
3640
3641     pc = PCFL(pcflow)->end;
3642
3643     //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3644     if(isPCI_SKIP(pc)) {
3645       //fprintf(stderr, "ends with skip\n");
3646       //pc->print(stderr,pc);
3647       pct=findNextInstruction(pc->next);
3648       LinkFlow_pCode(PCI(pc),PCI(pct));
3649       pct=findNextInstruction(pct->next);
3650       LinkFlow_pCode(PCI(pc),PCI(pct));
3651       continue;
3652     }
3653
3654     if(isPCI_BRANCH(pc)) {
3655       pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3656
3657       //fprintf(stderr, "ends with branch\n  ");
3658       //pc->print(stderr,pc);
3659
3660       if(!(pcol && isPCOLAB(pcol))) {
3661         if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) {
3662           pc->print(stderr,pc);
3663           fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3664         }
3665         continue;
3666       }
3667
3668       if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3669         LinkFlow_pCode(PCI(pc),PCI(pct));
3670       else
3671         fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
3672
3673       continue;
3674     }
3675
3676     if(isPCI(pc)) {
3677       //fprintf(stderr, "ends with non-branching instruction:\n");
3678       //pc->print(stderr,pc);
3679
3680       LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3681
3682       continue;
3683     }
3684
3685     if(pc) {
3686       //fprintf(stderr, "ends with unknown\n");
3687       //pc->print(stderr,pc);
3688       continue;
3689     }
3690
3691     //fprintf(stderr, "ends with nothing: ERROR\n");
3692     
3693   }
3694 }
3695 /*-----------------------------------------------------------------*/
3696 /*-----------------------------------------------------------------*/
3697
3698 /*-----------------------------------------------------------------*/
3699 /*-----------------------------------------------------------------*/
3700 int isPCinFlow(pCode *pc, pCode *pcflow)
3701 {
3702
3703   if(!pc || !pcflow)
3704     return 0;
3705
3706   if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3707     return 0;
3708
3709   if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3710     return 1;
3711
3712   return 0;
3713 }
3714
3715 /*-----------------------------------------------------------------*/
3716 /*-----------------------------------------------------------------*/
3717 void BanksUsedFlow2(pCode *pcflow)
3718 {
3719   pCode *pc=NULL;
3720
3721   int bank = -1;
3722   bool RegUsed = 0;
3723
3724   regs *reg;
3725
3726   if(!isPCFL(pcflow)) {
3727     fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3728     return;
3729   }
3730
3731   pc = findNextInstruction(pcflow->next);
3732
3733   PCFL(pcflow)->lastBank = -1;
3734
3735   while(isPCinFlow(pc,pcflow)) {
3736
3737     int bank_selected = isBankInstruction(pc);
3738
3739     //if(PCI(pc)->pcflow) 
3740     //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3741
3742     if(bank_selected > 0) {
3743       //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3744
3745       /* This instruction is modifying banking bits before accessing registers */
3746       if(!RegUsed)
3747         PCFL(pcflow)->firstBank = -1;
3748
3749       if(PCFL(pcflow)->lastBank == -1)
3750         PCFL(pcflow)->lastBank = 0;
3751
3752       bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3753       if(bank_selected & SET_BANK_BIT)
3754         PCFL(pcflow)->lastBank |= bank;
3755                                  
3756
3757     } else { 
3758       reg = getRegFromInstruction(pc);
3759
3760       if(reg && !isREGinBank(reg, bank)) {
3761         int allbanks = REGallBanks(reg);
3762         if(bank == -1)
3763           PCFL(pcflow)->firstBank = allbanks;
3764
3765         PCFL(pcflow)->lastBank = allbanks;
3766
3767         bank = allbanks;
3768       }
3769       RegUsed = 1;
3770     }
3771
3772     pc = findNextInstruction(pc->next);
3773   }
3774
3775 //  fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3776 //        pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3777
3778
3779
3780 }
3781 /*-----------------------------------------------------------------*/
3782 /*-----------------------------------------------------------------*/
3783 void BanksUsedFlow(pBlock *pb)
3784 {
3785   pCode *pcflow;
3786
3787
3788   //pb->pcHead->print(stderr, pb->pcHead);
3789
3790   pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3791   //pcflow->print(stderr,pcflow);
3792
3793   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
3794        pcflow != NULL;
3795        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3796
3797     BanksUsedFlow2(pcflow);
3798   }
3799
3800 }
3801
3802
3803 /*-----------------------------------------------------------------*/
3804 /*-----------------------------------------------------------------*/
3805 void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
3806 {
3807   pCode *new_pc;
3808
3809   if(!pc)
3810     return;
3811
3812   if(RP_BankBit < 0) 
3813     new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3814   else
3815     new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3816                       popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3817
3818   pCodeInsertAfter(pc->prev, new_pc);
3819
3820   /* Move the label, if there is one */
3821
3822   if(PCI(pc)->label) {
3823     PCI(new_pc)->label = PCI(pc)->label;
3824     PCI(pc)->label = NULL;
3825   }
3826
3827   /* The new instruction has the same pcflow block */
3828   PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3829
3830 }
3831 /*-----------------------------------------------------------------*/
3832 /*-----------------------------------------------------------------*/
3833 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3834 {
3835   pCode *pc=NULL;
3836   pCode *pcprev=NULL;
3837   pCode *new_pc;
3838
3839   regs *reg;
3840
3841   if(!pcfl)
3842     return;
3843
3844   pc = findNextInstruction(pcfl->pc.next);
3845
3846   while(isPCinFlow(pc,PCODE(pcfl))) {
3847
3848
3849     reg = getRegFromInstruction(pc);
3850 #if 0
3851     if(reg) {
3852       fprintf(stderr, "  %s  ",reg->name);
3853       fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3854
3855     }
3856 #endif
3857
3858     if(reg && REG_BANK(reg)!=cur_bank) {
3859       /* Examine the instruction before this one to make sure it is
3860        * not a skip type instruction */
3861       pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3862       if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3863         int b = cur_bank ^ REG_BANK(reg);
3864
3865         //fprintf(stderr, "Cool! can switch banks\n");
3866         cur_bank = REG_BANK(reg);
3867         switch(b & 3) {
3868         case 0:
3869           break;
3870         case 1:
3871           insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3872           break;
3873         case 2:
3874           insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3875           insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3876           break;
3877         case 3:
3878           if(cur_bank & 3) {
3879             insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3880             insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3881           } else
3882             insertBankSwitch(pc, -1, -1);
3883           break;
3884           /*
3885             new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3886             popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3887             pCodeInsertAfter(pc->prev, new_pc);
3888             if(PCI(pc)->label) { 
3889             PCI(new_pc)->label = PCI(pc)->label;
3890             PCI(pc)->label = NULL;
3891             }
3892           */
3893           /*
3894             new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3895             popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3896             pCodeInsertAfter(pc, new_pc);
3897           */
3898
3899         }
3900
3901       } else {
3902         //fprintf(stderr, "Bummer can't switch banks\n");
3903         ;
3904       }
3905     }
3906
3907     pcprev = pc;
3908     pc = findNextInstruction(pc->next);
3909
3910   }
3911
3912   if(pcprev && cur_bank) {
3913     /* Brute force - make sure that we point to bank 0 at the
3914      * end of each flow block */
3915     new_pc = newpCode(POC_BCF,
3916                       popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3917     pCodeInsertAfter(pcprev, new_pc);
3918       cur_bank = 0;
3919   }
3920
3921 }
3922
3923 /*-----------------------------------------------------------------*/
3924 /*int compareBankFlow - compare the banking requirements between   */
3925 /*  flow objects. */
3926 /*-----------------------------------------------------------------*/
3927 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3928 {
3929
3930   if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3931     return 0;
3932
3933   if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3934     return 0;
3935
3936   if(pcflow->firstBank == -1)
3937     return 0;
3938
3939
3940   if(pcflowLink->pcflow->firstBank == -1) {
3941     pCodeFlowLink *pctl = setFirstItem( toORfrom ? 
3942                                         pcflowLink->pcflow->to : 
3943                                         pcflowLink->pcflow->from);
3944     return compareBankFlow(pcflow, pctl, toORfrom);
3945   }
3946
3947   if(toORfrom) {
3948     if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3949       return 0;
3950
3951     pcflowLink->bank_conflict++;
3952     pcflowLink->pcflow->FromConflicts++;
3953     pcflow->ToConflicts++;
3954   } else {
3955     
3956     if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3957       return 0;
3958
3959     pcflowLink->bank_conflict++;
3960     pcflowLink->pcflow->ToConflicts++;
3961     pcflow->FromConflicts++;
3962
3963   }
3964   /*
3965   fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3966           pcflowLink->pcflow->pc.seq,
3967           pcflowLink->pcflow->FromConflicts,
3968           pcflowLink->pcflow->ToConflicts);
3969   */
3970   return 1;
3971
3972 }
3973 /*-----------------------------------------------------------------*/
3974 /*-----------------------------------------------------------------*/
3975 void FixBankFlow(pBlock *pb)
3976 {
3977   pCode *pc=NULL;
3978   pCode *pcflow;
3979   pCodeFlowLink *pcfl;
3980
3981   pCode *pcflow_max_To=NULL;
3982   pCode *pcflow_max_From=NULL;
3983   int max_ToConflicts=0;
3984   int max_FromConflicts=0;
3985
3986   //fprintf(stderr,"Fix Bank flow \n");
3987   pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3988
3989
3990   /*
3991     First loop through all of the flow objects in this pcode block
3992     and fix the ones that have banking conflicts between the 
3993     entry and exit.
3994   */
3995
3996   //fprintf(stderr, "FixBankFlow - Phase 1\n");
3997
3998   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
3999        pcflow != NULL;
4000        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4001
4002     if(!isPCFL(pcflow)) {
4003       fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4004       continue;
4005     }
4006
4007     if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank  &&
4008        PCFL(pcflow)->firstBank >= 0 &&
4009        PCFL(pcflow)->lastBank >= 0 ) {
4010
4011       int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4012         PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4013
4014       FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4015       BanksUsedFlow2(pcflow);
4016
4017     }
4018   }
4019
4020   //fprintf(stderr, "FixBankFlow - Phase 2\n");
4021
4022   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4023        pcflow != NULL;
4024        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4025
4026     int nFlows;
4027     int nConflicts;
4028
4029     if(!isPCFL(pcflow)) {
4030       fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4031       continue;
4032     }
4033
4034     PCFL(pcflow)->FromConflicts = 0;
4035     PCFL(pcflow)->ToConflicts = 0;
4036
4037     nFlows = 0;
4038     nConflicts = 0;
4039
4040     //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4041     pcfl = setFirstItem(PCFL(pcflow)->from);
4042     while (pcfl) {
4043
4044       pc = PCODE(pcfl->pcflow);
4045
4046       if(!isPCFL(pc)) {
4047         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4048         pc->print(stderr,pc);
4049       }
4050
4051       nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4052       nFlows++;
4053
4054       pcfl=setNextItem(PCFL(pcflow)->from);
4055     }
4056
4057     if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4058       //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4059
4060       FixRegisterBankingInFlow(PCFL(pcflow),0);
4061       BanksUsedFlow2(pcflow);
4062
4063       continue;  /* Don't need to check the flow from here - it's already been fixed */
4064
4065     }
4066
4067     nFlows = 0;
4068     nConflicts = 0;
4069
4070     pcfl = setFirstItem(PCFL(pcflow)->to);
4071     while (pcfl) {
4072
4073       pc = PCODE(pcfl->pcflow);
4074       if(!isPCFL(pc)) {
4075         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4076         pc->print(stderr,pc);
4077       }
4078
4079       nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4080       nFlows++;
4081
4082       pcfl=setNextItem(PCFL(pcflow)->to);
4083     }
4084
4085     if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4086       //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4087
4088       FixRegisterBankingInFlow(PCFL(pcflow),0);
4089       BanksUsedFlow2(pcflow);
4090     }
4091   }
4092
4093   /*
4094     Loop through the flow objects again and find the ones with the 
4095     maximum conflicts
4096   */
4097
4098   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4099        pcflow != NULL;
4100        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4101
4102     if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4103       pcflow_max_To = pcflow;
4104
4105     if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4106       pcflow_max_From = pcflow;
4107   }
4108 /*
4109   if(pcflow_max_To)
4110     fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4111             PCFL(pcflow_max_To)->pc.seq,
4112             PCFL(pcflow_max_To)->ToConflicts);
4113
4114   if(pcflow_max_From)
4115     fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4116             PCFL(pcflow_max_From)->pc.seq,
4117             PCFL(pcflow_max_From)->FromConflicts);
4118 */
4119 }
4120
4121 /*-----------------------------------------------------------------*/
4122 /*-----------------------------------------------------------------*/
4123 void DumpFlow(pBlock *pb)
4124 {
4125   pCode *pc=NULL;
4126   pCode *pcflow;
4127   pCodeFlowLink *pcfl;
4128
4129
4130   fprintf(stderr,"Dump flow \n");
4131   pb->pcHead->print(stderr, pb->pcHead);
4132
4133   pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4134   pcflow->print(stderr,pcflow);
4135
4136   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4137        pcflow != NULL;
4138        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4139
4140     if(!isPCFL(pcflow)) {
4141       fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4142       continue;
4143     }
4144     fprintf(stderr,"dumping: ");
4145     pcflow->print(stderr,pcflow);
4146     FlowStats(PCFL(pcflow));
4147
4148     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4149
4150       pc = PCODE(pcfl->pcflow);
4151
4152       fprintf(stderr, "    from seq %d:\n",pc->seq);
4153       if(!isPCFL(pc)) {
4154         fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4155         pc->print(stderr,pc);
4156       }
4157
4158     }
4159
4160     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4161
4162       pc = PCODE(pcfl->pcflow);
4163
4164       fprintf(stderr, "    to seq %d:\n",pc->seq);
4165       if(!isPCFL(pc)) {
4166         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4167         pc->print(stderr,pc);
4168       }
4169
4170     }
4171
4172   }
4173
4174 }
4175
4176 /*-----------------------------------------------------------------*/
4177 /*-----------------------------------------------------------------*/
4178 int OptimizepBlock(pBlock *pb)
4179 {
4180   pCode *pc, *pcprev;
4181   int matches =0;
4182
4183   if(!pb || !peepOptimizing)
4184     return 0;
4185
4186   DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4187 /*
4188   for(pc = pb->pcHead; pc; pc = pc->next)
4189     matches += pCodePeepMatchRule(pc);
4190 */
4191
4192   pc = findNextInstruction(pb->pcHead);
4193   if(!pc)
4194     return 0;
4195
4196   pcprev = pc->prev;
4197   do {
4198
4199
4200     if(pCodePeepMatchRule(pc)) {
4201
4202       matches++;
4203
4204       if(pcprev)
4205         pc = findNextInstruction(pcprev->next);
4206       else 
4207         pc = findNextInstruction(pb->pcHead);
4208     } else
4209       pc = findNextInstruction(pc->next);
4210   } while(pc);
4211
4212   if(matches)
4213     DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4214   return matches;
4215
4216 }
4217
4218 /*-----------------------------------------------------------------*/
4219 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
4220 /*-----------------------------------------------------------------*/
4221 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4222 {
4223   pCode *pc;
4224
4225   for(pc = pcs; pc; pc = pc->next) {
4226
4227     if((pc->type == PC_OPCODE) && 
4228        (PCI(pc)->pcop) && 
4229        (PCI(pc)->pcop->type == PO_LABEL) &&
4230        (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4231       return pc;
4232   }
4233  
4234
4235   return NULL;
4236 }
4237
4238 /*-----------------------------------------------------------------*/
4239 /*-----------------------------------------------------------------*/
4240 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4241 {
4242
4243   if(isPCI(pc) && 
4244      (PCI(pc)->pcop) && 
4245      (PCI(pc)->pcop->type == PO_LABEL)) {
4246
4247     pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4248
4249     //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4250     if(pcol->pcop.name)
4251       free(pcol->pcop.name);
4252
4253     sprintf(buffer,"_%05d_DS_",pcl->key);
4254
4255     pcol->pcop.name = Safe_strdup(buffer);
4256     pcol->key = pcl->key;
4257     //pc->print(stderr,pc);
4258
4259   }
4260
4261
4262 }
4263
4264 /*-----------------------------------------------------------------*/
4265 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
4266 /*                            pCode chain if they're not used.     */
4267 /*-----------------------------------------------------------------*/
4268 void pBlockRemoveUnusedLabels(pBlock *pb)
4269 {
4270   pCode *pc; pCodeLabel *pcl;
4271
4272   if(!pb)
4273     return;
4274
4275   for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4276
4277     pBranch *pbr = PCI(pc)->label;
4278     if(pbr && pbr->next) {
4279       pCode *pcd = pb->pcHead;
4280
4281       //fprintf(stderr, "multiple labels\n");
4282       //pc->print(stderr,pc);
4283
4284       pbr = pbr->next;
4285       while(pbr) {
4286
4287         while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4288           //fprintf(stderr,"Used by:\n");
4289           //pcd->print(stderr,pcd);
4290
4291           exchangeLabels(PCL(pbr->pc),pcd);
4292
4293           pcd = pcd->next;
4294         }
4295         pbr = pbr->next;
4296       }
4297     }
4298   }
4299
4300   for(pc = pb->pcHead; pc; pc = pc->next) {
4301
4302     if(isPCL(pc)) // pc->type == PC_LABEL)
4303       pcl = PCL(pc);
4304     else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4305       pcl = PCL(PCI(pc)->label->pc);
4306     else continue;
4307
4308     //fprintf(stderr," found  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4309
4310     /* This pCode is a label, so search the pBlock to see if anyone
4311      * refers to it */
4312
4313     if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4314     //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4315       /* Couldn't find an instruction that refers to this label
4316        * So, unlink the pCode label from it's pCode chain
4317        * and destroy the label */
4318       //fprintf(stderr," removed  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4319
4320       DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4321       if(pc->type == PC_LABEL) {
4322         unlinkpCode(pc);
4323         pCodeLabelDestruct(pc);
4324       } else {
4325         unlinkpCodeFromBranch(pc, PCODE(pcl));
4326         /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4327           free(pc->label);
4328         }*/
4329       }
4330
4331     }
4332   }
4333
4334 }
4335
4336
4337 /*-----------------------------------------------------------------*/
4338 /* pBlockMergeLabels - remove the pCode labels from the pCode      */
4339 /*                     chain and put them into pBranches that are  */
4340 /*                     associated with the appropriate pCode       */
4341 /*                     instructions.                               */
4342 /*-----------------------------------------------------------------*/
4343 void pBlockMergeLabels(pBlock *pb)
4344 {
4345   pBranch *pbr;
4346   pCode *pc, *pcnext=NULL;
4347
4348   if(!pb)
4349     return;
4350
4351   /* First, Try to remove any unused labels */
4352   //pBlockRemoveUnusedLabels(pb);
4353
4354   /* Now loop through the pBlock and merge the labels with the opcodes */
4355
4356   pc = pb->pcHead;
4357   //  for(pc = pb->pcHead; pc; pc = pc->next) {
4358
4359   while(pc) {
4360     pCode *pcn = pc->next;
4361
4362     if(pc->type == PC_LABEL) {
4363
4364       //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4365       //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4366       if((pcnext = findNextInstruction(pc) )) {
4367
4368         // Unlink the pCode label from it's pCode chain
4369         unlinkpCode(pc);
4370         
4371         //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4372         // And link it into the instruction's pBranch labels. (Note, since
4373         // it's possible to have multiple labels associated with one instruction
4374         // we must provide a means to accomodate the additional labels. Thus
4375         // the labels are placed into the singly-linked list "label" as 
4376         // opposed to being a single member of the pCodeInstruction.)
4377
4378         //_ALLOC(pbr,sizeof(pBranch));
4379         pbr = Safe_calloc(1,sizeof(pBranch));
4380         pbr->pc = pc;
4381         pbr->next = NULL;
4382
4383         PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4384
4385       } else {
4386         fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4387       }
4388     } else if(pc->type == PC_CSOURCE) {
4389
4390       /* merge the source line symbolic info into the next instruction */
4391       if((pcnext = findNextInstruction(pc) )) {
4392
4393         // Unlink the pCode label from it's pCode chain
4394         unlinkpCode(pc);
4395         PCI(pcnext)->cline = PCCS(pc);
4396         //fprintf(stderr, "merging CSRC\n");
4397         //genericPrint(stderr,pcnext);
4398       }
4399
4400     }
4401     pc = pcn;
4402   }
4403   pBlockRemoveUnusedLabels(pb);
4404
4405 }
4406
4407 /*-----------------------------------------------------------------*/
4408 /*-----------------------------------------------------------------*/
4409 int OptimizepCode(char dbName)
4410 {
4411 #define MAX_PASSES 4
4412
4413   int matches = 0;
4414   int passes = 0;
4415   pBlock *pb;
4416
4417   if(!the_pFile)
4418     return 0;
4419
4420   DFPRINTF((stderr," Optimizing pCode\n"));
4421
4422   do {
4423     matches = 0;
4424     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4425       if('*' == dbName || getpBlock_dbName(pb) == dbName)
4426         matches += OptimizepBlock(pb);
4427     }
4428   }
4429   while(matches && ++passes < MAX_PASSES);
4430
4431   return matches;
4432 }
4433
4434 /*-----------------------------------------------------------------*/
4435 /* popCopyGPR2Bit - copy a pcode operator                          */
4436 /*-----------------------------------------------------------------*/
4437
4438 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4439 {
4440   pCodeOp *pcop;
4441
4442   pcop = newpCodeOpBit(pc->name, bitval, 0);
4443
4444   if( !( (pcop->type == PO_LABEL) ||
4445          (pcop->type == PO_LITERAL) ||
4446          (pcop->type == PO_STR) ))
4447     PCOR(pcop)->r = PCOR(pc)->r;  /* This is dangerous... */
4448
4449   return pcop;
4450 }
4451
4452
4453
4454 #if 0
4455 /*-----------------------------------------------------------------*/
4456 /*-----------------------------------------------------------------*/
4457 int InstructionRegBank(pCode *pc)
4458 {
4459   regs *reg;
4460
4461   if( (reg = getRegFromInstruction(pc)) == NULL)
4462     return -1;
4463
4464   return REG_BANK(reg);
4465
4466 }
4467 #endif
4468
4469 /*-----------------------------------------------------------------*/
4470 /*-----------------------------------------------------------------*/
4471 void FixRegisterBanking(pBlock *pb)
4472 {
4473   pCode *pc=NULL;
4474   pCode *pcprev=NULL;
4475   pCode *new_pc;
4476
4477   int cur_bank;
4478   regs *reg;
4479   //  return;
4480   if(!pb)
4481     return;
4482
4483   //pc = findNextpCode(pb->pcHead, PC_FLOW);
4484   pc = findNextpCode(pb->pcHead, PC_OPCODE);
4485   if(!pc)
4486     return;
4487   /* loop through all of the flow blocks with in one pblock */
4488
4489   //fprintf(stderr,"Register banking\n");
4490   cur_bank = 0;
4491   do {
4492     /* at this point, pc should point to a PC_FLOW object */
4493
4494
4495     /* for each flow block, determine the register banking 
4496        requirements */
4497
4498     //    do {
4499       if(isPCI(pc)) {
4500         //genericPrint(stderr, pc);
4501
4502         reg = getRegFromInstruction(pc);
4503         #if 0
4504         if(reg) {
4505           fprintf(stderr, "  %s  ",reg->name);
4506           fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4507
4508         }
4509         #endif
4510         if(reg && REG_BANK(reg)!=cur_bank) {
4511           /* Examine the instruction before this one to make sure it is
4512            * not a skip type instruction */
4513           pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4514           if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4515             int b = cur_bank ^ REG_BANK(reg);
4516
4517             //fprintf(stderr, "Cool! can switch banks\n");
4518             cur_bank = REG_BANK(reg);
4519             if(b & 1) {
4520               new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
4521                                 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4522               pCodeInsertAfter(pc->prev, new_pc);
4523               if(PCI(pc)->label) { 
4524                 PCI(new_pc)->label = PCI(pc)->label;
4525                 PCI(pc)->label = NULL;
4526               }
4527               /*
4528                 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
4529                 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4530                 pCodeInsertAfter(pc, new_pc);
4531               */
4532
4533             }
4534
4535           } else {
4536             //fprintf(stderr, "Bummer can't switch banks\n");
4537             ;
4538           }
4539         }
4540       }
4541
4542       pcprev = pc;
4543       pc = pc->next;
4544       // } while(pc && !(isPCFL(pc))); 
4545
4546
4547   }while (pc);
4548
4549     if(pcprev && cur_bank) {
4550       /* Brute force - make sure that we point to bank 0 at the
4551        * end of each flow block */
4552       new_pc = newpCode(POC_BCF,
4553                         popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4554       pCodeInsertAfter(pcprev, new_pc);
4555       cur_bank = 0;
4556     }
4557
4558 }
4559
4560 void pBlockDestruct(pBlock *pb)
4561 {
4562
4563   if(!pb)
4564     return;
4565
4566
4567   free(pb);
4568
4569 }
4570
4571 /*-----------------------------------------------------------------*/
4572 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4573 /*                                  name dbName and combine them   */
4574 /*                                  into one block                 */
4575 /*-----------------------------------------------------------------*/
4576 void mergepBlocks(char dbName)
4577 {
4578
4579   pBlock *pb, *pbmerged = NULL,*pbn;
4580
4581   pb = the_pFile->pbHead;
4582
4583   //fprintf(stderr," merging blocks named %c\n",dbName);
4584   while(pb) {
4585
4586     pbn = pb->next;
4587     //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4588     if( getpBlock_dbName(pb) == dbName) {
4589
4590       //fprintf(stderr," merged block %c\n",dbName);
4591
4592       if(!pbmerged) {
4593         pbmerged = pb;
4594       } else {
4595         addpCode2pBlock(pbmerged, pb->pcHead);
4596         /* addpCode2pBlock doesn't handle the tail: */
4597         pbmerged->pcTail = pb->pcTail;
4598
4599         pb->prev->next = pbn;
4600         if(pbn) 
4601           pbn->prev = pb->prev;
4602
4603
4604         pBlockDestruct(pb);
4605       }
4606       //printpBlock(stderr, pbmerged);
4607     } 
4608     pb = pbn;
4609   }
4610
4611 }
4612
4613 /*-----------------------------------------------------------------*/
4614 /* AnalyzeFlow - Examine the flow of the code and optimize         */
4615 /*                                                                 */
4616 /* level 0 == minimal optimization                                 */
4617 /*   optimize registers that are used only by two instructions     */
4618 /* level 1 == maximal optimization                                 */
4619 /*   optimize by looking at pairs of instructions that use the     */
4620 /*   register.                                                     */
4621 /*-----------------------------------------------------------------*/
4622
4623 void AnalyzeFlow(int level)
4624 {
4625   static int times_called=0;
4626
4627   pBlock *pb;
4628
4629   if(!the_pFile)
4630     return;
4631
4632
4633   /* if this is not the first time this function has been called,
4634      then clean up old flow information */
4635   if(times_called++) {
4636     for(pb = the_pFile->pbHead; pb; pb = pb->next)
4637       unBuildFlow(pb);
4638
4639     RegsUnMapLiveRanges();
4640
4641   }
4642
4643   GpcFlowSeq = 1;
4644
4645   /* Phase 2 - Flow Analysis - Register Banking
4646    *
4647    * In this phase, the individual flow blocks are examined
4648    * and register banking is fixed.
4649    */
4650
4651   //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4652   //FixRegisterBanking(pb);
4653
4654   /* Phase 2 - Flow Analysis
4655    *
4656    * In this phase, the pCode is partition into pCodeFlow 
4657    * blocks. The flow blocks mark the points where a continuous
4658    * stream of instructions changes flow (e.g. because of
4659    * a call or goto or whatever).
4660    */
4661
4662   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4663     BuildFlow(pb);
4664
4665
4666   /* Phase 2 - Flow Analysis - linking flow blocks
4667    *
4668    * In this phase, the individual flow blocks are examined
4669    * to determine their order of excution.
4670    */
4671
4672   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4673     LinkFlow(pb);
4674
4675   /* Phase 3 - Flow Analysis - Flow Tree
4676    *
4677    * In this phase, the individual flow blocks are examined
4678    * to determine their order of excution.
4679    */
4680   /*
4681   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4682     BuildFlowTree(pb);
4683
4684   */
4685
4686   /* Phase x - Flow Analysis - Used Banks
4687    *
4688    * In this phase, the individual flow blocks are examined
4689    * to determine the Register Banks they use
4690    */
4691
4692   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4693     FixBankFlow(pb);
4694
4695
4696   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4697     pCodeRegMapLiveRanges(pb);
4698
4699   RemoveUnusedRegisters();
4700
4701   //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
4702   pCodeRegOptimizeRegUsage(level);
4703
4704   OptimizepCode('*');
4705
4706
4707 /*
4708   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4709     DumpFlow(pb);
4710 */
4711   /* debug stuff */ 
4712   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4713     pCode *pcflow;
4714     for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4715          (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4716          pcflow = pcflow->next) {
4717
4718       FillFlow(PCFL(pcflow));
4719     }
4720   }
4721
4722 /*
4723   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4724     pCode *pcflow;
4725     for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4726          (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4727          pcflow = pcflow->next) {
4728
4729       FlowStats(PCFL(pcflow));
4730     }
4731   }
4732 */
4733 }
4734
4735 /*-----------------------------------------------------------------*/
4736 /* AnalyzeBanking - Called after the memory addresses have been    */
4737 /*                  assigned to the registers.                     */
4738 /*                                                                 */
4739 /*-----------------------------------------------------------------*/
4740
4741 void AnalyzeBanking(void)
4742 {
4743   pBlock  *pb;
4744
4745   if(!picIsInitialized()) {
4746     fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
4747     fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
4748     fprintf(stderr,"support/scripts/inc2h.pl\n");
4749     fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
4750
4751     exit(1);
4752   }
4753
4754   /* Phase x - Flow Analysis - Used Banks
4755    *
4756    * In this phase, the individual flow blocks are examined
4757    * to determine the Register Banks they use
4758    */
4759
4760   AnalyzeFlow(0);
4761   AnalyzeFlow(1);
4762
4763   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4764     BanksUsedFlow(pb);
4765   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4766     FixRegisterBanking(pb);
4767
4768 }
4769
4770 /*-----------------------------------------------------------------*/
4771 /* buildCallTree - look at the flow and extract all of the calls   */
4772 /*                                                                 */
4773 /*-----------------------------------------------------------------*/
4774 set *register_usage(pBlock *pb);
4775
4776 void buildCallTree(void    )
4777 {
4778   pBranch *pbr;
4779   pBlock  *pb;
4780   pCode   *pc;
4781
4782   if(!the_pFile)
4783     return;
4784
4785
4786
4787   /* Now build the call tree.
4788      First we examine all of the pCodes for functions.
4789      Keep in mind that the function boundaries coincide
4790      with pBlock boundaries. 
4791
4792      The algorithm goes something like this:
4793      We have two nested loops. The outer loop iterates
4794      through all of the pBlocks/functions. The inner
4795      loop iterates through all of the pCodes for
4796      a given pBlock. When we begin iterating through
4797      a pBlock, the variable pc_fstart, pCode of the start
4798      of a function, is cleared. We then search for pCodes
4799      of type PC_FUNCTION. When one is encountered, we
4800      initialize pc_fstart to this and at the same time
4801      associate a new pBranch object that signifies a 
4802      branch entry. If a return is found, then this signifies
4803      a function exit point. We'll link the pCodes of these
4804      returns to the matching pc_fstart.
4805
4806      When we're done, a doubly linked list of pBranches
4807      will exist. The head of this list is stored in
4808      `the_pFile', which is the meta structure for all
4809      of the pCode. Look at the printCallTree function
4810      on how the pBranches are linked together.
4811
4812    */
4813   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4814     pCode *pc_fstart=NULL;
4815     for(pc = pb->pcHead; pc; pc = pc->next) {
4816       if(isPCF(pc)) {
4817         if (PCF(pc)->fname) {
4818
4819           if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4820             //fprintf(stderr," found main \n");
4821             pb->cmemmap = NULL;  /* FIXME do we need to free ? */
4822             pb->dbName = 'M';
4823           }
4824
4825           pbr = Safe_calloc(1,sizeof(pBranch));
4826           pbr->pc = pc_fstart = pc;
4827           pbr->next = NULL;
4828
4829           the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4830
4831           // Here's a better way of doing the same:
4832           addSet(&pb->function_entries, pc);
4833
4834         } else {
4835           // Found an exit point in a function, e.g. return
4836           // (Note, there may be more than one return per function)
4837           if(pc_fstart)
4838             pBranchLink(PCF(pc_fstart), PCF(pc));
4839
4840           addSet(&pb->function_exits, pc);
4841         }
4842       } else if(isCALL(pc)) {
4843         addSet(&pb->function_calls,pc);
4844       }
4845     }
4846   }
4847
4848   /* Re-allocate the registers so that there are no collisions
4849    * between local variables when one function call another */
4850
4851   // this is weird...
4852   //  pic14_deallocateAllRegs();
4853
4854   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4855     if(!pb->visited)
4856       register_usage(pb);
4857   }
4858
4859 }
4860
4861 /*-----------------------------------------------------------------*/
4862 /* AnalyzepCode - parse the pCode that has been generated and form */
4863 /*                all of the logical connections.                  */
4864 /*                                                                 */
4865 /* Essentially what's done here is that the pCode flow is          */
4866 /* determined.                                                     */
4867 /*-----------------------------------------------------------------*/
4868
4869 void AnalyzepCode(char dbName)
4870 {
4871   pBlock *pb;
4872   int i,changes;
4873
4874   if(!the_pFile)
4875     return;
4876
4877   mergepBlocks('D');
4878
4879
4880   /* Phase 1 - Register allocation and peep hole optimization
4881    *
4882    * The first part of the analysis is to determine the registers
4883    * that are used in the pCode. Once that is done, the peep rules
4884    * are applied to the code. We continue to loop until no more
4885    * peep rule optimizations are found (or until we exceed the
4886    * MAX_PASSES threshold). 
4887    *
4888    * When done, the required registers will be determined.
4889    *
4890    */
4891   i = 0;
4892   do {
4893
4894     DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4895     //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4896
4897     /* First, merge the labels with the instructions */
4898     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4899       if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4900
4901         DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4902         //fprintf(stderr," analyze and merging block %c\n",dbName);
4903         pBlockMergeLabels(pb);
4904         AnalyzepBlock(pb);
4905       } else {
4906         DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4907       }
4908     }
4909
4910     changes = OptimizepCode(dbName);
4911
4912   } while(changes && (i++ < MAX_PASSES));
4913
4914   buildCallTree();
4915 }
4916
4917 /*-----------------------------------------------------------------*/
4918 /* ispCodeFunction - returns true if *pc is the pCode of a         */
4919 /*                   function                                      */
4920 /*-----------------------------------------------------------------*/
4921 bool ispCodeFunction(pCode *pc)
4922 {
4923
4924   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
4925     return 1;
4926
4927   return 0;
4928 }
4929
4930 /*-----------------------------------------------------------------*/
4931 /* findFunction - Search for a function by name (given the name)   */
4932 /*                in the set of all functions that are in a pBlock */
4933 /* (note - I expect this to change because I'm planning to limit   */
4934 /*  pBlock's to just one function declaration                      */
4935 /*-----------------------------------------------------------------*/
4936 pCode *findFunction(char *fname)
4937 {
4938   pBlock *pb;
4939   pCode *pc;
4940   if(!fname)
4941     return NULL;
4942
4943   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4944
4945     pc = setFirstItem(pb->function_entries);
4946     while(pc) {
4947     
4948       if((pc->type == PC_FUNCTION) &&
4949          (PCF(pc)->fname) && 
4950          (strcmp(fname, PCF(pc)->fname)==0))
4951         return pc;
4952
4953       pc = setNextItem(pb->function_entries);
4954
4955     }
4956
4957   }
4958   return NULL;
4959 }
4960
4961 void MarkUsedRegisters(set *regset)
4962 {
4963
4964   regs *r1,*r2;
4965
4966   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4967     r2 = pic14_regWithIdx(r1->rIdx);
4968     r2->isFree = 0;
4969     r2->wasUsed = 1;
4970   }
4971 }
4972
4973 void pBlockStats(FILE *of, pBlock *pb)
4974 {
4975
4976   pCode *pc;
4977   regs  *r;
4978
4979   fprintf(of,";***\n;  pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4980
4981   // for now just print the first element of each set
4982   pc = setFirstItem(pb->function_entries);
4983   if(pc) {
4984     fprintf(of,";entry:  ");
4985     pc->print(of,pc);
4986   }
4987   pc = setFirstItem(pb->function_exits);
4988   if(pc) {
4989     fprintf(of,";has an exit\n");
4990     //pc->print(of,pc);
4991   }
4992
4993   pc = setFirstItem(pb->function_calls);
4994   if(pc) {
4995     fprintf(of,";functions called:\n");
4996
4997     while(pc) {
4998       if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
4999         fprintf(of,";   %s\n",get_op_from_instruction(PCI(pc)));
5000       }
5001       pc = setNextItem(pb->function_calls);
5002     }
5003   }
5004
5005   r = setFirstItem(pb->tregisters);
5006   if(r) {
5007     int n = elementsInSet(pb->tregisters);
5008
5009     fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5010
5011     while (r) {
5012       fprintf(of,";   %s\n",r->name);
5013       r = setNextItem(pb->tregisters);
5014     }
5015   }
5016 }
5017
5018 /*-----------------------------------------------------------------*/
5019 /*-----------------------------------------------------------------*/
5020 #if 0
5021 static void sequencepCode(void)
5022 {
5023   pBlock *pb;
5024   pCode *pc;
5025
5026
5027   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5028
5029     pb->seq = GpCodeSequenceNumber+1;
5030
5031     for( pc = pb->pcHead; pc; pc = pc->next)
5032       pc->seq = ++GpCodeSequenceNumber;
5033   }
5034
5035 }
5036 #endif
5037
5038 /*-----------------------------------------------------------------*/
5039 /*-----------------------------------------------------------------*/
5040 set *register_usage(pBlock *pb)
5041 {
5042   pCode *pc,*pcn;
5043   set *registers=NULL;
5044   set *registersInCallPath = NULL;
5045
5046   /* check recursion */
5047
5048   pc = setFirstItem(pb->function_entries);
5049
5050   if(!pc)
5051     return registers;
5052
5053   pb->visited = 1;
5054
5055   if(pc->type != PC_FUNCTION)
5056     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5057
5058   pc = setFirstItem(pb->function_calls);
5059   for( ; pc; pc = setNextItem(pb->function_calls)) {
5060
5061     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5062       char *dest = get_op_from_instruction(PCI(pc));
5063
5064       pcn = findFunction(dest);
5065       if(pcn) 
5066         registersInCallPath = register_usage(pcn->pb);
5067     } else
5068       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5069
5070   }
5071
5072 #ifdef PCODE_DEBUG
5073   pBlockStats(stderr,pb);  // debug
5074 #endif
5075
5076   // Mark the registers in this block as used.
5077
5078   MarkUsedRegisters(pb->tregisters);
5079   if(registersInCallPath) {
5080     /* registers were used in the functions this pBlock has called */
5081     /* so now, we need to see if these collide with the ones we are */
5082     /* using here */
5083
5084     regs *r1,*r2, *newreg;
5085
5086     DFPRINTF((stderr,"comparing registers\n"));
5087
5088     r1 = setFirstItem(registersInCallPath);
5089     while(r1) {
5090
5091       r2 = setFirstItem(pb->tregisters);
5092
5093       while(r2 && (r1->type != REG_STK)) {
5094
5095         if(r2->rIdx == r1->rIdx) {
5096           newreg = pic14_findFreeReg(REG_GPR);
5097
5098
5099           if(!newreg) {
5100             DFPRINTF((stderr,"Bummer, no more registers.\n"));
5101             exit(1);
5102           }
5103
5104           DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5105                   r1->rIdx, newreg->rIdx));
5106           r2->rIdx = newreg->rIdx;
5107           //if(r2->name) free(r2->name);
5108           if(newreg->name)
5109             r2->name = Safe_strdup(newreg->name);
5110           else
5111             r2->name = NULL;
5112           newreg->isFree = 0;
5113           newreg->wasUsed = 1;
5114         }
5115         r2 = setNextItem(pb->tregisters);
5116       }
5117
5118       r1 = setNextItem(registersInCallPath);
5119     }
5120
5121     /* Collisions have been resolved. Now free the registers in the call path */
5122     r1 = setFirstItem(registersInCallPath);
5123     while(r1) {
5124       if(r1->type != REG_STK) {
5125         newreg = pic14_regWithIdx(r1->rIdx);
5126         newreg->isFree = 1;
5127       }
5128       r1 = setNextItem(registersInCallPath);
5129     }
5130
5131   }// else
5132   //    MarkUsedRegisters(pb->registers);
5133
5134   registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5135 #ifdef PCODE_DEBUG
5136   if(registers) 
5137     DFPRINTF((stderr,"returning regs\n"));
5138   else
5139     DFPRINTF((stderr,"not returning regs\n"));
5140
5141   DFPRINTF((stderr,"pBlock after register optim.\n"));
5142   pBlockStats(stderr,pb);  // debug
5143 #endif
5144
5145   return registers;
5146 }
5147
5148 /*-----------------------------------------------------------------*/
5149 /* printCallTree - writes the call tree to a file                  */
5150 /*                                                                 */
5151 /*-----------------------------------------------------------------*/
5152 void pct2(FILE *of,pBlock *pb,int indent)
5153 {
5154   pCode *pc,*pcn;
5155   int i;
5156   //  set *registersInCallPath = NULL;
5157
5158   if(!of)
5159     return;
5160
5161   if(indent > 10)
5162     return; //recursion ?
5163
5164   pc = setFirstItem(pb->function_entries);
5165
5166   if(!pc)
5167     return;
5168
5169   pb->visited = 0;
5170
5171   for(i=0;i<indent;i++)   // Indentation
5172     fputc(' ',of);
5173
5174   if(pc->type == PC_FUNCTION)
5175     fprintf(of,"%s\n",PCF(pc)->fname);
5176   else
5177     return;  // ???
5178
5179
5180   pc = setFirstItem(pb->function_calls);
5181   for( ; pc; pc = setNextItem(pb->function_calls)) {
5182
5183     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5184       char *dest = get_op_from_instruction(PCI(pc));
5185
5186       pcn = findFunction(dest);
5187       if(pcn) 
5188         pct2(of,pcn->pb,indent+1);
5189     } else
5190       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5191
5192   }
5193
5194
5195 }
5196
5197
5198 /*-----------------------------------------------------------------*/
5199 /* printCallTree - writes the call tree to a file                  */
5200 /*                                                                 */
5201 /*-----------------------------------------------------------------*/
5202
5203 void printCallTree(FILE *of)
5204 {
5205   pBranch *pbr;
5206   pBlock  *pb;
5207   pCode   *pc;
5208
5209   if(!the_pFile)
5210     return;
5211
5212   if(!of)
5213     of = stderr;
5214
5215   fprintf(of, "\npBlock statistics\n");
5216   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
5217     pBlockStats(of,pb);
5218
5219
5220
5221   fprintf(of,"Call Tree\n");
5222   pbr = the_pFile->functions;
5223   while(pbr) {
5224     if(pbr->pc) {
5225       pc = pbr->pc;
5226       if(!ispCodeFunction(pc))
5227         fprintf(of,"bug in call tree");
5228
5229
5230       fprintf(of,"Function: %s\n", PCF(pc)->fname);
5231
5232       while(pc->next && !ispCodeFunction(pc->next)) {
5233         pc = pc->next;
5234         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5235           fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5236       }
5237     }
5238
5239     pbr = pbr->next;
5240   }
5241
5242
5243   fprintf(of,"\n**************\n\na better call tree\n");
5244   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5245     if(pb->visited)
5246       pct2(of,pb,0);
5247   }
5248
5249   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5250     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5251   }
5252 }
5253
5254
5255
5256 /*-----------------------------------------------------------------*/
5257 /*                                                                 */
5258 /*-----------------------------------------------------------------*/
5259
5260 void InlineFunction(pBlock *pb)
5261 {
5262   pCode *pc;
5263   pCode *pc_call;
5264
5265   if(!pb)
5266     return;
5267
5268   pc = setFirstItem(pb->function_calls);
5269
5270   for( ; pc; pc = setNextItem(pb->function_calls)) {
5271
5272     if(isCALL(pc)) {
5273       pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5274       pCode *pct;
5275       pCode *pce;
5276
5277       pBranch *pbr;
5278
5279       if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5280         
5281         //fprintf(stderr,"Cool can inline:\n");
5282         //pcn->print(stderr,pcn);
5283
5284         //fprintf(stderr,"recursive call Inline\n");
5285         InlineFunction(pcn->pb);
5286         //fprintf(stderr,"return from recursive call Inline\n");
5287
5288         /*
5289           At this point, *pc points to a CALL mnemonic, and
5290           *pcn points to the function that is being called.
5291
5292           To in-line this call, we need to remove the CALL
5293           and RETURN(s), and link the function pCode in with
5294           the CALLee pCode.
5295
5296         */
5297
5298
5299         /* Remove the CALL */
5300         pc_call = pc;
5301         pc = pc->prev;
5302
5303         /* remove callee pBlock from the pBlock linked list */
5304         removepBlock(pcn->pb);
5305
5306         pce = pcn;
5307         while(pce) {
5308           pce->pb = pb;
5309           pce = pce->next;
5310         }
5311
5312         /* Remove the Function pCode */
5313         pct = findNextInstruction(pcn->next);
5314
5315         /* Link the function with the callee */
5316         pc->next = pcn->next;
5317         pcn->next->prev = pc;
5318         
5319         /* Convert the function name into a label */
5320
5321         pbr = Safe_calloc(1,sizeof(pBranch));
5322         pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5323         pbr->next = NULL;
5324         PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5325         PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5326
5327         /* turn all of the return's except the last into goto's */
5328         /* check case for 2 instruction pBlocks */
5329         pce = findNextInstruction(pcn->next);
5330         while(pce) {
5331           pCode *pce_next = findNextInstruction(pce->next);
5332
5333           if(pce_next == NULL) {
5334             /* found the last return */
5335             pCode *pc_call_next =  findNextInstruction(pc_call->next);
5336
5337             //fprintf(stderr,"found last return\n");
5338             //pce->print(stderr,pce);
5339             pce->prev->next = pc_call->next;
5340             pc_call->next->prev = pce->prev;
5341             PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5342                                                       PCI(pce)->label);
5343           }
5344
5345           pce = pce_next;
5346         }
5347
5348
5349       }
5350     } else
5351       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5352
5353   }
5354
5355 }
5356
5357 /*-----------------------------------------------------------------*/
5358 /*                                                                 */
5359 /*-----------------------------------------------------------------*/
5360
5361 void InlinepCode(void)
5362 {
5363
5364   pBlock  *pb;
5365   pCode   *pc;
5366
5367   if(!the_pFile)
5368     return;
5369
5370   if(!functionInlining)
5371     return;
5372
5373   /* Loop through all of the function definitions and count the
5374    * number of times each one is called */
5375   //fprintf(stderr,"inlining %d\n",__LINE__);
5376
5377   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5378
5379     pc = setFirstItem(pb->function_calls);
5380
5381     for( ; pc; pc = setNextItem(pb->function_calls)) {
5382
5383       if(isCALL(pc)) {
5384         pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5385         if(pcn && isPCF(pcn)) {
5386           PCF(pcn)->ncalled++;
5387         }
5388       } else
5389         fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5390
5391     }
5392   }
5393
5394   //fprintf(stderr,"inlining %d\n",__LINE__);
5395
5396   /* Now, Loop through the function definitions again, but this
5397    * time inline those functions that have only been called once. */
5398   
5399   InlineFunction(the_pFile->pbHead);
5400   //fprintf(stderr,"inlining %d\n",__LINE__);
5401
5402   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5403     unBuildFlow(pb);
5404
5405 }