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