Interrupt context registers WSAVE and SSAVE were not getting allocated.
[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))
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   return pcop;
2110 }
2111
2112 /*-----------------------------------------------------------------*
2113  * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2114  *
2115  * If rIdx >=0 then a specific register from the set of registers
2116  * will be selected. If rIdx <0, then a new register will be searched
2117  * for.
2118  *-----------------------------------------------------------------*/
2119
2120 pCodeOp *newpCodeOpReg(int rIdx)
2121 {
2122   pCodeOp *pcop;
2123
2124   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2125
2126   pcop->name = NULL;
2127
2128   if(rIdx >= 0) {
2129     PCOR(pcop)->rIdx = rIdx;
2130     PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2131   } else {
2132     PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2133
2134     if(PCOR(pcop)->r)
2135       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2136     //fprintf(stderr, "newpcodeOpReg - rIdx = %d\n", PCOR(pcop)->r->rIdx);
2137   }
2138
2139   pcop->type = PCOR(pcop)->r->pc_type;
2140
2141   return pcop;
2142 }
2143
2144 pCodeOp *newpCodeOpRegFromStr(char *name)
2145 {
2146   pCodeOp *pcop;
2147
2148   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2149   PCOR(pcop)->r = allocRegByName(name, 1);
2150   PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2151   pcop->type = PCOR(pcop)->r->pc_type;
2152   pcop->name = PCOR(pcop)->r->name;
2153
2154   return pcop;
2155 }
2156
2157 /*-----------------------------------------------------------------*/
2158 /*-----------------------------------------------------------------*/
2159
2160 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2161 {
2162   pCodeOp *pcop;
2163
2164   switch(type) {
2165   case PO_BIT:
2166   case PO_GPR_BIT:
2167     pcop = newpCodeOpBit(name, -1,0);
2168     break;
2169
2170   case PO_LITERAL:
2171     pcop = newpCodeOpLit(-1);
2172     break;
2173
2174   case PO_LABEL:
2175     pcop = newpCodeOpLabel(NULL,-1);
2176     break;
2177   case PO_GPR_TEMP:
2178     pcop = newpCodeOpReg(-1);
2179     break;
2180
2181   default:
2182     pcop = Safe_calloc(1,sizeof(pCodeOp) );
2183     pcop->type = type;
2184     if(name)
2185       pcop->name = Safe_strdup(name);   
2186     else
2187       pcop->name = NULL;
2188   }
2189
2190   return pcop;
2191 }
2192
2193 /*-----------------------------------------------------------------*/
2194 /*-----------------------------------------------------------------*/
2195 void pCodeConstString(char *name, char *value)
2196 {
2197   pBlock *pb;
2198
2199   //  fprintf(stderr, " %s  %s  %s\n",__FUNCTION__,name,value);
2200
2201   if(!name || !value)
2202     return;
2203
2204   pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2205
2206   addpBlock(pb);
2207
2208   sprintf(buffer,"; %s = %s",name,value);
2209   
2210   addpCode2pBlock(pb,newpCodeCharP(buffer));
2211   addpCode2pBlock(pb,newpCodeLabel(name,-1));
2212
2213   do {
2214     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2215   }while (*value++);
2216
2217
2218 }
2219
2220 /*-----------------------------------------------------------------*/
2221 /*-----------------------------------------------------------------*/
2222 void pCodeReadCodeTable(void)
2223 {
2224   pBlock *pb;
2225
2226   fprintf(stderr, " %s\n",__FUNCTION__);
2227
2228   pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2229
2230   addpBlock(pb);
2231
2232   addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2233   addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2234   addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2235   addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2236
2237   addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2238   addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2239   addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2240   addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2241
2242
2243 }
2244
2245 /*-----------------------------------------------------------------*/
2246 /* addpCode2pBlock - place the pCode into the pBlock linked list   */
2247 /*-----------------------------------------------------------------*/
2248 void addpCode2pBlock(pBlock *pb, pCode *pc)
2249 {
2250
2251   if(!pc)
2252     return;
2253
2254   if(!pb->pcHead) {
2255     /* If this is the first pcode to be added to a block that
2256      * was initialized with a NULL pcode, then go ahead and
2257      * make this pcode the head and tail */
2258     pb->pcHead  = pb->pcTail = pc;
2259   } else {
2260     //    if(pb->pcTail)
2261     pb->pcTail->next = pc;
2262
2263     pc->prev = pb->pcTail;
2264     pc->pb = pb;
2265
2266     pb->pcTail = pc;
2267   }
2268 }
2269
2270 /*-----------------------------------------------------------------*/
2271 /* addpBlock - place a pBlock into the pFile                       */
2272 /*-----------------------------------------------------------------*/
2273 void addpBlock(pBlock *pb)
2274 {
2275   // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2276
2277   if(!the_pFile) {
2278     /* First time called, we'll pass through here. */
2279     //_ALLOC(the_pFile,sizeof(pFile));
2280     the_pFile = Safe_calloc(1,sizeof(pFile));
2281     the_pFile->pbHead = the_pFile->pbTail = pb;
2282     the_pFile->functions = NULL;
2283     return;
2284   }
2285
2286   the_pFile->pbTail->next = pb;
2287   pb->prev = the_pFile->pbTail;
2288   pb->next = NULL;
2289   the_pFile->pbTail = pb;
2290 }
2291
2292 /*-----------------------------------------------------------------*/
2293 /* removepBlock - remove a pBlock from the pFile                   */
2294 /*-----------------------------------------------------------------*/
2295 void removepBlock(pBlock *pb)
2296 {
2297   pBlock *pbs;
2298
2299   if(!the_pFile)
2300     return;
2301
2302
2303   //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2304
2305   for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2306     if(pbs == pb) {
2307
2308       if(pbs == the_pFile->pbHead)
2309         the_pFile->pbHead = pbs->next;
2310
2311       if (pbs == the_pFile->pbTail) 
2312         the_pFile->pbTail = pbs->prev;
2313
2314       if(pbs->next)
2315         pbs->next->prev = pbs->prev;
2316
2317       if(pbs->prev)
2318         pbs->prev->next = pbs->next;
2319
2320       return;
2321
2322     }
2323   }
2324
2325   fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2326
2327 }
2328
2329 /*-----------------------------------------------------------------*/
2330 /* printpCode - write the contents of a pCode to a file            */
2331 /*-----------------------------------------------------------------*/
2332 void printpCode(FILE *of, pCode *pc)
2333 {
2334
2335   if(!pc || !of)
2336     return;
2337
2338   if(pc->print) {
2339     pc->print(of,pc);
2340     return;
2341   }
2342
2343   fprintf(of,"warning - unable to print pCode\n");
2344 }
2345
2346 /*-----------------------------------------------------------------*/
2347 /* printpBlock - write the contents of a pBlock to a file          */
2348 /*-----------------------------------------------------------------*/
2349 void printpBlock(FILE *of, pBlock *pb)
2350 {
2351   pCode *pc;
2352
2353   if(!pb)
2354     return;
2355
2356   if(!of)
2357     of = stderr;
2358
2359   for(pc = pb->pcHead; pc; pc = pc->next)
2360     printpCode(of,pc);
2361
2362 }
2363
2364 /*-----------------------------------------------------------------*/
2365 /*                                                                 */
2366 /*       pCode processing                                          */
2367 /*                                                                 */
2368 /*                                                                 */
2369 /*                                                                 */
2370 /*-----------------------------------------------------------------*/
2371
2372 void unlinkpCode(pCode *pc)
2373 {
2374
2375
2376   if(pc) {
2377 #ifdef PCODE_DEBUG
2378     fprintf(stderr,"Unlinking: ");
2379     printpCode(stderr, pc);
2380 #endif
2381     if(pc->prev) 
2382       pc->prev->next = pc->next;
2383     if(pc->next)
2384       pc->next->prev = pc->prev;
2385
2386     pc->prev = pc->next = NULL;
2387   }
2388 }
2389
2390 /*-----------------------------------------------------------------*/
2391 /*-----------------------------------------------------------------*/
2392
2393 static void genericDestruct(pCode *pc)
2394 {
2395
2396   unlinkpCode(pc);
2397
2398   if(isPCI(pc)) {
2399     /* For instructions, tell the register (if there's one used)
2400      * that it's no longer needed */
2401     regs *reg = getRegFromInstruction(pc);
2402     if(reg)
2403       deleteSetItem (&(reg->reglives.usedpCodes),pc);
2404   }
2405
2406   /* Instead of deleting the memory used by this pCode, mark
2407    * the object as bad so that if there's a pointer to this pCode
2408    * dangling around somewhere then (hopefully) when the type is
2409    * checked we'll catch it.
2410    */
2411
2412   pc->type = PC_BAD;
2413
2414   addpCode2pBlock(pb_dead_pcodes, pc);
2415
2416   //free(pc);
2417
2418 }
2419
2420
2421 /*-----------------------------------------------------------------*/
2422 /*-----------------------------------------------------------------*/
2423 void pBlockRegs(FILE *of, pBlock *pb)
2424 {
2425
2426   regs  *r;
2427
2428   r = setFirstItem(pb->tregisters);
2429   while (r) {
2430     r = setNextItem(pb->tregisters);
2431   }
2432 }
2433
2434
2435 /*-----------------------------------------------------------------*/
2436 /*-----------------------------------------------------------------*/
2437 char *get_op(pCodeOp *pcop,char *buffer, int size)
2438 {
2439   regs *r;
2440   static char b[50];
2441   char *s;
2442   int use_buffer = 1;    // copy the string to the passed buffer pointer
2443
2444   if(!buffer) {
2445     buffer = b;
2446     size = sizeof(b);
2447     use_buffer = 0;     // Don't bother copying the string to the buffer.
2448   } 
2449
2450   if(pcop) {
2451     switch(pcop->type) {
2452     case PO_INDF:
2453     case PO_FSR:
2454       if(use_buffer) {
2455         SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2456         return buffer;
2457       }
2458       return PCOR(pcop)->r->name;
2459       break;
2460     case PO_GPR_TEMP:
2461       r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2462
2463       if(use_buffer) {
2464         SAFE_snprintf(&buffer,&size,"%s",r->name);
2465         return buffer;
2466       }
2467
2468       return r->name;
2469
2470
2471     case PO_IMMEDIATE:
2472       s = buffer;
2473
2474       if(PCOI(pcop)->_const) {
2475
2476         if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2477           SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2478                         pcop->name,
2479                         PCOI(pcop)->index,
2480                         8 * PCOI(pcop)->offset );
2481         } else
2482           SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2483       } else {
2484       
2485         if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2486           SAFE_snprintf(&s,&size,"(%s + %d)",
2487                         pcop->name,
2488                         PCOI(pcop)->index );
2489         } else
2490           SAFE_snprintf(&s,&size,"%s",pcop->name);
2491       }
2492
2493       return buffer;
2494
2495     case PO_DIR:
2496       s = buffer;
2497       //size = sizeof(buffer);
2498       if( PCOR(pcop)->instance) {
2499         SAFE_snprintf(&s,&size,"(%s + %d)",
2500                       pcop->name,
2501                       PCOR(pcop)->instance );
2502         //fprintf(stderr,"PO_DIR %s\n",buffer);
2503       } else
2504         SAFE_snprintf(&s,&size,"%s",pcop->name);
2505       return buffer;
2506
2507     default:
2508       if  (pcop->name) {
2509         if(use_buffer) {
2510           SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2511           return buffer;
2512         }
2513         return pcop->name;
2514       }
2515
2516     }
2517   }
2518
2519   return "NO operand";
2520
2521 }
2522
2523 /*-----------------------------------------------------------------*/
2524 /*-----------------------------------------------------------------*/
2525 static char *get_op_from_instruction( pCodeInstruction *pcc)
2526 {
2527
2528   if(pcc )
2529     return get_op(pcc->pcop,NULL,0);
2530   
2531   return ("ERROR Null: "__FUNCTION__);
2532
2533 }
2534
2535 /*-----------------------------------------------------------------*/
2536 /*-----------------------------------------------------------------*/
2537 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2538 {
2539
2540   fprintf(of,"pcodeopprint- not implemented\n");
2541 }
2542
2543 /*-----------------------------------------------------------------*/
2544 /*-----------------------------------------------------------------*/
2545 char *pCode2str(char *str, int size, pCode *pc)
2546 {
2547   char *s = str;
2548
2549   switch(pc->type) {
2550
2551   case PC_OPCODE:
2552
2553     SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2554
2555     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2556
2557       if(PCI(pc)->isBitInst) {
2558         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2559           if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2560             SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
2561                           PCI(pc)->pcop->name ,
2562                           PCI(pc)->pcop->name );
2563           else
2564             SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)), 
2565                           (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2566         } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2567           SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2568         }else
2569           SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
2570         //PCI(pc)->pcop->t.bit );
2571       } else {
2572
2573         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2574           if( PCI(pc)->num_ops == 2)
2575             SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2576           else
2577             SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
2578
2579         }else {
2580           SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
2581
2582           if( PCI(pc)->num_ops == 2)
2583             SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2584         }
2585       }
2586
2587     }
2588     break;
2589
2590   case PC_COMMENT:
2591     /* assuming that comment ends with a \n */
2592     SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2593     break;
2594
2595   case PC_INLINE:
2596     /* assuming that inline code ends with a \n */
2597     SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
2598     break;
2599
2600   case PC_LABEL:
2601     SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2602     break;
2603   case PC_FUNCTION:
2604     SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2605     break;
2606   case PC_WILD:
2607     SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2608     break;
2609   case PC_FLOW:
2610     SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2611     break;
2612   case PC_CSOURCE:
2613     SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2614     break;
2615
2616   case PC_BAD:
2617     SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
2618   }
2619
2620   return str;
2621
2622 }
2623
2624 /*-----------------------------------------------------------------*/
2625 /* genericPrint - the contents of a pCode to a file                */
2626 /*-----------------------------------------------------------------*/
2627 static void genericPrint(FILE *of, pCode *pc)
2628 {
2629
2630   if(!pc || !of)
2631     return;
2632
2633   switch(pc->type) {
2634   case PC_COMMENT:
2635     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2636     break;
2637
2638   case PC_INLINE:
2639     fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
2640      break;
2641
2642   case PC_OPCODE:
2643     // If the opcode has a label, print that first
2644     {
2645       pBranch *pbl = PCI(pc)->label;
2646       while(pbl && pbl->pc) {
2647         if(pbl->pc->type == PC_LABEL)
2648           pCodePrintLabel(of, pbl->pc);
2649         pbl = pbl->next;
2650       }
2651     }
2652
2653     if(PCI(pc)->cline) 
2654       genericPrint(of,PCODE(PCI(pc)->cline));
2655
2656     {
2657       char str[256];
2658       
2659       pCode2str(str, 256, pc);
2660
2661       fprintf(of,"%s",str);
2662
2663       /* Debug */
2664       if(debug_verbose) {
2665         fprintf(of, "\t;key=%03x",pc->seq);
2666         if(PCI(pc)->pcflow)
2667           fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2668       }
2669     }
2670 #if 0
2671     {
2672       pBranch *dpb = pc->to;   // debug
2673       while(dpb) {
2674         switch ( dpb->pc->type) {
2675         case PC_OPCODE:
2676           fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2677           break;
2678         case PC_LABEL:
2679           fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2680           break;
2681         case PC_FUNCTION:
2682           fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2683           break;
2684         case PC_FLOW:
2685           fprintf(of, "\t;flow");
2686           break;
2687         case PC_COMMENT:
2688         case PC_WILD:
2689           break;
2690         }
2691         dpb = dpb->next;
2692       }
2693     }
2694 #endif
2695     fprintf(of,"\n");
2696     break;
2697
2698   case PC_WILD:
2699     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2700     if(PCW(pc)->pci.label)
2701       pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2702
2703     if(PCW(pc)->operand) {
2704       fprintf(of,";\toperand  ");
2705       pCodeOpPrint(of,PCW(pc)->operand );
2706     }
2707     break;
2708
2709   case PC_FLOW:
2710     if(debug_verbose) {
2711       fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
2712       if(PCFL(pc)->ancestor)
2713         fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
2714       fprintf(of,"\n");
2715
2716     }
2717     break;
2718
2719   case PC_CSOURCE:
2720     fprintf(of,";#CSRC\t%s %d\n;  %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
2721     break;
2722   case PC_LABEL:
2723   default:
2724     fprintf(of,"unknown pCode type %d\n",pc->type);
2725   }
2726
2727 }
2728
2729 /*-----------------------------------------------------------------*/
2730 /* pCodePrintFunction - prints function begin/end                  */
2731 /*-----------------------------------------------------------------*/
2732
2733 static void pCodePrintFunction(FILE *of, pCode *pc)
2734 {
2735
2736   if(!pc || !of)
2737     return;
2738
2739   if( ((pCodeFunction *)pc)->modname) 
2740     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2741
2742   if(PCF(pc)->fname) {
2743     pBranch *exits = PCF(pc)->to;
2744     int i=0;
2745     fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2746     while(exits) {
2747       i++;
2748       exits = exits->next;
2749     }
2750     //if(i) i--;
2751     fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2752     
2753   }else {
2754     if((PCF(pc)->from && 
2755         PCF(pc)->from->pc->type == PC_FUNCTION &&
2756         PCF(PCF(pc)->from->pc)->fname) )
2757       fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2758     else
2759       fprintf(of,"; exit point [can't find entry point]\n");
2760   }
2761 }
2762 /*-----------------------------------------------------------------*/
2763 /* pCodePrintLabel - prints label                                  */
2764 /*-----------------------------------------------------------------*/
2765
2766 static void pCodePrintLabel(FILE *of, pCode *pc)
2767 {
2768
2769   if(!pc || !of)
2770     return;
2771
2772   if(PCL(pc)->label) 
2773     fprintf(of,"%s\n",PCL(pc)->label);
2774   else if (PCL(pc)->key >=0) 
2775     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2776   else
2777     fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2778
2779 }
2780 /*-----------------------------------------------------------------*/
2781 /* unlinkpCodeFromBranch - Search for a label in a pBranch and     */
2782 /*                         remove it if it is found.               */
2783 /*-----------------------------------------------------------------*/
2784 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2785 {
2786   pBranch *b, *bprev;
2787
2788
2789   bprev = NULL;
2790
2791   if(pcl->type == PC_OPCODE)
2792     b = PCI(pcl)->label;
2793   else {
2794     fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2795     exit(1);
2796
2797   }
2798
2799   //fprintf (stderr, "%s \n",__FUNCTION__);
2800   //pcl->print(stderr,pcl);
2801   //pc->print(stderr,pc);
2802   while(b) {
2803     if(b->pc == pc) {
2804       //fprintf (stderr, "found label\n");
2805
2806       /* Found a label */
2807       if(bprev) {
2808         bprev->next = b->next;  /* Not first pCode in chain */
2809         free(b);
2810       } else {
2811         pc->destruct(pc);
2812         PCI(pcl)->label = b->next;   /* First pCode in chain */
2813         free(b);
2814       }
2815       return;  /* A label can't occur more than once */
2816     }
2817     bprev = b;
2818     b = b->next;
2819   }
2820
2821 }
2822
2823 /*-----------------------------------------------------------------*/
2824 /*-----------------------------------------------------------------*/
2825 pBranch * pBranchAppend(pBranch *h, pBranch *n)
2826 {
2827   pBranch *b;
2828
2829   if(!h)
2830     return n;
2831
2832   if(h == n)
2833     return n;
2834
2835   b = h;
2836   while(b->next)
2837     b = b->next;
2838
2839   b->next = n;
2840
2841   return h;
2842   
2843 }  
2844 /*-----------------------------------------------------------------*/
2845 /* pBranchLink - given two pcodes, this function will link them    */
2846 /*               together through their pBranches                  */
2847 /*-----------------------------------------------------------------*/
2848 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2849 {
2850   pBranch *b;
2851
2852   // Declare a new branch object for the 'from' pCode.
2853
2854   //_ALLOC(b,sizeof(pBranch));
2855   b = Safe_calloc(1,sizeof(pBranch));
2856   b->pc = PCODE(t);             // The link to the 'to' pCode.
2857   b->next = NULL;
2858
2859   f->to = pBranchAppend(f->to,b);
2860
2861   // Now do the same for the 'to' pCode.
2862
2863   //_ALLOC(b,sizeof(pBranch));
2864   b = Safe_calloc(1,sizeof(pBranch));
2865   b->pc = PCODE(f);
2866   b->next = NULL;
2867
2868   t->from = pBranchAppend(t->from,b);
2869   
2870 }
2871
2872 #if 0
2873 /*-----------------------------------------------------------------*/
2874 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2875 /*               a pCode                                           */
2876 /*-----------------------------------------------------------------*/
2877 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2878 {
2879   while(pb) {
2880
2881     if(pb->pc == pc)
2882       return pb;
2883
2884     pb = pb->next;
2885   }
2886
2887   return NULL;
2888 }
2889
2890 /*-----------------------------------------------------------------*/
2891 /* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
2892 /*-----------------------------------------------------------------*/
2893 static void pCodeUnlink(pCode *pc)
2894 {
2895   pBranch *pb1,*pb2;
2896   pCode *pc1;
2897
2898   if(!pc->prev || !pc->next) {
2899     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2900     exit(1);
2901   }
2902
2903   /* first remove the pCode from the chain */
2904   pc->prev->next = pc->next;
2905   pc->next->prev = pc->prev;
2906
2907   /* Now for the hard part... */
2908
2909   /* Remove the branches */
2910
2911   pb1 = pc->from;
2912   while(pb1) {
2913     pc1 = pb1->pc;    /* Get the pCode that branches to the
2914                        * one we're unlinking */
2915
2916     /* search for the link back to this pCode (the one we're
2917      * unlinking) */
2918     if(pb2 = pBranchFind(pc1->to,pc)) {
2919       pb2->pc = pc->to->pc;  // make the replacement
2920
2921       /* if the pCode we're unlinking contains multiple 'to'
2922        * branches (e.g. this a skip instruction) then we need
2923        * to copy these extra branches to the chain. */
2924       if(pc->to->next)
2925         pBranchAppend(pb2, pc->to->next);
2926     }
2927     
2928     pb1 = pb1->next;
2929   }
2930
2931
2932 }
2933 #endif
2934 /*-----------------------------------------------------------------*/
2935 /*-----------------------------------------------------------------*/
2936 #if 0
2937 static void genericAnalyze(pCode *pc)
2938 {
2939   switch(pc->type) {
2940   case PC_WILD:
2941   case PC_COMMENT:
2942     return;
2943   case PC_LABEL:
2944   case PC_FUNCTION:
2945   case PC_OPCODE:
2946     {
2947       // Go through the pCodes that are in pCode chain and link
2948       // them together through the pBranches. Note, the pCodes
2949       // are linked together as a contiguous stream like the 
2950       // assembly source code lines. The linking here mimics this
2951       // except that comments are not linked in.
2952       // 
2953       pCode *npc = pc->next;
2954       while(npc) {
2955         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2956           pBranchLink(pc,npc);
2957           return;
2958         } else
2959           npc = npc->next;
2960       }
2961       /* reached the end of the pcode chain without finding
2962        * an instruction we could link to. */
2963     }
2964     break;
2965   case PC_FLOW:
2966     fprintf(stderr,"analyze PC_FLOW\n");
2967
2968     return;
2969   case PC_BAD:
2970     fprintf(stderr,,";A bad pCode is being used\n");
2971
2972   }
2973 }
2974 #endif
2975
2976 /*-----------------------------------------------------------------*/
2977 /*-----------------------------------------------------------------*/
2978 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2979 {
2980   pBranch *pbr;
2981
2982   if(pc->type == PC_LABEL) {
2983     if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
2984       return TRUE;
2985   }
2986   if(pc->type == PC_OPCODE) {
2987     pbr = PCI(pc)->label;
2988     while(pbr) {
2989       if(pbr->pc->type == PC_LABEL) {
2990         if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
2991           return TRUE;
2992       }
2993       pbr = pbr->next;
2994     }
2995   }
2996
2997   return FALSE;
2998 }
2999
3000 /*-----------------------------------------------------------------*/
3001 /*-----------------------------------------------------------------*/
3002 int checkLabel(pCode *pc)
3003 {
3004   pBranch *pbr;
3005
3006   if(pc && isPCI(pc)) {
3007     pbr = PCI(pc)->label;
3008     while(pbr) {
3009       if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3010         return TRUE;
3011
3012       pbr = pbr->next;
3013     }
3014   }
3015
3016   return FALSE;
3017 }
3018
3019 /*-----------------------------------------------------------------*/
3020 /* findLabelinpBlock - Search the pCode for a particular label     */
3021 /*-----------------------------------------------------------------*/
3022 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3023 {
3024   pCode  *pc;
3025
3026   if(!pb)
3027     return NULL;
3028
3029   for(pc = pb->pcHead; pc; pc = pc->next) 
3030     if(compareLabel(pc,pcop_label))
3031       return pc;
3032     
3033   return NULL;
3034 }
3035
3036 /*-----------------------------------------------------------------*/
3037 /* findLabel - Search the pCode for a particular label             */
3038 /*-----------------------------------------------------------------*/
3039 pCode * findLabel(pCodeOpLabel *pcop_label)
3040 {
3041   pBlock *pb;
3042   pCode  *pc;
3043
3044   if(!the_pFile)
3045     return NULL;
3046
3047   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3048     if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3049       return pc;
3050   }
3051
3052   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3053   return NULL;
3054 }
3055
3056 /*-----------------------------------------------------------------*/
3057 /* findNextpCode - given a pCode, find the next of type 'pct'      */
3058 /*                 in the linked list                              */
3059 /*-----------------------------------------------------------------*/
3060 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3061 {
3062
3063   while(pc) {
3064     if(pc->type == pct)
3065       return pc;
3066
3067     pc = pc->next;
3068   }
3069
3070   return NULL;
3071 }
3072
3073 /*-----------------------------------------------------------------*/
3074 /* findPrevpCode - given a pCode, find the previous of type 'pct'  */
3075 /*                 in the linked list                              */
3076 /*-----------------------------------------------------------------*/
3077 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3078 {
3079
3080   while(pc) {
3081     if(pc->type == pct)
3082       return pc;
3083
3084     pc = pc->prev;
3085   }
3086
3087   return NULL;
3088 }
3089 /*-----------------------------------------------------------------*/
3090 /* findNextInstruction - given a pCode, find the next instruction  */
3091 /*                       in the linked list                        */
3092 /*-----------------------------------------------------------------*/
3093 pCode * findNextInstruction(pCode *pci)
3094 {
3095   pCode *pc = pci;
3096
3097   while(pc) {
3098     if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3099       return pc;
3100
3101 #ifdef PCODE_DEBUG
3102     fprintf(stderr,"findNextInstruction:  ");
3103     printpCode(stderr, pc);
3104 #endif
3105     pc = pc->next;
3106   }
3107
3108   //fprintf(stderr,"Couldn't find instruction\n");
3109   return NULL;
3110 }
3111
3112 /*-----------------------------------------------------------------*/
3113 /* findNextInstruction - given a pCode, find the next instruction  */
3114 /*                       in the linked list                        */
3115 /*-----------------------------------------------------------------*/
3116 pCode * findPrevInstruction(pCode *pci)
3117 {
3118   return findPrevpCode(pci, PC_OPCODE);
3119 }
3120
3121 /*-----------------------------------------------------------------*/
3122 /* findFunctionEnd - given a pCode find the end of the function    */
3123 /*                   that contains it                              */
3124 /*-----------------------------------------------------------------*/
3125 pCode * findFunctionEnd(pCode *pc)
3126 {
3127
3128   while(pc) {
3129     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
3130       return pc;
3131
3132     pc = pc->next;
3133   }
3134
3135   fprintf(stderr,"Couldn't find function end\n");
3136   return NULL;
3137 }
3138
3139 #if 0
3140 /*-----------------------------------------------------------------*/
3141 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
3142 /*                instruction with which it is associated.         */
3143 /*-----------------------------------------------------------------*/
3144 static void AnalyzeLabel(pCode *pc)
3145 {
3146
3147   pCodeUnlink(pc);
3148
3149 }
3150 #endif
3151
3152 #if 0
3153 static void AnalyzeGOTO(pCode *pc)
3154 {
3155
3156   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3157
3158 }
3159
3160 static void AnalyzeSKIP(pCode *pc)
3161 {
3162
3163   pBranchLink(pc,findNextInstruction(pc->next));
3164   pBranchLink(pc,findNextInstruction(pc->next->next));
3165
3166 }
3167
3168 static void AnalyzeRETURN(pCode *pc)
3169 {
3170
3171   //  branch_link(pc,findFunctionEnd(pc->next));
3172
3173 }
3174
3175 #endif
3176
3177 /*-----------------------------------------------------------------*/
3178 /*-----------------------------------------------------------------*/
3179 regs * getRegFromInstruction(pCode *pc)
3180 {
3181
3182   if(!pc                   || 
3183      !isPCI(pc)            ||
3184      !PCI(pc)->pcop        ||
3185      PCI(pc)->num_ops == 0 )
3186     return NULL;
3187
3188   switch(PCI(pc)->pcop->type) {
3189   case PO_INDF:
3190   case PO_FSR:
3191     return PCOR(PCI(pc)->pcop)->r;
3192
3193     //    return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3194
3195   case PO_BIT:
3196   case PO_GPR_TEMP:
3197     //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3198     return PCOR(PCI(pc)->pcop)->r;
3199
3200   case PO_IMMEDIATE:
3201     if(PCOI(PCI(pc)->pcop)->r)
3202       return (PCOI(PCI(pc)->pcop)->r);
3203
3204     //fprintf(stderr, "getRegFromInstruction - immediate\n");
3205     return dirregWithName(PCI(pc)->pcop->name);
3206     //return NULL; // PCOR(PCI(pc)->pcop)->r;
3207
3208   case PO_GPR_BIT:
3209     return PCOR(PCI(pc)->pcop)->r;
3210
3211   case PO_DIR:
3212     //fprintf(stderr, "getRegFromInstruction - dir\n");
3213     return PCOR(PCI(pc)->pcop)->r;
3214   case PO_LITERAL:
3215     //fprintf(stderr, "getRegFromInstruction - literal\n");
3216     break;
3217
3218   default:
3219     //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3220     //genericPrint(stderr, pc);
3221     break;
3222   }
3223
3224   return NULL;
3225
3226 }
3227
3228 /*-----------------------------------------------------------------*/
3229 /*-----------------------------------------------------------------*/
3230
3231 void AnalyzepBlock(pBlock *pb)
3232 {
3233   pCode *pc;
3234
3235   if(!pb)
3236     return;
3237
3238   /* Find all of the registers used in this pBlock 
3239    * by looking at each instruction and examining it's
3240    * operands
3241    */
3242   for(pc = pb->pcHead; pc; pc = pc->next) {
3243
3244     /* Is this an instruction with operands? */
3245     if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3246
3247       if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
3248
3249         /* Loop through all of the registers declared so far in
3250            this block and see if we find this one there */
3251
3252         regs *r = setFirstItem(pb->tregisters);
3253
3254         while(r) {
3255           if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
3256             PCOR(PCI(pc)->pcop)->r = r;
3257             break;
3258           }
3259           r = setNextItem(pb->tregisters);
3260         }
3261
3262         if(!r) {
3263           /* register wasn't found */
3264           //r = Safe_calloc(1, sizeof(regs));
3265           //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3266           //addSet(&pb->tregisters, r);
3267           addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3268           //PCOR(PCI(pc)->pcop)->r = r;
3269           //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3270         }/* else 
3271           fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3272          */
3273       }
3274       if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3275         if(PCOR(PCI(pc)->pcop)->r) {
3276           pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3277           DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3278         } else {
3279           if(PCI(pc)->pcop->name)
3280             fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3281           else
3282             fprintf(stderr,"ERROR: NULL register\n");
3283         }
3284       }
3285     }
3286
3287
3288   }
3289 }
3290
3291 /*-----------------------------------------------------------------*/
3292 /* */
3293 /*-----------------------------------------------------------------*/
3294 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
3295
3296 void InsertpFlow(pCode *pc, pCode **pflow)
3297 {
3298   if(*pflow)
3299     PCFL(*pflow)->end = pc;
3300
3301   if(!pc || !pc->next)
3302     return;
3303
3304   *pflow = newpCodeFlow();
3305   pCodeInsertAfter(pc, *pflow);
3306 }
3307
3308 /*-----------------------------------------------------------------*/
3309 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
3310 /*                         the flow blocks.                        */
3311 /*
3312  * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3313  * point the instruction flow changes. 
3314  */
3315 /*-----------------------------------------------------------------*/
3316 void BuildFlow(pBlock *pb)
3317 {
3318   pCode *pc;
3319   pCode *last_pci=NULL;
3320   pCode *pflow=NULL;
3321   int seq = 0;
3322
3323   if(!pb)
3324     return;
3325
3326   //fprintf (stderr,"build flow start seq %d  ",GpcFlowSeq);
3327   /* Insert a pCodeFlow object at the beginning of a pBlock */
3328
3329   InsertpFlow(pb->pcHead, &pflow);
3330
3331   //pflow = newpCodeFlow();    /* Create a new Flow object */
3332   //pflow->next = pb->pcHead;  /* Make the current head the next object */
3333   //pb->pcHead->prev = pflow;  /* let the current head point back to the flow object */
3334   //pb->pcHead = pflow;        /* Make the Flow object the head */
3335   //pflow->pb = pb;
3336
3337   for( pc = findNextInstruction(pb->pcHead);
3338        pc != NULL;
3339        pc=findNextInstruction(pc)) { 
3340
3341     pc->seq = seq++;
3342     PCI(pc)->pcflow = PCFL(pflow);
3343
3344     //fprintf(stderr," build: ");
3345     //pflow->print(stderr,pflow);
3346
3347     if( PCI(pc)->isSkip) {
3348
3349       /* The two instructions immediately following this one 
3350        * mark the beginning of a new flow segment */
3351
3352       while(pc && PCI(pc)->isSkip) {
3353
3354         PCI(pc)->pcflow = PCFL(pflow);
3355         pc->seq = seq-1;
3356         seq = 1;
3357
3358         InsertpFlow(pc, &pflow);
3359         pc=findNextInstruction(pc->next);
3360       }
3361
3362       seq = 0;
3363
3364       if(!pc)
3365         break;
3366
3367       PCI(pc)->pcflow = PCFL(pflow);
3368       pc->seq = 0;
3369       InsertpFlow(pc, &pflow);
3370
3371     } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next)))  {
3372
3373       InsertpFlow(pc, &pflow);
3374       seq = 0;
3375
3376     } else if (checkLabel(pc)) { 
3377
3378       /* This instruction marks the beginning of a
3379        * new flow segment */
3380
3381       pc->seq = 0;
3382       seq = 1;
3383
3384       /* If the previous pCode is not a flow object, then 
3385        * insert a new flow object. (This check prevents 
3386        * two consecutive flow objects from being insert in
3387        * the case where a skip instruction preceeds an
3388        * instruction containing a label.) */
3389
3390       if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3391         InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3392
3393       PCI(pc)->pcflow = PCFL(pflow);
3394       
3395     }
3396     last_pci = pc;
3397     pc = pc->next;
3398   }
3399
3400   //fprintf (stderr,",end seq %d",GpcFlowSeq);
3401   if(pflow)
3402     PCFL(pflow)->end = pb->pcTail;
3403 }
3404
3405 /*-------------------------------------------------------------------*/
3406 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
3407 /*                           the flow blocks.                        */
3408 /*
3409  * unBuildFlow removes pCodeFlow objects from a pCode chain
3410  */
3411 /*-----------------------------------------------------------------*/
3412 void unBuildFlow(pBlock *pb)
3413 {
3414   pCode *pc,*pcnext;
3415
3416   if(!pb)
3417     return;
3418
3419   pc = pb->pcHead;
3420
3421   while(pc) {
3422     pcnext = pc->next;
3423
3424     if(isPCI(pc)) {
3425
3426       pc->seq = 0;
3427       if(PCI(pc)->pcflow) {
3428         //free(PCI(pc)->pcflow);
3429         PCI(pc)->pcflow = NULL;
3430       }
3431
3432     } else if(isPCFL(pc) )
3433       pc->destruct(pc);
3434
3435     pc = pcnext;
3436   }
3437
3438
3439 }
3440
3441 /*-----------------------------------------------------------------*/
3442 /*-----------------------------------------------------------------*/
3443 void dumpCond(int cond)
3444 {
3445
3446   static char *pcc_str[] = {
3447     //"PCC_NONE",
3448     "PCC_REGISTER",
3449     "PCC_C",
3450     "PCC_Z",
3451     "PCC_DC",
3452     "PCC_W",
3453     "PCC_EXAMINE_PCOP",
3454     "PCC_REG_BANK0",
3455     "PCC_REG_BANK1",
3456     "PCC_REG_BANK2",
3457     "PCC_REG_BANK3"
3458   };
3459
3460   int ncond = sizeof(pcc_str) / sizeof(char *);
3461   int i,j;
3462
3463   fprintf(stderr, "0x%04X\n",cond);
3464
3465   for(i=0,j=1; i<ncond; i++, j<<=1)
3466     if(cond & j)
3467       fprintf(stderr, "  %s\n",pcc_str[i]);
3468
3469 }
3470
3471 /*-----------------------------------------------------------------*/
3472 /*-----------------------------------------------------------------*/
3473 void FlowStats(pCodeFlow *pcflow)
3474 {
3475
3476   pCode *pc;
3477
3478   if(!isPCFL(pcflow))
3479     return;
3480
3481   fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3482
3483   pc = findNextpCode(PCODE(pcflow), PC_OPCODE); 
3484
3485   if(!pc) {
3486     fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3487     return;
3488   }
3489
3490
3491   fprintf(stderr, "  FlowStats inCond: ");
3492   dumpCond(pcflow->inCond);
3493   fprintf(stderr, "  FlowStats outCond: ");
3494   dumpCond(pcflow->outCond);
3495
3496 }
3497
3498 /*-----------------------------------------------------------------*
3499  * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3500  *    if it affects the banking bits. 
3501  * 
3502  * return: -1 == Banking bits are unaffected by this pCode.
3503  *
3504  * return: > 0 == Banking bits are affected.
3505  *
3506  *  If the banking bits are affected, then the returned value describes
3507  * which bits are affected and how they're affected. The lower half
3508  * of the integer maps to the bits that are affected, the upper half
3509  * to whether they're set or cleared.
3510  *
3511  *-----------------------------------------------------------------*/
3512 #define SET_BANK_BIT (1 << 16)
3513 #define CLR_BANK_BIT 0
3514
3515 int isBankInstruction(pCode *pc)
3516 {
3517   regs *reg;
3518   int bank = -1;
3519
3520   if(!isPCI(pc))
3521     return -1;
3522
3523   if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
3524
3525     /* Check to see if the register banks are changing */
3526     if(PCI(pc)->isModReg) {
3527
3528       pCodeOp *pcop = PCI(pc)->pcop;
3529       switch(PCI(pc)->op) {
3530
3531       case POC_BSF:
3532         if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3533           //fprintf(stderr, "  isBankInstruction - Set RP0\n");
3534           return  SET_BANK_BIT | PIC_RP0_BIT;
3535         }
3536
3537         if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3538           //fprintf(stderr, "  isBankInstruction - Set RP1\n");
3539           return  CLR_BANK_BIT | PIC_RP0_BIT;
3540         }
3541         break;
3542
3543       case POC_BCF:
3544         if(PCORB(pcop)->bit == PIC_RP0_BIT) {
3545           //fprintf(stderr, "  isBankInstruction - Clr RP0\n");
3546           return  CLR_BANK_BIT | PIC_RP1_BIT;
3547         }
3548         if(PCORB(pcop)->bit == PIC_RP1_BIT) {
3549           //fprintf(stderr, "  isBankInstruction - Clr RP1\n");
3550           return  CLR_BANK_BIT | PIC_RP1_BIT;
3551         }
3552         break;
3553       default:
3554         //fprintf(stderr, "  isBankInstruction - Status register is getting Modified by:\n");
3555         //genericPrint(stderr, pc);
3556         ;
3557       }
3558     }
3559
3560   }
3561
3562   return bank;
3563 }
3564
3565
3566 /*-----------------------------------------------------------------*/
3567 /*-----------------------------------------------------------------*/
3568 void FillFlow(pCodeFlow *pcflow)
3569 {
3570
3571   pCode *pc;
3572   int cur_bank;
3573
3574   if(!isPCFL(pcflow))
3575     return;
3576
3577   //  fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
3578
3579   pc = findNextpCode(PCODE(pcflow), PC_OPCODE); 
3580
3581   if(!pc) {
3582     //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
3583     return;
3584   }
3585
3586   cur_bank = -1;
3587
3588   do {
3589     isBankInstruction(pc);
3590     pc = pc->next;
3591   } while (pc && (pc != pcflow->end) && !isPCFL(pc));
3592
3593 /*
3594   if(!pc ) {
3595     fprintf(stderr, "  FillFlow - Bad end of flow\n");
3596   } else {
3597     fprintf(stderr, "  FillFlow - Ending flow with\n  ");
3598     pc->print(stderr,pc);
3599   }
3600
3601   fprintf(stderr, "  FillFlow inCond: ");
3602   dumpCond(pcflow->inCond);
3603   fprintf(stderr, "  FillFlow outCond: ");
3604   dumpCond(pcflow->outCond);
3605 */
3606 }
3607
3608 /*-----------------------------------------------------------------*/
3609 /*-----------------------------------------------------------------*/
3610 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
3611 {
3612   pCodeFlowLink *fromLink, *toLink;
3613
3614   if(!from || !to || !to->pcflow || !from->pcflow)
3615     return;
3616
3617   fromLink = newpCodeFlowLink(from->pcflow);
3618   toLink   = newpCodeFlowLink(to->pcflow);
3619
3620   addSetIfnotP(&(from->pcflow->to), toLink);   //to->pcflow);
3621   addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
3622
3623 }
3624
3625 /*-----------------------------------------------------------------*
3626  * void LinkFlow(pBlock *pb)
3627  *
3628  * In BuildFlow, the PIC code has been partitioned into contiguous
3629  * non-branching segments. In LinkFlow, we determine the execution
3630  * order of these segments. For example, if one of the segments ends
3631  * with a skip, then we know that there are two possible flow segments
3632  * to which control may be passed.
3633  *-----------------------------------------------------------------*/
3634 void LinkFlow(pBlock *pb)
3635 {
3636   pCode *pc=NULL;
3637   pCode *pcflow;
3638   pCode *pct;
3639
3640   //fprintf(stderr,"linkflow \n");
3641
3642   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
3643        pcflow != NULL;
3644        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3645
3646     if(!isPCFL(pcflow))
3647       fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
3648
3649     //fprintf(stderr," link: ");
3650     //pcflow->print(stderr,pcflow);
3651
3652     //FillFlow(PCFL(pcflow));
3653
3654     pc = PCFL(pcflow)->end;
3655
3656     //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
3657     if(isPCI_SKIP(pc)) {
3658       //fprintf(stderr, "ends with skip\n");
3659       //pc->print(stderr,pc);
3660       pct=findNextInstruction(pc->next);
3661       LinkFlow_pCode(PCI(pc),PCI(pct));
3662       pct=findNextInstruction(pct->next);
3663       LinkFlow_pCode(PCI(pc),PCI(pct));
3664       continue;
3665     }
3666
3667     if(isPCI_BRANCH(pc)) {
3668       pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
3669
3670       //fprintf(stderr, "ends with branch\n  ");
3671       //pc->print(stderr,pc);
3672
3673       if(!(pcol && isPCOLAB(pcol))) {
3674         if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
3675           pc->print(stderr,pc);
3676           fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
3677         }
3678         continue;
3679       }
3680
3681       if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
3682         LinkFlow_pCode(PCI(pc),PCI(pct));
3683       else
3684         fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__);
3685
3686       continue;
3687     }
3688
3689     if(isPCI(pc)) {
3690       //fprintf(stderr, "ends with non-branching instruction:\n");
3691       //pc->print(stderr,pc);
3692
3693       LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
3694
3695       continue;
3696     }
3697
3698     if(pc) {
3699       //fprintf(stderr, "ends with unknown\n");
3700       //pc->print(stderr,pc);
3701       continue;
3702     }
3703
3704     //fprintf(stderr, "ends with nothing: ERROR\n");
3705     
3706   }
3707 }
3708 /*-----------------------------------------------------------------*/
3709 /*-----------------------------------------------------------------*/
3710
3711 /*-----------------------------------------------------------------*/
3712 /*-----------------------------------------------------------------*/
3713 int isPCinFlow(pCode *pc, pCode *pcflow)
3714 {
3715
3716   if(!pc || !pcflow)
3717     return 0;
3718
3719   if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
3720     return 0;
3721
3722   if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
3723     return 1;
3724
3725   return 0;
3726 }
3727
3728 /*-----------------------------------------------------------------*/
3729 /*-----------------------------------------------------------------*/
3730 void BanksUsedFlow2(pCode *pcflow)
3731 {
3732   pCode *pc=NULL;
3733
3734   int bank = -1;
3735   bool RegUsed = 0;
3736
3737   regs *reg;
3738
3739   if(!isPCFL(pcflow)) {
3740     fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
3741     return;
3742   }
3743
3744   pc = findNextInstruction(pcflow->next);
3745
3746   PCFL(pcflow)->lastBank = -1;
3747
3748   while(isPCinFlow(pc,pcflow)) {
3749
3750     int bank_selected = isBankInstruction(pc);
3751
3752     //if(PCI(pc)->pcflow) 
3753     //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
3754
3755     if(bank_selected > 0) {
3756       //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
3757
3758       /* This instruction is modifying banking bits before accessing registers */
3759       if(!RegUsed)
3760         PCFL(pcflow)->firstBank = -1;
3761
3762       if(PCFL(pcflow)->lastBank == -1)
3763         PCFL(pcflow)->lastBank = 0;
3764
3765       bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
3766       if(bank_selected & SET_BANK_BIT)
3767         PCFL(pcflow)->lastBank |= bank;
3768                                  
3769
3770     } else { 
3771       reg = getRegFromInstruction(pc);
3772
3773       if(reg && !isREGinBank(reg, bank)) {
3774         int allbanks = REGallBanks(reg);
3775         if(bank == -1)
3776           PCFL(pcflow)->firstBank = allbanks;
3777
3778         PCFL(pcflow)->lastBank = allbanks;
3779
3780         bank = allbanks;
3781       }
3782       RegUsed = 1;
3783     }
3784
3785     pc = findNextInstruction(pc->next);
3786   }
3787
3788 //  fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
3789 //        pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
3790
3791
3792
3793 }
3794 /*-----------------------------------------------------------------*/
3795 /*-----------------------------------------------------------------*/
3796 void BanksUsedFlow(pBlock *pb)
3797 {
3798   pCode *pcflow;
3799
3800
3801   //pb->pcHead->print(stderr, pb->pcHead);
3802
3803   pcflow = findNextpCode(pb->pcHead, PC_FLOW);
3804   //pcflow->print(stderr,pcflow);
3805
3806   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
3807        pcflow != NULL;
3808        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
3809
3810     BanksUsedFlow2(pcflow);
3811   }
3812
3813 }
3814
3815
3816 /*-----------------------------------------------------------------*/
3817 /*-----------------------------------------------------------------*/
3818 void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit)
3819 {
3820   pCode *new_pc;
3821
3822   if(!pc)
3823     return;
3824
3825   if(RP_BankBit < 0) 
3826     new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status));
3827   else
3828     new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF),
3829                       popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
3830
3831   pCodeInsertAfter(pc->prev, new_pc);
3832
3833   /* Move the label, if there is one */
3834
3835   if(PCI(pc)->label) {
3836     PCI(new_pc)->label = PCI(pc)->label;
3837     PCI(pc)->label = NULL;
3838   }
3839
3840   /* The new instruction has the same pcflow block */
3841   PCI(new_pc)->pcflow = PCI(pc)->pcflow;
3842
3843 }
3844 /*-----------------------------------------------------------------*/
3845 /*-----------------------------------------------------------------*/
3846 void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
3847 {
3848   pCode *pc=NULL;
3849   pCode *pcprev=NULL;
3850   pCode *new_pc;
3851
3852   regs *reg;
3853
3854   if(!pcfl)
3855     return;
3856
3857   pc = findNextInstruction(pcfl->pc.next);
3858
3859   while(isPCinFlow(pc,PCODE(pcfl))) {
3860
3861
3862     reg = getRegFromInstruction(pc);
3863 #if 0
3864     if(reg) {
3865       fprintf(stderr, "  %s  ",reg->name);
3866       fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3867
3868     }
3869 #endif
3870
3871     if(reg && REG_BANK(reg)!=cur_bank) {
3872       /* Examine the instruction before this one to make sure it is
3873        * not a skip type instruction */
3874       pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3875       if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
3876         int b = cur_bank ^ REG_BANK(reg);
3877
3878         //fprintf(stderr, "Cool! can switch banks\n");
3879         cur_bank = REG_BANK(reg);
3880         switch(b & 3) {
3881         case 0:
3882           break;
3883         case 1:
3884           insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3885           break;
3886         case 2:
3887           insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3888           insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3889           break;
3890         case 3:
3891           if(cur_bank & 3) {
3892             insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT);
3893             insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT);
3894           } else
3895             insertBankSwitch(pc, -1, -1);
3896           break;
3897           /*
3898             new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3899             popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3900             pCodeInsertAfter(pc->prev, new_pc);
3901             if(PCI(pc)->label) { 
3902             PCI(new_pc)->label = PCI(pc)->label;
3903             PCI(pc)->label = NULL;
3904             }
3905           */
3906           /*
3907             new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3908             popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3909             pCodeInsertAfter(pc, new_pc);
3910           */
3911
3912         }
3913
3914       } else {
3915         //fprintf(stderr, "Bummer can't switch banks\n");
3916         ;
3917       }
3918     }
3919
3920     pcprev = pc;
3921     pc = findNextInstruction(pc->next);
3922
3923   }
3924
3925   if(pcprev && cur_bank) {
3926     /* Brute force - make sure that we point to bank 0 at the
3927      * end of each flow block */
3928     new_pc = newpCode(POC_BCF,
3929                       popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3930     pCodeInsertAfter(pcprev, new_pc);
3931       cur_bank = 0;
3932   }
3933
3934 }
3935
3936 /*-----------------------------------------------------------------*/
3937 /*int compareBankFlow - compare the banking requirements between   */
3938 /*  flow objects. */
3939 /*-----------------------------------------------------------------*/
3940 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
3941 {
3942
3943   if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
3944     return 0;
3945
3946   if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
3947     return 0;
3948
3949   if(pcflow->firstBank == -1)
3950     return 0;
3951
3952
3953   if(pcflowLink->pcflow->firstBank == -1) {
3954     pCodeFlowLink *pctl = setFirstItem( toORfrom ? 
3955                                         pcflowLink->pcflow->to : 
3956                                         pcflowLink->pcflow->from);
3957     return compareBankFlow(pcflow, pctl, toORfrom);
3958   }
3959
3960   if(toORfrom) {
3961     if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
3962       return 0;
3963
3964     pcflowLink->bank_conflict++;
3965     pcflowLink->pcflow->FromConflicts++;
3966     pcflow->ToConflicts++;
3967   } else {
3968     
3969     if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
3970       return 0;
3971
3972     pcflowLink->bank_conflict++;
3973     pcflowLink->pcflow->ToConflicts++;
3974     pcflow->FromConflicts++;
3975
3976   }
3977   /*
3978   fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
3979           pcflowLink->pcflow->pc.seq,
3980           pcflowLink->pcflow->FromConflicts,
3981           pcflowLink->pcflow->ToConflicts);
3982   */
3983   return 1;
3984
3985 }
3986 /*-----------------------------------------------------------------*/
3987 /*-----------------------------------------------------------------*/
3988 void FixBankFlow(pBlock *pb)
3989 {
3990   pCode *pc=NULL;
3991   pCode *pcflow;
3992   pCodeFlowLink *pcfl;
3993
3994   pCode *pcflow_max_To=NULL;
3995   pCode *pcflow_max_From=NULL;
3996   int max_ToConflicts=0;
3997   int max_FromConflicts=0;
3998
3999   //fprintf(stderr,"Fix Bank flow \n");
4000   pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4001
4002
4003   /*
4004     First loop through all of the flow objects in this pcode block
4005     and fix the ones that have banking conflicts between the 
4006     entry and exit.
4007   */
4008
4009   //fprintf(stderr, "FixBankFlow - Phase 1\n");
4010
4011   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4012        pcflow != NULL;
4013        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4014
4015     if(!isPCFL(pcflow)) {
4016       fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4017       continue;
4018     }
4019
4020     if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank  &&
4021        PCFL(pcflow)->firstBank >= 0 &&
4022        PCFL(pcflow)->lastBank >= 0 ) {
4023
4024       int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4025         PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4026
4027       FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4028       BanksUsedFlow2(pcflow);
4029
4030     }
4031   }
4032
4033   //fprintf(stderr, "FixBankFlow - Phase 2\n");
4034
4035   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4036        pcflow != NULL;
4037        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4038
4039     int nFlows;
4040     int nConflicts;
4041
4042     if(!isPCFL(pcflow)) {
4043       fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4044       continue;
4045     }
4046
4047     PCFL(pcflow)->FromConflicts = 0;
4048     PCFL(pcflow)->ToConflicts = 0;
4049
4050     nFlows = 0;
4051     nConflicts = 0;
4052
4053     //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4054     pcfl = setFirstItem(PCFL(pcflow)->from);
4055     while (pcfl) {
4056
4057       pc = PCODE(pcfl->pcflow);
4058
4059       if(!isPCFL(pc)) {
4060         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4061         pc->print(stderr,pc);
4062       }
4063
4064       nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4065       nFlows++;
4066
4067       pcfl=setNextItem(PCFL(pcflow)->from);
4068     }
4069
4070     if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4071       //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4072
4073       FixRegisterBankingInFlow(PCFL(pcflow),0);
4074       BanksUsedFlow2(pcflow);
4075
4076       continue;  /* Don't need to check the flow from here - it's already been fixed */
4077
4078     }
4079
4080     nFlows = 0;
4081     nConflicts = 0;
4082
4083     pcfl = setFirstItem(PCFL(pcflow)->to);
4084     while (pcfl) {
4085
4086       pc = PCODE(pcfl->pcflow);
4087       if(!isPCFL(pc)) {
4088         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4089         pc->print(stderr,pc);
4090       }
4091
4092       nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4093       nFlows++;
4094
4095       pcfl=setNextItem(PCFL(pcflow)->to);
4096     }
4097
4098     if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4099       //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4100
4101       FixRegisterBankingInFlow(PCFL(pcflow),0);
4102       BanksUsedFlow2(pcflow);
4103     }
4104   }
4105
4106   /*
4107     Loop through the flow objects again and find the ones with the 
4108     maximum conflicts
4109   */
4110
4111   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4112        pcflow != NULL;
4113        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4114
4115     if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4116       pcflow_max_To = pcflow;
4117
4118     if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4119       pcflow_max_From = pcflow;
4120   }
4121 /*
4122   if(pcflow_max_To)
4123     fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4124             PCFL(pcflow_max_To)->pc.seq,
4125             PCFL(pcflow_max_To)->ToConflicts);
4126
4127   if(pcflow_max_From)
4128     fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4129             PCFL(pcflow_max_From)->pc.seq,
4130             PCFL(pcflow_max_From)->FromConflicts);
4131 */
4132 }
4133
4134 /*-----------------------------------------------------------------*/
4135 /*-----------------------------------------------------------------*/
4136 void DumpFlow(pBlock *pb)
4137 {
4138   pCode *pc=NULL;
4139   pCode *pcflow;
4140   pCodeFlowLink *pcfl;
4141
4142
4143   fprintf(stderr,"Dump flow \n");
4144   pb->pcHead->print(stderr, pb->pcHead);
4145
4146   pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4147   pcflow->print(stderr,pcflow);
4148
4149   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4150        pcflow != NULL;
4151        pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4152
4153     if(!isPCFL(pcflow)) {
4154       fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4155       continue;
4156     }
4157     fprintf(stderr,"dumping: ");
4158     pcflow->print(stderr,pcflow);
4159     FlowStats(PCFL(pcflow));
4160
4161     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4162
4163       pc = PCODE(pcfl->pcflow);
4164
4165       fprintf(stderr, "    from seq %d:\n",pc->seq);
4166       if(!isPCFL(pc)) {
4167         fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4168         pc->print(stderr,pc);
4169       }
4170
4171     }
4172
4173     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4174
4175       pc = PCODE(pcfl->pcflow);
4176
4177       fprintf(stderr, "    to seq %d:\n",pc->seq);
4178       if(!isPCFL(pc)) {
4179         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4180         pc->print(stderr,pc);
4181       }
4182
4183     }
4184
4185   }
4186
4187 }
4188
4189 /*-----------------------------------------------------------------*/
4190 /*-----------------------------------------------------------------*/
4191 int OptimizepBlock(pBlock *pb)
4192 {
4193   pCode *pc, *pcprev;
4194   int matches =0;
4195
4196   if(!pb || !peepOptimizing)
4197     return 0;
4198
4199   DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4200 /*
4201   for(pc = pb->pcHead; pc; pc = pc->next)
4202     matches += pCodePeepMatchRule(pc);
4203 */
4204
4205   pc = findNextInstruction(pb->pcHead);
4206   if(!pc)
4207     return 0;
4208
4209   pcprev = pc->prev;
4210   do {
4211
4212
4213     if(pCodePeepMatchRule(pc)) {
4214
4215       matches++;
4216
4217       if(pcprev)
4218         pc = findNextInstruction(pcprev->next);
4219       else 
4220         pc = findNextInstruction(pb->pcHead);
4221     } else
4222       pc = findNextInstruction(pc->next);
4223   } while(pc);
4224
4225   if(matches)
4226     DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4227   return matches;
4228
4229 }
4230
4231 /*-----------------------------------------------------------------*/
4232 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
4233 /*-----------------------------------------------------------------*/
4234 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4235 {
4236   pCode *pc;
4237
4238   for(pc = pcs; pc; pc = pc->next) {
4239
4240     if((pc->type == PC_OPCODE) && 
4241        (PCI(pc)->pcop) && 
4242        (PCI(pc)->pcop->type == PO_LABEL) &&
4243        (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4244       return pc;
4245   }
4246  
4247
4248   return NULL;
4249 }
4250
4251 /*-----------------------------------------------------------------*/
4252 /*-----------------------------------------------------------------*/
4253 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4254 {
4255
4256   if(isPCI(pc) && 
4257      (PCI(pc)->pcop) && 
4258      (PCI(pc)->pcop->type == PO_LABEL)) {
4259
4260     pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4261
4262     //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4263     if(pcol->pcop.name)
4264       free(pcol->pcop.name);
4265
4266     sprintf(buffer,"_%05d_DS_",pcl->key);
4267
4268     pcol->pcop.name = Safe_strdup(buffer);
4269     pcol->key = pcl->key;
4270     //pc->print(stderr,pc);
4271
4272   }
4273
4274
4275 }
4276
4277 /*-----------------------------------------------------------------*/
4278 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
4279 /*                            pCode chain if they're not used.     */
4280 /*-----------------------------------------------------------------*/
4281 void pBlockRemoveUnusedLabels(pBlock *pb)
4282 {
4283   pCode *pc; pCodeLabel *pcl;
4284
4285   if(!pb)
4286     return;
4287
4288   for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4289
4290     pBranch *pbr = PCI(pc)->label;
4291     if(pbr && pbr->next) {
4292       pCode *pcd = pb->pcHead;
4293
4294       //fprintf(stderr, "multiple labels\n");
4295       //pc->print(stderr,pc);
4296
4297       pbr = pbr->next;
4298       while(pbr) {
4299
4300         while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4301           //fprintf(stderr,"Used by:\n");
4302           //pcd->print(stderr,pcd);
4303
4304           exchangeLabels(PCL(pbr->pc),pcd);
4305
4306           pcd = pcd->next;
4307         }
4308         pbr = pbr->next;
4309       }
4310     }
4311   }
4312
4313   for(pc = pb->pcHead; pc; pc = pc->next) {
4314
4315     if(isPCL(pc)) // pc->type == PC_LABEL)
4316       pcl = PCL(pc);
4317     else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
4318       pcl = PCL(PCI(pc)->label->pc);
4319     else continue;
4320
4321     //fprintf(stderr," found  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4322
4323     /* This pCode is a label, so search the pBlock to see if anyone
4324      * refers to it */
4325
4326     if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4327     //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4328       /* Couldn't find an instruction that refers to this label
4329        * So, unlink the pCode label from it's pCode chain
4330        * and destroy the label */
4331       //fprintf(stderr," removed  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4332
4333       DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4334       if(pc->type == PC_LABEL) {
4335         unlinkpCode(pc);
4336         pCodeLabelDestruct(pc);
4337       } else {
4338         unlinkpCodeFromBranch(pc, PCODE(pcl));
4339         /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4340           free(pc->label);
4341         }*/
4342       }
4343
4344     }
4345   }
4346
4347 }
4348
4349
4350 /*-----------------------------------------------------------------*/
4351 /* pBlockMergeLabels - remove the pCode labels from the pCode      */
4352 /*                     chain and put them into pBranches that are  */
4353 /*                     associated with the appropriate pCode       */
4354 /*                     instructions.                               */
4355 /*-----------------------------------------------------------------*/
4356 void pBlockMergeLabels(pBlock *pb)
4357 {
4358   pBranch *pbr;
4359   pCode *pc, *pcnext=NULL;
4360
4361   if(!pb)
4362     return;
4363
4364   /* First, Try to remove any unused labels */
4365   //pBlockRemoveUnusedLabels(pb);
4366
4367   /* Now loop through the pBlock and merge the labels with the opcodes */
4368
4369   pc = pb->pcHead;
4370   //  for(pc = pb->pcHead; pc; pc = pc->next) {
4371
4372   while(pc) {
4373     pCode *pcn = pc->next;
4374
4375     if(pc->type == PC_LABEL) {
4376
4377       //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4378       //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4379       if((pcnext = findNextInstruction(pc) )) {
4380
4381         // Unlink the pCode label from it's pCode chain
4382         unlinkpCode(pc);
4383         
4384         //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4385         // And link it into the instruction's pBranch labels. (Note, since
4386         // it's possible to have multiple labels associated with one instruction
4387         // we must provide a means to accomodate the additional labels. Thus
4388         // the labels are placed into the singly-linked list "label" as 
4389         // opposed to being a single member of the pCodeInstruction.)
4390
4391         //_ALLOC(pbr,sizeof(pBranch));
4392         pbr = Safe_calloc(1,sizeof(pBranch));
4393         pbr->pc = pc;
4394         pbr->next = NULL;
4395
4396         PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4397
4398       } else {
4399         fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4400       }
4401     } else if(pc->type == PC_CSOURCE) {
4402
4403       /* merge the source line symbolic info into the next instruction */
4404       if((pcnext = findNextInstruction(pc) )) {
4405
4406         // Unlink the pCode label from it's pCode chain
4407         unlinkpCode(pc);
4408         PCI(pcnext)->cline = PCCS(pc);
4409         //fprintf(stderr, "merging CSRC\n");
4410         //genericPrint(stderr,pcnext);
4411       }
4412
4413     }
4414     pc = pcn;
4415   }
4416   pBlockRemoveUnusedLabels(pb);
4417
4418 }
4419
4420 /*-----------------------------------------------------------------*/
4421 /*-----------------------------------------------------------------*/
4422 int OptimizepCode(char dbName)
4423 {
4424 #define MAX_PASSES 4
4425
4426   int matches = 0;
4427   int passes = 0;
4428   pBlock *pb;
4429
4430   if(!the_pFile)
4431     return 0;
4432
4433   DFPRINTF((stderr," Optimizing pCode\n"));
4434
4435   do {
4436     matches = 0;
4437     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4438       if('*' == dbName || getpBlock_dbName(pb) == dbName)
4439         matches += OptimizepBlock(pb);
4440     }
4441   }
4442   while(matches && ++passes < MAX_PASSES);
4443
4444   return matches;
4445 }
4446
4447 /*-----------------------------------------------------------------*/
4448 /* popCopyGPR2Bit - copy a pcode operator                          */
4449 /*-----------------------------------------------------------------*/
4450
4451 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
4452 {
4453   pCodeOp *pcop;
4454
4455   pcop = newpCodeOpBit(pc->name, bitval, 0);
4456
4457   if( !( (pcop->type == PO_LABEL) ||
4458          (pcop->type == PO_LITERAL) ||
4459          (pcop->type == PO_STR) ))
4460     PCOR(pcop)->r = PCOR(pc)->r;  /* This is dangerous... */
4461
4462   return pcop;
4463 }
4464
4465
4466
4467 #if 0
4468 /*-----------------------------------------------------------------*/
4469 /*-----------------------------------------------------------------*/
4470 int InstructionRegBank(pCode *pc)
4471 {
4472   regs *reg;
4473
4474   if( (reg = getRegFromInstruction(pc)) == NULL)
4475     return -1;
4476
4477   return REG_BANK(reg);
4478
4479 }
4480 #endif
4481
4482 /*-----------------------------------------------------------------*/
4483 /*-----------------------------------------------------------------*/
4484 void FixRegisterBanking(pBlock *pb)
4485 {
4486   pCode *pc=NULL;
4487   pCode *pcprev=NULL;
4488   pCode *new_pc;
4489
4490   int cur_bank;
4491   regs *reg;
4492   //  return;
4493   if(!pb)
4494     return;
4495
4496   //pc = findNextpCode(pb->pcHead, PC_FLOW);
4497   pc = findNextpCode(pb->pcHead, PC_OPCODE);
4498   if(!pc)
4499     return;
4500   /* loop through all of the flow blocks with in one pblock */
4501
4502   //fprintf(stderr,"Register banking\n");
4503   cur_bank = 0;
4504   do {
4505     /* at this point, pc should point to a PC_FLOW object */
4506
4507
4508     /* for each flow block, determine the register banking 
4509        requirements */
4510
4511     //    do {
4512       if(isPCI(pc)) {
4513         //genericPrint(stderr, pc);
4514
4515         reg = getRegFromInstruction(pc);
4516         #if 0
4517         if(reg) {
4518           fprintf(stderr, "  %s  ",reg->name);
4519           fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
4520
4521         }
4522         #endif
4523         if(reg && REG_BANK(reg)!=cur_bank) {
4524           /* Examine the instruction before this one to make sure it is
4525            * not a skip type instruction */
4526           pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4527           if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4528             int b = cur_bank ^ REG_BANK(reg);
4529
4530             //fprintf(stderr, "Cool! can switch banks\n");
4531             cur_bank = REG_BANK(reg);
4532             if(b & 1) {
4533               new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
4534                                 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4535               pCodeInsertAfter(pc->prev, new_pc);
4536               if(PCI(pc)->label) { 
4537                 PCI(new_pc)->label = PCI(pc)->label;
4538                 PCI(pc)->label = NULL;
4539               }
4540               /*
4541                 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
4542                 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4543                 pCodeInsertAfter(pc, new_pc);
4544               */
4545
4546             }
4547
4548           } else {
4549             //fprintf(stderr, "Bummer can't switch banks\n");
4550             ;
4551           }
4552         }
4553       }
4554
4555       pcprev = pc;
4556       pc = pc->next;
4557       // } while(pc && !(isPCFL(pc))); 
4558
4559
4560   }while (pc);
4561
4562     if(pcprev && cur_bank) {
4563       /* Brute force - make sure that we point to bank 0 at the
4564        * end of each flow block */
4565       new_pc = newpCode(POC_BCF,
4566                         popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
4567       pCodeInsertAfter(pcprev, new_pc);
4568       cur_bank = 0;
4569     }
4570
4571 }
4572
4573 void pBlockDestruct(pBlock *pb)
4574 {
4575
4576   if(!pb)
4577     return;
4578
4579
4580   free(pb);
4581
4582 }
4583
4584 /*-----------------------------------------------------------------*/
4585 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
4586 /*                                  name dbName and combine them   */
4587 /*                                  into one block                 */
4588 /*-----------------------------------------------------------------*/
4589 void mergepBlocks(char dbName)
4590 {
4591
4592   pBlock *pb, *pbmerged = NULL,*pbn;
4593
4594   pb = the_pFile->pbHead;
4595
4596   //fprintf(stderr," merging blocks named %c\n",dbName);
4597   while(pb) {
4598
4599     pbn = pb->next;
4600     //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
4601     if( getpBlock_dbName(pb) == dbName) {
4602
4603       //fprintf(stderr," merged block %c\n",dbName);
4604
4605       if(!pbmerged) {
4606         pbmerged = pb;
4607       } else {
4608         addpCode2pBlock(pbmerged, pb->pcHead);
4609         /* addpCode2pBlock doesn't handle the tail: */
4610         pbmerged->pcTail = pb->pcTail;
4611
4612         pb->prev->next = pbn;
4613         if(pbn) 
4614           pbn->prev = pb->prev;
4615
4616
4617         pBlockDestruct(pb);
4618       }
4619       //printpBlock(stderr, pbmerged);
4620     } 
4621     pb = pbn;
4622   }
4623
4624 }
4625
4626 /*-----------------------------------------------------------------*/
4627 /* AnalyzeFlow - Examine the flow of the code and optimize         */
4628 /*                                                                 */
4629 /* level 0 == minimal optimization                                 */
4630 /*   optimize registers that are used only by two instructions     */
4631 /* level 1 == maximal optimization                                 */
4632 /*   optimize by looking at pairs of instructions that use the     */
4633 /*   register.                                                     */
4634 /*-----------------------------------------------------------------*/
4635
4636 void AnalyzeFlow(int level)
4637 {
4638   static int times_called=0;
4639
4640   pBlock *pb;
4641
4642   if(!the_pFile)
4643     return;
4644
4645
4646   /* if this is not the first time this function has been called,
4647      then clean up old flow information */
4648   if(times_called++) {
4649     for(pb = the_pFile->pbHead; pb; pb = pb->next)
4650       unBuildFlow(pb);
4651
4652     RegsUnMapLiveRanges();
4653
4654   }
4655
4656   GpcFlowSeq = 1;
4657
4658   /* Phase 2 - Flow Analysis - Register Banking
4659    *
4660    * In this phase, the individual flow blocks are examined
4661    * and register banking is fixed.
4662    */
4663
4664   //for(pb = the_pFile->pbHead; pb; pb = pb->next)
4665   //FixRegisterBanking(pb);
4666
4667   /* Phase 2 - Flow Analysis
4668    *
4669    * In this phase, the pCode is partition into pCodeFlow 
4670    * blocks. The flow blocks mark the points where a continuous
4671    * stream of instructions changes flow (e.g. because of
4672    * a call or goto or whatever).
4673    */
4674
4675   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4676     BuildFlow(pb);
4677
4678
4679   /* Phase 2 - Flow Analysis - linking flow blocks
4680    *
4681    * In this phase, the individual flow blocks are examined
4682    * to determine their order of excution.
4683    */
4684
4685   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4686     LinkFlow(pb);
4687
4688   /* Phase 3 - Flow Analysis - Flow Tree
4689    *
4690    * In this phase, the individual flow blocks are examined
4691    * to determine their order of excution.
4692    */
4693
4694   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4695     BuildFlowTree(pb);
4696
4697
4698   /* Phase x - Flow Analysis - Used Banks
4699    *
4700    * In this phase, the individual flow blocks are examined
4701    * to determine the Register Banks they use
4702    */
4703
4704   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4705     FixBankFlow(pb);
4706
4707
4708   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4709     pCodeRegMapLiveRanges(pb);
4710
4711   RemoveUnusedRegisters();
4712
4713   //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
4714   pCodeRegOptimizeRegUsage(level);
4715
4716   OptimizepCode('*');
4717
4718
4719 /*
4720   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4721     DumpFlow(pb);
4722 */
4723   /* debug stuff */ 
4724   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4725     pCode *pcflow;
4726     for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4727          (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4728          pcflow = pcflow->next) {
4729
4730       FillFlow(PCFL(pcflow));
4731     }
4732   }
4733
4734 /*
4735   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4736     pCode *pcflow;
4737     for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4738          (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
4739          pcflow = pcflow->next) {
4740
4741       FlowStats(PCFL(pcflow));
4742     }
4743   }
4744 */
4745 }
4746
4747 /*-----------------------------------------------------------------*/
4748 /* AnalyzeBanking - Called after the memory addresses have been    */
4749 /*                  assigned to the registers.                     */
4750 /*                                                                 */
4751 /*-----------------------------------------------------------------*/
4752
4753 void AnalyzeBanking(void)
4754 {
4755   pBlock  *pb;
4756
4757   if(!picIsInitialized()) {
4758     fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
4759     fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
4760     fprintf(stderr,"support/scripts/inc2h.pl\n");
4761     fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
4762
4763     exit(1);
4764   }
4765
4766   /* Phase x - Flow Analysis - Used Banks
4767    *
4768    * In this phase, the individual flow blocks are examined
4769    * to determine the Register Banks they use
4770    */
4771
4772   AnalyzeFlow(0);
4773   AnalyzeFlow(1);
4774
4775   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4776     BanksUsedFlow(pb);
4777   for(pb = the_pFile->pbHead; pb; pb = pb->next)
4778     FixRegisterBanking(pb);
4779
4780 }
4781
4782 /*-----------------------------------------------------------------*/
4783 /* buildCallTree - look at the flow and extract all of the calls   */
4784 /*                                                                 */
4785 /*-----------------------------------------------------------------*/
4786 set *register_usage(pBlock *pb);
4787
4788 void buildCallTree(void    )
4789 {
4790   pBranch *pbr;
4791   pBlock  *pb;
4792   pCode   *pc;
4793
4794   if(!the_pFile)
4795     return;
4796
4797
4798
4799   /* Now build the call tree.
4800      First we examine all of the pCodes for functions.
4801      Keep in mind that the function boundaries coincide
4802      with pBlock boundaries. 
4803
4804      The algorithm goes something like this:
4805      We have two nested loops. The outer loop iterates
4806      through all of the pBlocks/functions. The inner
4807      loop iterates through all of the pCodes for
4808      a given pBlock. When we begin iterating through
4809      a pBlock, the variable pc_fstart, pCode of the start
4810      of a function, is cleared. We then search for pCodes
4811      of type PC_FUNCTION. When one is encountered, we
4812      initialize pc_fstart to this and at the same time
4813      associate a new pBranch object that signifies a 
4814      branch entry. If a return is found, then this signifies
4815      a function exit point. We'll link the pCodes of these
4816      returns to the matching pc_fstart.
4817
4818      When we're done, a doubly linked list of pBranches
4819      will exist. The head of this list is stored in
4820      `the_pFile', which is the meta structure for all
4821      of the pCode. Look at the printCallTree function
4822      on how the pBranches are linked together.
4823
4824    */
4825   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4826     pCode *pc_fstart=NULL;
4827     for(pc = pb->pcHead; pc; pc = pc->next) {
4828       if(isPCF(pc)) {
4829         if (PCF(pc)->fname) {
4830
4831           if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
4832             //fprintf(stderr," found main \n");
4833             pb->cmemmap = NULL;  /* FIXME do we need to free ? */
4834             pb->dbName = 'M';
4835           }
4836
4837           pbr = Safe_calloc(1,sizeof(pBranch));
4838           pbr->pc = pc_fstart = pc;
4839           pbr->next = NULL;
4840
4841           the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
4842
4843           // Here's a better way of doing the same:
4844           addSet(&pb->function_entries, pc);
4845
4846         } else {
4847           // Found an exit point in a function, e.g. return
4848           // (Note, there may be more than one return per function)
4849           if(pc_fstart)
4850             pBranchLink(PCF(pc_fstart), PCF(pc));
4851
4852           addSet(&pb->function_exits, pc);
4853         }
4854       } else if(isCALL(pc)) {
4855         addSet(&pb->function_calls,pc);
4856       }
4857     }
4858   }
4859
4860   /* Re-allocate the registers so that there are no collisions
4861    * between local variables when one function call another */
4862
4863   // this is weird...
4864   //  pic14_deallocateAllRegs();
4865
4866   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4867     if(!pb->visited)
4868       register_usage(pb);
4869   }
4870
4871 }
4872
4873 /*-----------------------------------------------------------------*/
4874 /* AnalyzepCode - parse the pCode that has been generated and form */
4875 /*                all of the logical connections.                  */
4876 /*                                                                 */
4877 /* Essentially what's done here is that the pCode flow is          */
4878 /* determined.                                                     */
4879 /*-----------------------------------------------------------------*/
4880
4881 void AnalyzepCode(char dbName)
4882 {
4883   pBlock *pb;
4884   int i,changes;
4885
4886   if(!the_pFile)
4887     return;
4888
4889   mergepBlocks('D');
4890
4891
4892   /* Phase 1 - Register allocation and peep hole optimization
4893    *
4894    * The first part of the analysis is to determine the registers
4895    * that are used in the pCode. Once that is done, the peep rules
4896    * are applied to the code. We continue to loop until no more
4897    * peep rule optimizations are found (or until we exceed the
4898    * MAX_PASSES threshold). 
4899    *
4900    * When done, the required registers will be determined.
4901    *
4902    */
4903   i = 0;
4904   do {
4905
4906     DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
4907     //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
4908
4909     /* First, merge the labels with the instructions */
4910     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4911       if('*' == dbName || getpBlock_dbName(pb) == dbName) {
4912
4913         DFPRINTF((stderr," analyze and merging block %c\n",dbName));
4914         //fprintf(stderr," analyze and merging block %c\n",dbName);
4915         pBlockMergeLabels(pb);
4916         AnalyzepBlock(pb);
4917       } else {
4918         DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
4919       }
4920     }
4921
4922     changes = OptimizepCode(dbName);
4923
4924   } while(changes && (i++ < MAX_PASSES));
4925
4926   buildCallTree();
4927 }
4928
4929 /*-----------------------------------------------------------------*/
4930 /* ispCodeFunction - returns true if *pc is the pCode of a         */
4931 /*                   function                                      */
4932 /*-----------------------------------------------------------------*/
4933 bool ispCodeFunction(pCode *pc)
4934 {
4935
4936   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
4937     return 1;
4938
4939   return 0;
4940 }
4941
4942 /*-----------------------------------------------------------------*/
4943 /* findFunction - Search for a function by name (given the name)   */
4944 /*                in the set of all functions that are in a pBlock */
4945 /* (note - I expect this to change because I'm planning to limit   */
4946 /*  pBlock's to just one function declaration                      */
4947 /*-----------------------------------------------------------------*/
4948 pCode *findFunction(char *fname)
4949 {
4950   pBlock *pb;
4951   pCode *pc;
4952   if(!fname)
4953     return NULL;
4954
4955   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4956
4957     pc = setFirstItem(pb->function_entries);
4958     while(pc) {
4959     
4960       if((pc->type == PC_FUNCTION) &&
4961          (PCF(pc)->fname) && 
4962          (strcmp(fname, PCF(pc)->fname)==0))
4963         return pc;
4964
4965       pc = setNextItem(pb->function_entries);
4966
4967     }
4968
4969   }
4970   return NULL;
4971 }
4972
4973 void MarkUsedRegisters(set *regset)
4974 {
4975
4976   regs *r1,*r2;
4977
4978   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
4979     r2 = pic14_regWithIdx(r1->rIdx);
4980     r2->isFree = 0;
4981     r2->wasUsed = 1;
4982   }
4983 }
4984
4985 void pBlockStats(FILE *of, pBlock *pb)
4986 {
4987
4988   pCode *pc;
4989   regs  *r;
4990
4991   fprintf(of,";***\n;  pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
4992
4993   // for now just print the first element of each set
4994   pc = setFirstItem(pb->function_entries);
4995   if(pc) {
4996     fprintf(of,";entry:  ");
4997     pc->print(of,pc);
4998   }
4999   pc = setFirstItem(pb->function_exits);
5000   if(pc) {
5001     fprintf(of,";has an exit\n");
5002     //pc->print(of,pc);
5003   }
5004
5005   pc = setFirstItem(pb->function_calls);
5006   if(pc) {
5007     fprintf(of,";functions called:\n");
5008
5009     while(pc) {
5010       if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5011         fprintf(of,";   %s\n",get_op_from_instruction(PCI(pc)));
5012       }
5013       pc = setNextItem(pb->function_calls);
5014     }
5015   }
5016
5017   r = setFirstItem(pb->tregisters);
5018   if(r) {
5019     int n = elementsInSet(pb->tregisters);
5020
5021     fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5022
5023     while (r) {
5024       fprintf(of,";   %s\n",r->name);
5025       r = setNextItem(pb->tregisters);
5026     }
5027   }
5028 }
5029
5030 /*-----------------------------------------------------------------*/
5031 /*-----------------------------------------------------------------*/
5032 #if 0
5033 static void sequencepCode(void)
5034 {
5035   pBlock *pb;
5036   pCode *pc;
5037
5038
5039   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5040
5041     pb->seq = GpCodeSequenceNumber+1;
5042
5043     for( pc = pb->pcHead; pc; pc = pc->next)
5044       pc->seq = ++GpCodeSequenceNumber;
5045   }
5046
5047 }
5048 #endif
5049
5050 /*-----------------------------------------------------------------*/
5051 /*-----------------------------------------------------------------*/
5052 set *register_usage(pBlock *pb)
5053 {
5054   pCode *pc,*pcn;
5055   set *registers=NULL;
5056   set *registersInCallPath = NULL;
5057
5058   /* check recursion */
5059
5060   pc = setFirstItem(pb->function_entries);
5061
5062   if(!pc)
5063     return registers;
5064
5065   pb->visited = 1;
5066
5067   if(pc->type != PC_FUNCTION)
5068     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5069
5070   pc = setFirstItem(pb->function_calls);
5071   for( ; pc; pc = setNextItem(pb->function_calls)) {
5072
5073     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5074       char *dest = get_op_from_instruction(PCI(pc));
5075
5076       pcn = findFunction(dest);
5077       if(pcn) 
5078         registersInCallPath = register_usage(pcn->pb);
5079     } else
5080       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5081
5082   }
5083
5084 #ifdef PCODE_DEBUG
5085   pBlockStats(stderr,pb);  // debug
5086 #endif
5087
5088   // Mark the registers in this block as used.
5089
5090   MarkUsedRegisters(pb->tregisters);
5091   if(registersInCallPath) {
5092     /* registers were used in the functions this pBlock has called */
5093     /* so now, we need to see if these collide with the ones we are */
5094     /* using here */
5095
5096     regs *r1,*r2, *newreg;
5097
5098     DFPRINTF((stderr,"comparing registers\n"));
5099
5100     r1 = setFirstItem(registersInCallPath);
5101     while(r1) {
5102
5103       r2 = setFirstItem(pb->tregisters);
5104
5105       while(r2 && (r1->type != REG_STK)) {
5106
5107         if(r2->rIdx == r1->rIdx) {
5108           newreg = pic14_findFreeReg(REG_GPR);
5109
5110
5111           if(!newreg) {
5112             DFPRINTF((stderr,"Bummer, no more registers.\n"));
5113             exit(1);
5114           }
5115
5116           DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5117                   r1->rIdx, newreg->rIdx));
5118           r2->rIdx = newreg->rIdx;
5119           //if(r2->name) free(r2->name);
5120           if(newreg->name)
5121             r2->name = Safe_strdup(newreg->name);
5122           else
5123             r2->name = NULL;
5124           newreg->isFree = 0;
5125           newreg->wasUsed = 1;
5126         }
5127         r2 = setNextItem(pb->tregisters);
5128       }
5129
5130       r1 = setNextItem(registersInCallPath);
5131     }
5132
5133     /* Collisions have been resolved. Now free the registers in the call path */
5134     r1 = setFirstItem(registersInCallPath);
5135     while(r1) {
5136       if(r1->type != REG_STK) {
5137         newreg = pic14_regWithIdx(r1->rIdx);
5138         newreg->isFree = 1;
5139       }
5140       r1 = setNextItem(registersInCallPath);
5141     }
5142
5143   }// else
5144   //    MarkUsedRegisters(pb->registers);
5145
5146   registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5147 #ifdef PCODE_DEBUG
5148   if(registers) 
5149     DFPRINTF((stderr,"returning regs\n"));
5150   else
5151     DFPRINTF((stderr,"not returning regs\n"));
5152
5153   DFPRINTF((stderr,"pBlock after register optim.\n"));
5154   pBlockStats(stderr,pb);  // debug
5155 #endif
5156
5157   return registers;
5158 }
5159
5160 /*-----------------------------------------------------------------*/
5161 /* printCallTree - writes the call tree to a file                  */
5162 /*                                                                 */
5163 /*-----------------------------------------------------------------*/
5164 void pct2(FILE *of,pBlock *pb,int indent)
5165 {
5166   pCode *pc,*pcn;
5167   int i;
5168   //  set *registersInCallPath = NULL;
5169
5170   if(!of)
5171     return;
5172
5173   if(indent > 10)
5174     return; //recursion ?
5175
5176   pc = setFirstItem(pb->function_entries);
5177
5178   if(!pc)
5179     return;
5180
5181   pb->visited = 0;
5182
5183   for(i=0;i<indent;i++)   // Indentation
5184     fputc(' ',of);
5185
5186   if(pc->type == PC_FUNCTION)
5187     fprintf(of,"%s\n",PCF(pc)->fname);
5188   else
5189     return;  // ???
5190
5191
5192   pc = setFirstItem(pb->function_calls);
5193   for( ; pc; pc = setNextItem(pb->function_calls)) {
5194
5195     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5196       char *dest = get_op_from_instruction(PCI(pc));
5197
5198       pcn = findFunction(dest);
5199       if(pcn) 
5200         pct2(of,pcn->pb,indent+1);
5201     } else
5202       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5203
5204   }
5205
5206
5207 }
5208
5209
5210 /*-----------------------------------------------------------------*/
5211 /* printCallTree - writes the call tree to a file                  */
5212 /*                                                                 */
5213 /*-----------------------------------------------------------------*/
5214
5215 void printCallTree(FILE *of)
5216 {
5217   pBranch *pbr;
5218   pBlock  *pb;
5219   pCode   *pc;
5220
5221   if(!the_pFile)
5222     return;
5223
5224   if(!of)
5225     of = stderr;
5226
5227   fprintf(of, "\npBlock statistics\n");
5228   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
5229     pBlockStats(of,pb);
5230
5231
5232
5233   fprintf(of,"Call Tree\n");
5234   pbr = the_pFile->functions;
5235   while(pbr) {
5236     if(pbr->pc) {
5237       pc = pbr->pc;
5238       if(!ispCodeFunction(pc))
5239         fprintf(of,"bug in call tree");
5240
5241
5242       fprintf(of,"Function: %s\n", PCF(pc)->fname);
5243
5244       while(pc->next && !ispCodeFunction(pc->next)) {
5245         pc = pc->next;
5246         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5247           fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5248       }
5249     }
5250
5251     pbr = pbr->next;
5252   }
5253
5254
5255   fprintf(of,"\n**************\n\na better call tree\n");
5256   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5257     if(pb->visited)
5258       pct2(of,pb,0);
5259   }
5260
5261   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5262     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5263   }
5264 }
5265
5266
5267
5268 /*-----------------------------------------------------------------*/
5269 /*                                                                 */
5270 /*-----------------------------------------------------------------*/
5271
5272 void InlineFunction(pBlock *pb)
5273 {
5274   pCode *pc;
5275   pCode *pc_call;
5276
5277   if(!pb)
5278     return;
5279
5280   pc = setFirstItem(pb->function_calls);
5281
5282   for( ; pc; pc = setNextItem(pb->function_calls)) {
5283
5284     if(isCALL(pc)) {
5285       pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5286       pCode *pct;
5287       pCode *pce;
5288
5289       pBranch *pbr;
5290
5291       if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1)) {
5292         
5293         //fprintf(stderr,"Cool can inline:\n");
5294         //pcn->print(stderr,pcn);
5295
5296         //fprintf(stderr,"recursive call Inline\n");
5297         InlineFunction(pcn->pb);
5298         //fprintf(stderr,"return from recursive call Inline\n");
5299
5300         /*
5301           At this point, *pc points to a CALL mnemonic, and
5302           *pcn points to the function that is being called.
5303
5304           To in-line this call, we need to remove the CALL
5305           and RETURN(s), and link the function pCode in with
5306           the CALLee pCode.
5307
5308         */
5309
5310
5311         /* Remove the CALL */
5312         pc_call = pc;
5313         pc = pc->prev;
5314
5315         /* remove callee pBlock from the pBlock linked list */
5316         removepBlock(pcn->pb);
5317
5318         pce = pcn;
5319         while(pce) {
5320           pce->pb = pb;
5321           pce = pce->next;
5322         }
5323
5324         /* Remove the Function pCode */
5325         pct = findNextInstruction(pcn->next);
5326
5327         /* Link the function with the callee */
5328         pc->next = pcn->next;
5329         pcn->next->prev = pc;
5330         
5331         /* Convert the function name into a label */
5332
5333         pbr = Safe_calloc(1,sizeof(pBranch));
5334         pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5335         pbr->next = NULL;
5336         PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5337         PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5338
5339         /* turn all of the return's except the last into goto's */
5340         /* check case for 2 instruction pBlocks */
5341         pce = findNextInstruction(pcn->next);
5342         while(pce) {
5343           pCode *pce_next = findNextInstruction(pce->next);
5344
5345           if(pce_next == NULL) {
5346             /* found the last return */
5347             pCode *pc_call_next =  findNextInstruction(pc_call->next);
5348
5349             //fprintf(stderr,"found last return\n");
5350             //pce->print(stderr,pce);
5351             pce->prev->next = pc_call->next;
5352             pc_call->next->prev = pce->prev;
5353             PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5354                                                       PCI(pce)->label);
5355           }
5356
5357           pce = pce_next;
5358         }
5359
5360
5361       }
5362     } else
5363       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5364
5365   }
5366
5367 }
5368
5369 /*-----------------------------------------------------------------*/
5370 /*                                                                 */
5371 /*-----------------------------------------------------------------*/
5372
5373 void InlinepCode(void)
5374 {
5375
5376   pBlock  *pb;
5377   pCode   *pc;
5378
5379   if(!the_pFile)
5380     return;
5381
5382   if(!functionInlining)
5383     return;
5384
5385   /* Loop through all of the function definitions and count the
5386    * number of times each one is called */
5387   //fprintf(stderr,"inlining %d\n",__LINE__);
5388
5389   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5390
5391     pc = setFirstItem(pb->function_calls);
5392
5393     for( ; pc; pc = setNextItem(pb->function_calls)) {
5394
5395       if(isCALL(pc)) {
5396         pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5397         if(pcn && isPCF(pcn)) {
5398           PCF(pcn)->ncalled++;
5399         }
5400       } else
5401         fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5402
5403     }
5404   }
5405
5406   //fprintf(stderr,"inlining %d\n",__LINE__);
5407
5408   /* Now, Loop through the function definitions again, but this
5409    * time inline those functions that have only been called once. */
5410   
5411   InlineFunction(the_pFile->pbHead);
5412   //fprintf(stderr,"inlining %d\n",__LINE__);
5413
5414   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5415     unBuildFlow(pb);
5416
5417 }