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