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