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