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