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