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