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