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