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