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