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