Added -p command line option to allow selection of port dependent processor.
[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 // Eventually this will go into device dependent files:
40 pCodeOpReg pc_status    = {{PO_STATUS,  "STATUS"}, -1, NULL,0,NULL};
41 pCodeOpReg pc_indf      = {{PO_INDF,    "INDF"}, -1, NULL,0,NULL};
42 pCodeOpReg pc_fsr       = {{PO_FSR,     "FSR"}, -1, NULL,0,NULL};
43 pCodeOpReg pc_intcon    = {{PO_INTCON,  ""}, -1, NULL,0,NULL};
44 pCodeOpReg pc_pcl       = {{PO_PCL,     "PCL"}, -1, NULL,0,NULL};
45 pCodeOpReg pc_pclath    = {{PO_PCLATH,  "PCLATH"}, -1, NULL,0,NULL};
46
47 pCodeOpReg pc_kzero     = {{PO_GPR_REGISTER,  "KZ"}, -1, NULL,0,NULL};
48 pCodeOpReg pc_wsave     = {{PO_GPR_REGISTER,  "WSAVE"}, -1, NULL,0,NULL};
49 pCodeOpReg pc_ssave     = {{PO_GPR_REGISTER,  "SSAVE"}, -1, NULL,0,NULL};
50
51 static int mnemonics_initialized = 0;
52
53
54 static hTab *pic14MnemonicsHash = NULL;
55
56
57
58 static pFile *the_pFile = NULL;
59 static int peepOptimizing = 1;
60 static int GpCodeSequenceNumber = 1;
61 static int GpcFlowSeq = 1;
62
63 #define isPCI(x)        ((PCODE(x)->type == PC_OPCODE))
64 #define isPCI_BRANCH(x) ((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isBranch)
65 #define isPCI_SKIP(x)   ((PCODE(x)->type == PC_OPCODE) &&  PCI(x)->isSkip)
66 #define isPCFL(x)       ((PCODE(x)->type == PC_FLOW))
67 #define isPCF(x)        ((PCODE(x)->type == PC_FUNCTION))
68 #define isCALL(x)       ((isPCI(x)) && (PCI(x)->op == POC_CALL))
69 #define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS)
70
71 /****************************************************************/
72 /*                      Forward declarations                    */
73 /****************************************************************/
74
75 static void unlinkPC(pCode *pc);
76 #if 0
77 static void genericAnalyze(pCode *pc);
78 static void AnalyzeGOTO(pCode *pc);
79 static void AnalyzeSKIP(pCode *pc);
80 static void AnalyzeRETURN(pCode *pc);
81 #endif
82
83 static void genericDestruct(pCode *pc);
84 static void genericPrint(FILE *of,pCode *pc);
85
86 static void pCodePrintLabel(FILE *of, pCode *pc);
87 static void pCodePrintFunction(FILE *of, pCode *pc);
88 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
89 static char *get_op( pCodeInstruction *pcc);
90 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
91 int pCodePeepMatchRule(pCode *pc);
92 void pBlockStats(FILE *of, pBlock *pb);
93 extern void pCodeInsertAfter(pCode *pc1, pCode *pc2);
94
95 pCodeInstruction pciADDWF = {
96   {PC_OPCODE, NULL, NULL, 0, NULL, 
97    //   genericAnalyze,
98    genericDestruct,
99    genericPrint},
100   POC_ADDWF,
101   "ADDWF",
102   NULL, // from branch
103   NULL, // to branch
104   NULL, // label
105   NULL, // operand
106   NULL, // flow block
107   2,    // num ops
108   1,0,  // dest, bit instruction
109   0,0,  // branch, skip
110   (PCC_W | PCC_REGISTER),   // inCond
111   (PCC_REGISTER | PCC_Z) // outCond
112 };
113
114 pCodeInstruction pciADDFW = {
115   {PC_OPCODE, NULL, NULL, 0, NULL, 
116    //   genericAnalyze,
117    genericDestruct,
118    genericPrint},
119   POC_ADDWF,
120   "ADDWF",
121   NULL, // from branch
122   NULL, // to branch
123   NULL, // label
124   NULL, // operand
125   NULL, // flow block
126   2,    // num ops
127   0,0,  // dest, bit instruction
128   0,0,  // branch, skip
129   (PCC_W | PCC_REGISTER),   // inCond
130   (PCC_W | PCC_Z) // outCond
131 };
132
133 pCodeInstruction pciADDLW = {
134   {PC_OPCODE, NULL, NULL, 0, NULL, 
135    //   genericAnalyze,
136    genericDestruct,
137    genericPrint},
138   POC_ADDLW,
139   "ADDLW",
140   NULL, // from branch
141   NULL, // to branch
142   NULL, // label
143   NULL, // operand
144   NULL, // flow block
145   1,    // num ops
146   0,0,  // dest, bit instruction
147   0,0,  // branch, skip
148   PCC_W,   // inCond
149   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
150 };
151
152 pCodeInstruction pciANDLW = {
153   {PC_OPCODE, NULL, NULL, 0, NULL, 
154    //   genericAnalyze,
155    genericDestruct,
156    genericPrint},
157   POC_ANDLW,
158   "ANDLW",
159   NULL, // from branch
160   NULL, // to branch
161   NULL, // label
162   NULL, // operand
163   NULL, // flow block
164   1,    // num ops
165   0,0,  // dest, bit instruction
166   0,0,  // branch, skip
167   PCC_W,   // inCond
168   (PCC_W | PCC_Z) // outCond
169 };
170
171 pCodeInstruction pciANDWF = {
172   {PC_OPCODE, NULL, NULL, 0, NULL, 
173    //   genericAnalyze,
174    genericDestruct,
175    genericPrint},
176   POC_ANDWF,
177   "ANDWF",
178   NULL, // from branch
179   NULL, // to branch
180   NULL, // label
181   NULL, // operand
182   NULL, // flow block
183   2,    // num ops
184   1,0,  // dest, bit instruction
185   0,0,  // branch, skip
186   (PCC_W | PCC_REGISTER),   // inCond
187   (PCC_REGISTER | PCC_Z) // outCond
188 };
189
190 pCodeInstruction pciANDFW = {
191   {PC_OPCODE, NULL, NULL, 0, NULL, 
192    //   genericAnalyze,
193    genericDestruct,
194    genericPrint},
195   POC_ANDWF,
196   "ANDWF",
197   NULL, // from branch
198   NULL, // to branch
199   NULL, // label
200   NULL, // operand
201   NULL, // flow block
202   2,    // num ops
203   0,0,  // dest, bit instruction
204   0,0,  // branch, skip
205   (PCC_W | PCC_REGISTER),   // inCond
206   (PCC_W | PCC_Z) // outCond
207 };
208
209 pCodeInstruction pciBCF = {
210   {PC_OPCODE, NULL, NULL, 0, NULL, 
211    //   genericAnalyze,
212    genericDestruct,
213    genericPrint},
214   POC_BCF,
215   "BCF",
216   NULL, // from branch
217   NULL, // to branch
218   NULL, // label
219   NULL, // operand
220   NULL, // flow block
221   2,    // num ops
222   1,1,  // dest, bit instruction
223   0,0,  // branch, skip
224   PCC_REGISTER,   // inCond
225   PCC_REGISTER // outCond
226 };
227
228 pCodeInstruction pciBSF = {
229   {PC_OPCODE, NULL, NULL, 0, NULL, 
230    //   genericAnalyze,
231    genericDestruct,
232    genericPrint},
233   POC_BSF,
234   "BSF",
235   NULL, // from branch
236   NULL, // to branch
237   NULL, // label
238   NULL, // operand
239   NULL, // flow block
240   2,    // num ops
241   1,1,  // dest, bit instruction
242   0,0,  // branch, skip
243   PCC_REGISTER,   // inCond
244   PCC_REGISTER // outCond
245 };
246
247 pCodeInstruction pciBTFSC = {
248   {PC_OPCODE, NULL, NULL, 0, NULL, 
249    //   AnalyzeSKIP,
250    genericDestruct,
251    genericPrint},
252   POC_BTFSC,
253   "BTFSC",
254   NULL, // from branch
255   NULL, // to branch
256   NULL, // label
257   NULL, // operand
258   NULL, // flow block
259   2,    // num ops
260   0,1,  // dest, bit instruction
261   1,1,  // branch, skip
262   PCC_REGISTER,   // inCond
263   PCC_NONE // outCond
264 };
265
266 pCodeInstruction pciBTFSS = {
267   {PC_OPCODE, NULL, NULL, 0, NULL, 
268    //   AnalyzeSKIP,
269    genericDestruct,
270    genericPrint},
271   POC_BTFSS,
272   "BTFSS",
273   NULL, // from branch
274   NULL, // to branch
275   NULL, // label
276   NULL, // operand
277   NULL, // flow block
278   2,    // num ops
279   0,1,  // dest, bit instruction
280   1,1,  // branch, skip
281   PCC_REGISTER,   // inCond
282   PCC_NONE // outCond
283 };
284
285 pCodeInstruction pciCALL = {
286   {PC_OPCODE, NULL, NULL, 0, NULL, 
287    //   genericAnalyze,
288    genericDestruct,
289    genericPrint},
290   POC_CALL,
291   "CALL",
292   NULL, // from branch
293   NULL, // to branch
294   NULL, // label
295   NULL, // operand
296   NULL, // flow block
297   1,    // num ops
298   0,0,  // dest, bit instruction
299   1,0,  // branch, skip
300   PCC_NONE, // inCond
301   PCC_NONE  // outCond
302 };
303
304 pCodeInstruction pciCOMF = {
305   {PC_OPCODE, NULL, NULL, 0, NULL, 
306    //   genericAnalyze,
307    genericDestruct,
308    genericPrint},
309   POC_COMF,
310   "COMF",
311   NULL, // from branch
312   NULL, // to branch
313   NULL, // label
314   NULL, // operand
315   NULL, // flow block
316   2,    // num ops
317   1,0,  // dest, bit instruction
318   0,0,  // branch, skip
319   PCC_REGISTER,  // inCond
320   PCC_REGISTER   // outCond
321 };
322
323 pCodeInstruction pciCOMFW = {
324   {PC_OPCODE, NULL, NULL, 0, NULL, 
325    //   genericAnalyze,
326    genericDestruct,
327    genericPrint},
328   POC_COMFW,
329   "COMF",
330   NULL, // from branch
331   NULL, // to branch
332   NULL, // label
333   NULL, // operand
334   NULL, // flow block
335   2,    // num ops
336   0,0,  // dest, bit instruction
337   0,0,  // branch, skip
338   PCC_REGISTER,  // inCond
339   PCC_W   // outCond
340 };
341
342 pCodeInstruction pciCLRF = {
343   {PC_OPCODE, NULL, NULL, 0, NULL, 
344    //   genericAnalyze,
345    genericDestruct,
346    genericPrint},
347   POC_CLRF,
348   "CLRF",
349   NULL, // from branch
350   NULL, // to branch
351   NULL, // label
352   NULL, // operand
353   NULL, // flow block
354   1,    // num ops
355   0,0,  // dest, bit instruction
356   0,0,  // branch, skip
357   PCC_REGISTER, // inCond
358   PCC_REGISTER  // outCond
359 };
360
361 pCodeInstruction pciCLRW = {
362   {PC_OPCODE, NULL, NULL, 0, NULL, 
363    //   genericAnalyze,
364    genericDestruct,
365    genericPrint},
366   POC_CLRW,
367   "CLRW",
368   NULL, // from branch
369   NULL, // to branch
370   NULL, // label
371   NULL, // operand
372   NULL, // flow block
373   0,    // num ops
374   0,0,  // dest, bit instruction
375   0,0,  // branch, skip
376   PCC_W, // inCond
377   PCC_W  // outCond
378 };
379
380 pCodeInstruction pciDECF = {
381   {PC_OPCODE, NULL, NULL, 0, NULL, 
382    //   genericAnalyze,
383    genericDestruct,
384    genericPrint},
385   POC_DECF,
386   "DECF",
387   NULL, // from branch
388   NULL, // to branch
389   NULL, // label
390   NULL, // operand
391   NULL, // flow block
392   2,    // num ops
393   1,0,  // dest, bit instruction
394   0,0,  // branch, skip
395   PCC_REGISTER,   // inCond
396   PCC_REGISTER    // outCond
397 };
398
399 pCodeInstruction pciDECFW = {
400   {PC_OPCODE, NULL, NULL, 0, NULL, 
401    //   genericAnalyze,
402    genericDestruct,
403    genericPrint},
404   POC_DECFW,
405   "DECF",
406   NULL, // from branch
407   NULL, // to branch
408   NULL, // label
409   NULL, // operand
410   NULL, // flow block
411   2,    // num ops
412   0,0,  // dest, bit instruction
413   0,0,  // branch, skip
414   PCC_REGISTER,   // inCond
415   PCC_W    // outCond
416 };
417
418 pCodeInstruction pciDECFSZ = {
419   {PC_OPCODE, NULL, NULL, 0, NULL, 
420    //   AnalyzeSKIP,
421    genericDestruct,
422    genericPrint},
423   POC_DECFSZ,
424   "DECFSZ",
425   NULL, // from branch
426   NULL, // to branch
427   NULL, // label
428   NULL, // operand
429   NULL, // flow block
430   2,    // num ops
431   1,0,  // dest, bit instruction
432   1,1,  // branch, skip
433   PCC_REGISTER,   // inCond
434   PCC_REGISTER    // outCond
435 };
436
437 pCodeInstruction pciDECFSZW = {
438   {PC_OPCODE, NULL, NULL, 0, NULL, 
439    //   AnalyzeSKIP,
440    genericDestruct,
441    genericPrint},
442   POC_DECFSZW,
443   "DECFSZ",
444   NULL, // from branch
445   NULL, // to branch
446   NULL, // label
447   NULL, // operand
448   NULL, // flow block
449   2,    // num ops
450   0,0,  // dest, bit instruction
451   1,1,  // branch, skip
452   PCC_REGISTER,   // inCond
453   PCC_W           // outCond
454 };
455
456 pCodeInstruction pciGOTO = {
457   {PC_OPCODE, NULL, NULL, 0, NULL, 
458    //   AnalyzeGOTO,
459    genericDestruct,
460    genericPrint},
461   POC_GOTO,
462   "GOTO",
463   NULL, // from branch
464   NULL, // to branch
465   NULL, // label
466   NULL, // operand
467   NULL, // flow block
468   1,    // num ops
469   0,0,  // dest, bit instruction
470   1,0,  // branch, skip
471   PCC_NONE,   // inCond
472   PCC_NONE    // outCond
473 };
474
475
476 pCodeInstruction pciINCF = {
477   {PC_OPCODE, NULL, NULL, 0, NULL, 
478    //   genericAnalyze,
479    genericDestruct,
480    genericPrint},
481   POC_INCF,
482   "INCF",
483   NULL, // from branch
484   NULL, // to branch
485   NULL, // label
486   NULL, // operand
487   NULL, // flow block
488   2,    // num ops
489   1,0,  // dest, bit instruction
490   0,0,  // branch, skip
491   PCC_REGISTER,   // inCond
492   PCC_REGISTER    // outCond
493 };
494
495 pCodeInstruction pciINCFW = {
496   {PC_OPCODE, NULL, NULL, 0, NULL, 
497    //   genericAnalyze,
498    genericDestruct,
499    genericPrint},
500   POC_INCFW,
501   "INCF",
502   NULL, // from branch
503   NULL, // to branch
504   NULL, // label
505   NULL, // operand
506   NULL, // flow block
507   2,    // num ops
508   0,0,  // dest, bit instruction
509   0,0,  // branch, skip
510   PCC_REGISTER,   // inCond
511   PCC_W    // outCond
512 };
513
514 pCodeInstruction pciINCFSZ = {
515   {PC_OPCODE, NULL, NULL, 0, NULL, 
516    //   AnalyzeSKIP,
517    genericDestruct,
518    genericPrint},
519   POC_INCFSZ,
520   "INCFSZ",
521   NULL, // from branch
522   NULL, // to branch
523   NULL, // label
524   NULL, // operand
525   NULL, // flow block
526   2,    // num ops
527   1,0,  // dest, bit instruction
528   1,1,  // branch, skip
529   PCC_REGISTER,   // inCond
530   PCC_REGISTER    // outCond
531 };
532
533 pCodeInstruction pciINCFSZW = {
534   {PC_OPCODE, NULL, NULL, 0, NULL, 
535    //   AnalyzeSKIP,
536    genericDestruct,
537    genericPrint},
538   POC_INCFSZW,
539   "INCFSZ",
540   NULL, // from branch
541   NULL, // to branch
542   NULL, // label
543   NULL, // operand
544   NULL, // flow block
545   2,    // num ops
546   0,0,  // dest, bit instruction
547   1,1,  // branch, skip
548   PCC_REGISTER,   // inCond
549   PCC_W           // outCond
550 };
551
552 pCodeInstruction pciIORWF = {
553   {PC_OPCODE, NULL, NULL, 0, NULL, 
554    //   genericAnalyze,
555    genericDestruct,
556    genericPrint},
557   POC_IORWF,
558   "IORWF",
559   NULL, // from branch
560   NULL, // to branch
561   NULL, // label
562   NULL, // operand
563   NULL, // flow block
564   2,    // num ops
565   1,0,  // dest, bit instruction
566   0,0,  // branch, skip
567   (PCC_W | PCC_REGISTER),   // inCond
568   (PCC_REGISTER | PCC_Z) // outCond
569 };
570
571 pCodeInstruction pciIORFW = {
572   {PC_OPCODE, NULL, NULL, 0, NULL, 
573    //   genericAnalyze,
574    genericDestruct,
575    genericPrint},
576   POC_IORWF,
577   "IORWF",
578   NULL, // from branch
579   NULL, // to branch
580   NULL, // label
581   NULL, // operand
582   NULL, // flow block
583   2,    // num ops
584   0,0,  // dest, bit instruction
585   0,0,  // branch, skip
586   (PCC_W | PCC_REGISTER),   // inCond
587   (PCC_W | PCC_Z) // outCond
588 };
589
590 pCodeInstruction pciIORLW = {
591   {PC_OPCODE, NULL, NULL, 0, NULL, 
592    //   genericAnalyze,
593    genericDestruct,
594    genericPrint},
595   POC_IORLW,
596   "IORLW",
597   NULL, // from branch
598   NULL, // to branch
599   NULL, // label
600   NULL, // operand
601   NULL, // flow block
602   1,    // num ops
603   0,0,  // dest, bit instruction
604   0,0,  // branch, skip
605   PCC_W,   // inCond
606   (PCC_W | PCC_Z) // outCond
607 };
608
609 pCodeInstruction pciMOVF = {
610   {PC_OPCODE, NULL, NULL, 0, NULL, 
611    //   genericAnalyze,
612    genericDestruct,
613    genericPrint},
614   POC_MOVF,
615   "MOVF",
616   NULL, // from branch
617   NULL, // to branch
618   NULL, // label
619   NULL, // operand
620   NULL, // flow block
621   2,    // num ops
622   1,0,  // dest, bit instruction
623   0,0,  // branch, skip
624   PCC_REGISTER,   // inCond
625   PCC_Z // outCond
626 };
627
628 pCodeInstruction pciMOVFW = {
629   {PC_OPCODE, NULL, NULL, 0, NULL, 
630    //   genericAnalyze,
631    genericDestruct,
632    genericPrint},
633   POC_MOVFW,
634   "MOVF",
635   NULL, // from branch
636   NULL, // to branch
637   NULL, // label
638   NULL, // operand
639   NULL, // flow block
640   2,    // num ops
641   0,0,  // dest, bit instruction
642   0,0,  // branch, skip
643   PCC_REGISTER,   // inCond
644   (PCC_W | PCC_Z) // outCond
645 };
646
647 pCodeInstruction pciMOVWF = {
648   {PC_OPCODE, NULL, NULL, 0, NULL, 
649    //   genericAnalyze,
650    genericDestruct,
651    genericPrint},
652   POC_MOVWF,
653   "MOVWF",
654   NULL, // from branch
655   NULL, // to branch
656   NULL, // label
657   NULL, // operand
658   NULL, // flow block
659   1,    // num ops
660   0,0,  // dest, bit instruction
661   0,0,  // branch, skip
662   PCC_W,   // inCond
663   PCC_REGISTER // outCond
664 };
665
666 pCodeInstruction pciMOVLW = {
667   {PC_OPCODE, NULL, NULL, 0, NULL, 
668    //   genericAnalyze,
669    genericDestruct,
670    genericPrint},
671   POC_MOVLW,
672   "MOVLW",
673   NULL, // from branch
674   NULL, // to branch
675   NULL, // label
676   NULL, // operand
677   NULL, // flow block
678   1,    // num ops
679   0,0,  // dest, bit instruction
680   0,0,  // branch, skip
681   PCC_NONE,   // inCond
682   PCC_W // outCond
683 };
684
685 pCodeInstruction pciNOP = {
686   {PC_OPCODE, NULL, NULL, 0, NULL, 
687    genericDestruct,
688    genericPrint},
689   POC_NOP,
690   "NOP",
691   NULL, // from branch
692   NULL, // to branch
693   NULL, // label
694   NULL, // operand
695   NULL, // flow block
696   0,    // num ops
697   0,0,  // dest, bit instruction
698   0,0,  // branch, skip
699   PCC_NONE,   // inCond
700   PCC_NONE // outCond
701 };
702
703 pCodeInstruction pciRETFIE = {
704   {PC_OPCODE, NULL, NULL, 0, NULL, 
705    //   AnalyzeRETURN,
706    genericDestruct,
707    genericPrint},
708   POC_RETFIE,
709   "RETFIE",
710   NULL, // from branch
711   NULL, // to branch
712   NULL, // label
713   NULL, // operand
714   NULL, // flow block
715   0,    // num ops
716   0,0,  // dest, bit instruction
717   1,0,  // branch, skip
718   PCC_NONE,   // inCond
719   PCC_NONE // outCond (not true... affects the GIE bit too)
720 };
721
722 pCodeInstruction pciRETLW = {
723   {PC_OPCODE, NULL, NULL, 0, NULL, 
724    //   AnalyzeRETURN,
725    genericDestruct,
726    genericPrint},
727   POC_RETLW,
728   "RETLW",
729   NULL, // from branch
730   NULL, // to branch
731   NULL, // label
732   NULL, // operand
733   NULL, // flow block
734   1,    // num ops
735   0,0,  // dest, bit instruction
736   1,0,  // branch, skip
737   PCC_NONE,   // inCond
738   PCC_W // outCond
739 };
740
741 pCodeInstruction pciRETURN = {
742   {PC_OPCODE, NULL, NULL, 0, NULL, 
743    //   AnalyzeRETURN,
744    genericDestruct,
745    genericPrint},
746   POC_RETURN,
747   "RETURN",
748   NULL, // from branch
749   NULL, // to branch
750   NULL, // label
751   NULL, // operand
752   NULL, // flow block
753   0,    // num ops
754   0,0,  // dest, bit instruction
755   1,0,  // branch, skip
756   PCC_NONE,   // inCond
757   PCC_NONE // outCond
758 };
759
760 pCodeInstruction pciRLF = {
761   {PC_OPCODE, NULL, NULL, 0, NULL, 
762    //   genericAnalyze,
763    genericDestruct,
764    genericPrint},
765   POC_RLF,
766   "RLF",
767   NULL, // from branch
768   NULL, // to branch
769   NULL, // label
770   NULL, // operand
771   NULL, // flow block
772   2,    // num ops
773   1,0,  // dest, bit instruction
774   0,0,  // branch, skip
775   (PCC_C | PCC_REGISTER),   // inCond
776   (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
777 };
778
779 pCodeInstruction pciRLFW = {
780   {PC_OPCODE, NULL, NULL, 0, NULL, 
781    //   genericAnalyze,
782    genericDestruct,
783    genericPrint},
784   POC_RLFW,
785   "RLF",
786   NULL, // from branch
787   NULL, // to branch
788   NULL, // label
789   NULL, // operand
790   NULL, // flow block
791   2,    // num ops
792   0,0,  // dest, bit instruction
793   0,0,  // branch, skip
794   (PCC_C | PCC_REGISTER),   // inCond
795   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
796 };
797
798 pCodeInstruction pciRRF = {
799   {PC_OPCODE, NULL, NULL, 0, NULL, 
800    //   genericAnalyze,
801    genericDestruct,
802    genericPrint},
803   POC_RRF,
804   "RRF",
805   NULL, // from branch
806   NULL, // to branch
807   NULL, // label
808   NULL, // operand
809   NULL, // flow block
810   2,    // num ops
811   1,0,  // dest, bit instruction
812   0,0,  // branch, skip
813   (PCC_C | PCC_REGISTER),   // inCond
814   (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
815 };
816
817 pCodeInstruction pciRRFW = {
818   {PC_OPCODE, NULL, NULL, 0, NULL, 
819    //   genericAnalyze,
820    genericDestruct,
821    genericPrint},
822   POC_RRFW,
823   "RRF",
824   NULL, // from branch
825   NULL, // to branch
826   NULL, // label
827   NULL, // operand
828   NULL, // flow block
829   2,    // num ops
830   0,0,  // dest, bit instruction
831   0,0,  // branch, skip
832   (PCC_C | PCC_REGISTER),   // inCond
833   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
834 };
835
836 pCodeInstruction pciSUBWF = {
837   {PC_OPCODE, NULL, NULL, 0, NULL, 
838    //   genericAnalyze,
839    genericDestruct,
840    genericPrint},
841   POC_SUBWF,
842   "SUBWF",
843   NULL, // from branch
844   NULL, // to branch
845   NULL, // label
846   NULL, // operand
847   NULL, // flow block
848   2,    // num ops
849   1,0,  // dest, bit instruction
850   0,0,  // branch, skip
851   (PCC_W | PCC_REGISTER),   // inCond
852   (PCC_REGISTER | PCC_Z) // outCond
853 };
854
855 pCodeInstruction pciSUBFW = {
856   {PC_OPCODE, NULL, NULL, 0, NULL, 
857    //   genericAnalyze,
858    genericDestruct,
859    genericPrint},
860   POC_SUBWF,
861   "SUBWF",
862   NULL, // from branch
863   NULL, // to branch
864   NULL, // label
865   NULL, // operand
866   NULL, // flow block
867   2,    // num ops
868   0,0,  // dest, bit instruction
869   0,0,  // branch, skip
870   (PCC_W | PCC_REGISTER),   // inCond
871   (PCC_W | PCC_Z) // outCond
872 };
873
874 pCodeInstruction pciSUBLW = {
875   {PC_OPCODE, NULL, NULL, 0, NULL, 
876    //   genericAnalyze,
877    genericDestruct,
878    genericPrint},
879   POC_SUBLW,
880   "SUBLW",
881   NULL, // from branch
882   NULL, // to branch
883   NULL, // label
884   NULL, // operand
885   NULL, // flow block
886   1,    // num ops
887   0,0,  // dest, bit instruction
888   0,0,  // branch, skip
889   PCC_W,   // inCond
890   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
891 };
892
893 pCodeInstruction pciSWAPF = {
894   {PC_OPCODE, NULL, NULL, 0, NULL, 
895    //   genericAnalyze,
896    genericDestruct,
897    genericPrint},
898   POC_SWAPF,
899   "SWAPF",
900   NULL, // from branch
901   NULL, // to branch
902   NULL, // label
903   NULL, // operand
904   NULL, // flow block
905   2,    // num ops
906   1,0,  // dest, bit instruction
907   0,0,  // branch, skip
908   (PCC_REGISTER),   // inCond
909   (PCC_REGISTER) // outCond
910 };
911
912 pCodeInstruction pciSWAPFW = {
913   {PC_OPCODE, NULL, NULL, 0, NULL, 
914    //   genericAnalyze,
915    genericDestruct,
916    genericPrint},
917   POC_SWAPFW,
918   "SWAPF",
919   NULL, // from branch
920   NULL, // to branch
921   NULL, // label
922   NULL, // operand
923   NULL, // flow block
924   2,    // num ops
925   0,0,  // dest, bit instruction
926   0,0,  // branch, skip
927   (PCC_REGISTER),   // inCond
928   (PCC_W) // outCond
929 };
930
931 pCodeInstruction pciTRIS = {
932   {PC_OPCODE, NULL, NULL, 0, NULL, 
933    //   genericAnalyze,
934    genericDestruct,
935    genericPrint},
936   POC_TRIS,
937   "TRIS",
938   NULL, // from branch
939   NULL, // to branch
940   NULL, // label
941   NULL, // operand
942   NULL, // flow block
943   1,    // num ops
944   0,0,  // dest, bit instruction
945   0,0,  // branch, skip
946   PCC_NONE,   // inCond
947   PCC_REGISTER // outCond
948 };
949
950 pCodeInstruction pciXORWF = {
951   {PC_OPCODE, NULL, NULL, 0, NULL, 
952    //   genericAnalyze,
953    genericDestruct,
954    genericPrint},
955   POC_XORWF,
956   "XORWF",
957   NULL, // from branch
958   NULL, // to branch
959   NULL, // label
960   NULL, // operand
961   NULL, // flow block
962   2,    // num ops
963   1,0,  // dest, bit instruction
964   0,0,  // branch, skip
965   (PCC_W | PCC_REGISTER),   // inCond
966   (PCC_REGISTER | PCC_Z) // outCond
967 };
968
969 pCodeInstruction pciXORFW = {
970   {PC_OPCODE, NULL, NULL, 0, NULL, 
971    //   genericAnalyze,
972    genericDestruct,
973    genericPrint},
974   POC_XORWF,
975   "XORWF",
976   NULL, // from branch
977   NULL, // to branch
978   NULL, // label
979   NULL, // operand
980   NULL, // flow block
981   2,    // num ops
982   0,0,  // dest, bit instruction
983   0,0,  // branch, skip
984   (PCC_W | PCC_REGISTER),   // inCond
985   (PCC_W | PCC_Z) // outCond
986 };
987
988 pCodeInstruction pciXORLW = {
989   {PC_OPCODE, NULL, NULL, 0, NULL, 
990    //   genericAnalyze,
991    genericDestruct,
992    genericPrint},
993   POC_XORLW,
994   "XORLW",
995   NULL, // from branch
996   NULL, // to branch
997   NULL, // label
998   NULL, // operand
999   NULL, // flow block
1000   1,    // num ops
1001   0,0,  // dest, bit instruction
1002   0,0,  // branch, skip
1003   PCC_W,   // inCond
1004   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1005 };
1006
1007
1008 #define MAX_PIC14MNEMONICS 100
1009 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1010
1011 /* This definition needs to be part of configure.in */
1012 // #define USE_VSNPRINTF
1013
1014 #ifdef USE_VSNPRINTF
1015   // Alas, vsnprintf is not ANSI standard, and does not exist
1016   // on Solaris (and probably other non-Gnu flavored Unixes).
1017
1018 /*-----------------------------------------------------------------*/
1019 /* SAFE_snprintf - like snprintf except the string pointer is      */
1020 /*                 after the string has been printed to. This is   */
1021 /*                 useful for printing to string as though if it   */
1022 /*                 were a stream.                                  */
1023 /*-----------------------------------------------------------------*/
1024 void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
1025 {
1026   va_list val;
1027   int len;
1028
1029   if(!str || !*str)
1030     return;
1031
1032   va_start(val, format);
1033
1034   vsnprintf(*str, *size, format, val);
1035
1036   va_end (val);
1037
1038   len = strlen(*str);
1039   if(len > *size) {
1040     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1041   }
1042
1043   *str += len;
1044   *size -= len;
1045
1046 }
1047
1048 #else  //  USE_VSNPRINTF
1049
1050 // This version is *not* safe, despite the name.
1051
1052 void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
1053 {
1054   va_list val;
1055   int len;
1056   static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1057
1058   if(!str || !*str)
1059     return;
1060
1061   va_start(val, format);
1062
1063   vsprintf(buffer, format, val);
1064   va_end (val);
1065
1066   len = strlen(buffer);
1067   if(len > *size) {
1068     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1069   }
1070
1071   strcpy(*str, buffer);
1072   *str += len;
1073   *size -= len;
1074
1075 }
1076
1077 #endif    //  USE_VSNPRINTF
1078     
1079
1080 extern  void initStack(int base_address, int size);
1081 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1082 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1083 extern void init_pic(void);
1084
1085 void  pCodeInitRegisters(void)
1086 {
1087
1088   initStack(0x38, 8);
1089   init_pic();
1090
1091   pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
1092   pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1093   pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
1094   pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x80);
1095   pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1096   pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
1097
1098   pc_status.rIdx = IDX_STATUS;
1099   pc_fsr.rIdx = IDX_FSR;
1100   pc_indf.rIdx = IDX_INDF;
1101   pc_intcon.rIdx = IDX_INTCON;
1102   pc_pcl.rIdx = IDX_PCL;
1103   pc_pclath.rIdx = IDX_PCLATH;
1104
1105   pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
1106   pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80);
1107   pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
1108
1109   pc_kzero.rIdx = IDX_KZ;
1110   pc_wsave.rIdx = IDX_WSAVE;
1111   pc_ssave.rIdx = IDX_SSAVE;
1112
1113 }
1114
1115 /*-----------------------------------------------------------------*/
1116 /*  mnem2key - convert a pic mnemonic into a hash key              */
1117 /*   (BTW - this spreads the mnemonics quite well)                 */
1118 /*                                                                 */
1119 /*-----------------------------------------------------------------*/
1120
1121 int mnem2key(char const *mnem)
1122 {
1123   int key = 0;
1124
1125   if(!mnem)
1126     return 0;
1127
1128   while(*mnem) {
1129
1130     key += toupper(*mnem++) +1;
1131
1132   }
1133
1134   return (key & 0x1f);
1135
1136 }
1137
1138 void pic14initMnemonics(void)
1139 {
1140   int i = 0;
1141   int key;
1142   //  char *str;
1143   pCodeInstruction *pci;
1144
1145   if(mnemonics_initialized)
1146     return;
1147
1148   pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1149   pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1150   pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1151   pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1152   pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1153   pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1154   pic14Mnemonics[POC_BCF] = &pciBCF;
1155   pic14Mnemonics[POC_BSF] = &pciBSF;
1156   pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1157   pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1158   pic14Mnemonics[POC_CALL] = &pciCALL;
1159   pic14Mnemonics[POC_COMF] = &pciCOMF;
1160   pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1161   pic14Mnemonics[POC_CLRF] = &pciCLRF;
1162   pic14Mnemonics[POC_CLRW] = &pciCLRW;
1163   pic14Mnemonics[POC_DECF] = &pciDECF;
1164   pic14Mnemonics[POC_DECFW] = &pciDECFW;
1165   pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1166   pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1167   pic14Mnemonics[POC_GOTO] = &pciGOTO;
1168   pic14Mnemonics[POC_INCF] = &pciINCF;
1169   pic14Mnemonics[POC_INCFW] = &pciINCFW;
1170   pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1171   pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1172   pic14Mnemonics[POC_IORLW] = &pciIORLW;
1173   pic14Mnemonics[POC_IORWF] = &pciIORWF;
1174   pic14Mnemonics[POC_IORFW] = &pciIORFW;
1175   pic14Mnemonics[POC_MOVF] = &pciMOVF;
1176   pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1177   pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1178   pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1179   pic14Mnemonics[POC_NOP] = &pciNOP;
1180   pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1181   pic14Mnemonics[POC_RETLW] = &pciRETLW;
1182   pic14Mnemonics[POC_RETURN] = &pciRETURN;
1183   pic14Mnemonics[POC_RLF] = &pciRLF;
1184   pic14Mnemonics[POC_RLFW] = &pciRLFW;
1185   pic14Mnemonics[POC_RRF] = &pciRRF;
1186   pic14Mnemonics[POC_RRFW] = &pciRRFW;
1187   pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1188   pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1189   pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1190   pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1191   pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1192   pic14Mnemonics[POC_TRIS] = &pciTRIS;
1193   pic14Mnemonics[POC_XORLW] = &pciXORLW;
1194   pic14Mnemonics[POC_XORWF] = &pciXORWF;
1195   pic14Mnemonics[POC_XORFW] = &pciXORFW;
1196
1197   for(i=0; i<MAX_PIC14MNEMONICS; i++)
1198     if(pic14Mnemonics[i])
1199       hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1200   pci = hTabFirstItem(pic14MnemonicsHash, &key);
1201
1202   while(pci) {
1203     DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1204     pci = hTabNextItem(pic14MnemonicsHash, &key);
1205   }
1206
1207   mnemonics_initialized = 1;
1208 }
1209
1210 int getpCode(char *mnem,unsigned dest)
1211 {
1212
1213   pCodeInstruction *pci;
1214   int key = mnem2key(mnem);
1215
1216   if(!mnemonics_initialized)
1217     pic14initMnemonics();
1218
1219   pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1220
1221   while(pci) {
1222
1223     if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1224       if((pci->num_ops <= 1) || (pci->isModReg == dest))
1225         return(pci->op);
1226     }
1227
1228     pci = hTabNextItemWK (pic14MnemonicsHash);
1229   
1230   }
1231
1232   return -1;
1233 }
1234
1235 char getpBlock_dbName(pBlock *pb)
1236 {
1237   if(!pb)
1238     return 0;
1239
1240   if(pb->cmemmap)
1241     return pb->cmemmap->dbName;
1242
1243   return pb->dbName;
1244 }
1245 void pBlockConvert2ISR(pBlock *pb)
1246 {
1247   if(!pb)
1248     return;
1249
1250   if(pb->cmemmap)
1251     pb->cmemmap = NULL;
1252
1253   pb->dbName = 'I';
1254 }
1255
1256 /*-----------------------------------------------------------------*/
1257 /* movepBlock2Head - given the dbname of a pBlock, move all        */
1258 /*                   instances to the front of the doubly linked   */
1259 /*                   list of pBlocks                               */
1260 /*-----------------------------------------------------------------*/
1261
1262 void movepBlock2Head(char dbName)
1263 {
1264   pBlock *pb;
1265
1266   pb = the_pFile->pbHead;
1267
1268   while(pb) {
1269
1270     if(getpBlock_dbName(pb) == dbName) {
1271       pBlock *pbn = pb->next;
1272       pb->next = the_pFile->pbHead;
1273       the_pFile->pbHead->prev = pb;
1274       the_pFile->pbHead = pb;
1275
1276       if(pb->prev)
1277         pb->prev->next = pbn;
1278
1279       // If the pBlock that we just moved was the last
1280       // one in the link of all of the pBlocks, then we
1281       // need to point the tail to the block just before
1282       // the one we moved.
1283       // Note: if pb->next is NULL, then pb must have 
1284       // been the last pBlock in the chain.
1285
1286       if(pbn)
1287         pbn->prev = pb->prev;
1288       else
1289         the_pFile->pbTail = pb->prev;
1290
1291       pb = pbn;
1292
1293     } else
1294       pb = pb->next;
1295
1296   }
1297
1298 }
1299
1300 void copypCode(FILE *of, char dbName)
1301 {
1302   pBlock *pb;
1303
1304   if(!of || !the_pFile)
1305     return;
1306
1307   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1308     if(getpBlock_dbName(pb) == dbName) {
1309       pBlockStats(of,pb);
1310       printpBlock(of,pb);
1311     }
1312   }
1313
1314 }
1315 void pcode_test(void)
1316 {
1317
1318   DFPRINTF((stderr,"pcode is alive!\n"));
1319
1320   //initMnemonics();
1321
1322   if(the_pFile) {
1323
1324     pBlock *pb;
1325     FILE *pFile;
1326     char buffer[100];
1327
1328     /* create the file name */
1329     strcpy(buffer,srcFileName);
1330     strcat(buffer,".p");
1331
1332     if( !(pFile = fopen(buffer, "w" ))) {
1333       werror(E_FILE_OPEN_ERR,buffer);
1334       exit(1);
1335     }
1336
1337     fprintf(pFile,"pcode dump\n\n");
1338
1339     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1340       fprintf(pFile,"\n\tNew pBlock\n\n");
1341       if(pb->cmemmap)
1342         fprintf(pFile,"%s",pb->cmemmap->sname);
1343       else
1344         fprintf(pFile,"internal pblock");
1345
1346       fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1347       printpBlock(pFile,pb);
1348     }
1349   }
1350 }
1351 /*-----------------------------------------------------------------*/
1352 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg-  */
1353 /*      ister, RegCond will return the bit being referenced.       */
1354 /*                                                                 */
1355 /* fixme - why not just OR in the pcop bit field                   */
1356 /*-----------------------------------------------------------------*/
1357
1358 static int RegCond(pCodeOp *pcop)
1359 {
1360
1361   if(!pcop)
1362     return 0;
1363
1364   if(pcop->type == PO_GPR_BIT  && !strcmp(pcop->name, pc_status.pcop.name)) {
1365     switch(PCORB(pcop)->bit) {
1366     case PIC_C_BIT:
1367       return PCC_C;
1368     case PIC_DC_BIT:
1369         return PCC_DC;
1370     case PIC_Z_BIT:
1371       return PCC_Z;
1372     }
1373
1374   }
1375
1376   return 0;
1377 }
1378
1379 /*-----------------------------------------------------------------*/
1380 /* newpCode - create and return a newly initialized pCode          */
1381 /*                                                                 */
1382 /*  fixme - rename this                                            */
1383 /*                                                                 */
1384 /* The purpose of this routine is to create a new Instruction      */
1385 /* pCode. This is called by gen.c while the assembly code is being */
1386 /* generated.                                                      */
1387 /*                                                                 */
1388 /* Inouts:                                                         */
1389 /*  PIC_OPCODE op - the assembly instruction we wish to create.    */
1390 /*                  (note that the op is analogous to but not the  */
1391 /*                  same thing as the opcode of the instruction.)  */
1392 /*  pCdoeOp *pcop - pointer to the operand of the instruction.     */
1393 /*                                                                 */
1394 /* Outputs:                                                        */
1395 /*  a pointer to the new malloc'd pCode is returned.               */
1396 /*                                                                 */
1397 /*                                                                 */
1398 /*                                                                 */
1399 /*-----------------------------------------------------------------*/
1400 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1401 {
1402   pCodeInstruction *pci ;
1403
1404   if(!mnemonics_initialized)
1405     pic14initMnemonics();
1406     
1407   pci = Safe_calloc(1, sizeof(pCodeInstruction));
1408
1409   if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1410     memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1411     pci->pcop = pcop;
1412
1413     if(pci->inCond == PCC_EXAMINE_PCOP)
1414       pci->inCond   = RegCond(pcop);
1415
1416     if(pci->outCond == PCC_EXAMINE_PCOP)
1417       pci->outCond   = RegCond(pcop);
1418
1419     pci->pc.prev = pci->pc.next = NULL;
1420     return (pCode *)pci;
1421   }
1422
1423   fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1424   exit(1);
1425
1426   return NULL;
1427 }       
1428
1429 /*-----------------------------------------------------------------*/
1430 /* newpCodeWild - create a "wild" as in wild card pCode            */
1431 /*                                                                 */
1432 /* Wild pcodes are used during the peep hole optimizer to serve    */
1433 /* as place holders for any instruction. When a snippet of code is */
1434 /* compared to a peep hole rule, the wild card opcode will match   */
1435 /* any instruction. However, the optional operand and label are    */
1436 /* additional qualifiers that must also be matched before the      */
1437 /* line (of assembly code) is declared matched. Note that the      */
1438 /* operand may be wild too.                                        */
1439 /*                                                                 */
1440 /*   Note, a wild instruction is specified just like a wild var:   */
1441 /*      %4     ; A wild instruction,                               */
1442 /*  See the peeph.def file for additional examples                 */
1443 /*                                                                 */
1444 /*-----------------------------------------------------------------*/
1445
1446 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1447 {
1448
1449   pCodeWild *pcw;
1450     
1451   pcw = Safe_calloc(1,sizeof(pCodeWild));
1452
1453   pcw->pci.pc.type = PC_WILD;
1454   pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1455   pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1456   pcw->pci.pc.pb = NULL;
1457
1458   //  pcw->pci.pc.analyze = genericAnalyze;
1459   pcw->pci.pc.destruct = genericDestruct;
1460   pcw->pci.pc.print = genericPrint;
1461
1462   pcw->id = pCodeID;              // this is the 'n' in %n
1463   pcw->operand = optional_operand;
1464   pcw->label   = optional_label;
1465
1466   return ( (pCode *)pcw);
1467   
1468 }
1469
1470 /*-----------------------------------------------------------------*/
1471 /* newPcodeCharP - create a new pCode from a char string           */
1472 /*-----------------------------------------------------------------*/
1473
1474 pCode *newpCodeCharP(char *cP)
1475 {
1476
1477   pCodeComment *pcc ;
1478     
1479   pcc = Safe_calloc(1,sizeof(pCodeComment));
1480
1481   pcc->pc.type = PC_COMMENT;
1482   pcc->pc.prev = pcc->pc.next = NULL;
1483   //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1484   pcc->pc.pb = NULL;
1485
1486   //  pcc->pc.analyze = genericAnalyze;
1487   pcc->pc.destruct = genericDestruct;
1488   pcc->pc.print = genericPrint;
1489
1490   if(cP)
1491     pcc->comment = Safe_strdup(cP);
1492   else
1493     pcc->comment = NULL;
1494
1495   return ( (pCode *)pcc);
1496
1497 }
1498
1499 /*-----------------------------------------------------------------*/
1500 /* newpCodeFunction -                                              */
1501 /*-----------------------------------------------------------------*/
1502
1503
1504 pCode *newpCodeFunction(char *mod,char *f)
1505 {
1506   pCodeFunction *pcf;
1507
1508   pcf = Safe_calloc(1,sizeof(pCodeFunction));
1509   //_ALLOC(pcf,sizeof(pCodeFunction));
1510
1511   pcf->pc.type = PC_FUNCTION;
1512   pcf->pc.prev = pcf->pc.next = NULL;
1513   //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1514   pcf->pc.pb = NULL;
1515
1516   //  pcf->pc.analyze = genericAnalyze;
1517   pcf->pc.destruct = genericDestruct;
1518   pcf->pc.print = pCodePrintFunction;
1519
1520   if(mod) {
1521     //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1522     pcf->modname = Safe_calloc(1,strlen(mod)+1);
1523     strcpy(pcf->modname,mod);
1524   } else
1525     pcf->modname = NULL;
1526
1527   if(f) {
1528     //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1529     pcf->fname = Safe_calloc(1,strlen(f)+1);
1530     strcpy(pcf->fname,f);
1531   } else
1532     pcf->fname = NULL;
1533
1534   return ( (pCode *)pcf);
1535
1536 }
1537
1538 /*-----------------------------------------------------------------*/
1539 /* newpCodeFlow                                                    */
1540 /*-----------------------------------------------------------------*/
1541
1542
1543 pCode *newpCodeFlow(void )
1544 {
1545   pCodeFlow *pcflow;
1546
1547   //_ALLOC(pcflow,sizeof(pCodeFlow));
1548   pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1549
1550   pcflow->pc.type = PC_FLOW;
1551   pcflow->pc.prev = pcflow->pc.next = NULL;
1552   //pcflow->pc.from = pcflow->pc.to = pcflow->pc.label = NULL;
1553   pcflow->pc.pb = NULL;
1554
1555   //  pcflow->pc.analyze = genericAnalyze;
1556   pcflow->pc.destruct = genericDestruct;
1557   pcflow->pc.print = genericPrint;
1558
1559   pcflow->pc.seq = GpcFlowSeq++;
1560
1561   pcflow->nuses = 7;
1562   pcflow->uses = Safe_calloc(pcflow->nuses, sizeof(set *));
1563
1564   pcflow->from = pcflow->to = NULL;
1565
1566   pcflow->inCond = PCC_NONE;
1567   pcflow->outCond = PCC_NONE;
1568
1569   pcflow->end = NULL;
1570   return ( (pCode *)pcflow);
1571
1572 }
1573
1574 /*-----------------------------------------------------------------*/
1575 /* pCodeLabelDestruct - free memory used by a label.               */
1576 /*-----------------------------------------------------------------*/
1577 static void pCodeLabelDestruct(pCode *pc)
1578 {
1579
1580   if(!pc)
1581     return;
1582
1583   if((pc->type == PC_LABEL) && PCL(pc)->label)
1584     free(PCL(pc)->label);
1585
1586   free(pc);
1587
1588 }
1589
1590 pCode *newpCodeLabel(char *name, int key)
1591 {
1592
1593   char *s = buffer;
1594   pCodeLabel *pcl;
1595     
1596   pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1597
1598   pcl->pc.type = PC_LABEL;
1599   pcl->pc.prev = pcl->pc.next = NULL;
1600   //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1601   pcl->pc.pb = NULL;
1602
1603   //  pcl->pc.analyze = genericAnalyze;
1604   pcl->pc.destruct = pCodeLabelDestruct;
1605   pcl->pc.print = pCodePrintLabel;
1606
1607   pcl->key = key;
1608
1609   pcl->label = NULL;
1610   if(key>0) {
1611     sprintf(s,"_%05d_DS_",key);
1612   } else
1613     s = name;
1614
1615   if(s)
1616     pcl->label = Safe_strdup(s);
1617
1618
1619   return ( (pCode *)pcl);
1620
1621 }
1622
1623
1624 /*-----------------------------------------------------------------*/
1625 /* newpBlock - create and return a pointer to a new pBlock         */
1626 /*-----------------------------------------------------------------*/
1627 pBlock *newpBlock(void)
1628 {
1629
1630   pBlock *PpB;
1631
1632   PpB = Safe_calloc(1,sizeof(pBlock) );
1633   PpB->next = PpB->prev = NULL;
1634
1635   PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1636   PpB->tregisters = NULL;
1637   PpB->visited = 0;
1638
1639   return PpB;
1640
1641 }
1642
1643 /*-----------------------------------------------------------------*/
1644 /* newpCodeChain - create a new chain of pCodes                    */
1645 /*-----------------------------------------------------------------*
1646  *
1647  *  This function will create a new pBlock and the pointer to the
1648  *  pCode that is passed in will be the first pCode in the block.
1649  *-----------------------------------------------------------------*/
1650
1651
1652 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1653 {
1654
1655   pBlock *pB  = newpBlock();
1656
1657   pB->pcHead  = pB->pcTail = pc;
1658   pB->cmemmap = cm;
1659   pB->dbName  = c;
1660
1661   return pB;
1662 }
1663
1664 /*-----------------------------------------------------------------*/
1665 /* newpCodeOpLabel - Create a new label given the key              */
1666 /*  Note, a negative key means that the label is part of wild card */
1667 /*  (and hence a wild card label) used in the pCodePeep            */
1668 /*   optimizations).                                               */
1669 /*-----------------------------------------------------------------*/
1670
1671 pCodeOp *newpCodeOpLabel(char *name, int key)
1672 {
1673   char *s=NULL;
1674   static int label_key=-1;
1675
1676   pCodeOp *pcop;
1677
1678   pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1679   pcop->type = PO_LABEL;
1680
1681   pcop->name = NULL;
1682
1683   if(key>0)
1684     sprintf(s=buffer,"_%05d_DS_",key);
1685   else 
1686     s = name, key = label_key--;
1687
1688   if(s)
1689     pcop->name = Safe_strdup(s);
1690
1691   ((pCodeOpLabel *)pcop)->key = key;
1692
1693   return pcop;
1694 }
1695
1696 /*-----------------------------------------------------------------*/
1697 /*-----------------------------------------------------------------*/
1698 pCodeOp *newpCodeOpLit(int lit)
1699 {
1700   char *s = buffer;
1701   pCodeOp *pcop;
1702
1703
1704   pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1705   pcop->type = PO_LITERAL;
1706
1707   pcop->name = NULL;
1708   if(lit>=0) {
1709     sprintf(s,"0x%02x",lit);
1710     if(s)
1711       pcop->name = Safe_strdup(s);
1712   }
1713
1714   ((pCodeOpLit *)pcop)->lit = lit;
1715
1716   return pcop;
1717 }
1718
1719 /*-----------------------------------------------------------------*/
1720 /*-----------------------------------------------------------------*/
1721 pCodeOp *newpCodeOpImmd(char *name, int offset)
1722 {
1723   pCodeOp *pcop;
1724
1725
1726   pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
1727   pcop->type = PO_IMMEDIATE;
1728   if(name) {
1729     pcop->name = Safe_strdup(name);
1730   } else {
1731     pcop->name = NULL;
1732   }
1733
1734
1735   PCOI(pcop)->offset = offset;
1736
1737   return pcop;
1738 }
1739
1740 /*-----------------------------------------------------------------*/
1741 /*-----------------------------------------------------------------*/
1742 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1743 {
1744   char *s = buffer;
1745   pCodeOp *pcop;
1746
1747
1748   if(!pcp || !subtype) {
1749     fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1750     exit(1);
1751   }
1752
1753   pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1754   pcop->type = PO_WILD;
1755   sprintf(s,"%%%d",id);
1756   pcop->name = Safe_strdup(s);
1757
1758   PCOW(pcop)->id = id;
1759   PCOW(pcop)->pcp = pcp;
1760   PCOW(pcop)->subtype = subtype;
1761   PCOW(pcop)->matched = NULL;
1762
1763   return pcop;
1764 }
1765
1766 /*-----------------------------------------------------------------*/
1767 /*-----------------------------------------------------------------*/
1768 pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace)
1769 {
1770   pCodeOp *pcop;
1771
1772   pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
1773   pcop->type = PO_GPR_BIT;
1774   if(s)
1775     pcop->name = Safe_strdup(s);   
1776   else
1777     pcop->name = NULL;
1778
1779   PCORB(pcop)->bit = bit;
1780   PCORB(pcop)->inBitSpace = inBitSpace;
1781
1782   return pcop;
1783 }
1784
1785 pCodeOp *newpCodeOpReg(int rIdx)
1786 {
1787   pCodeOp *pcop;
1788
1789   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1790
1791   pcop->name = NULL;
1792   PCOR(pcop)->rIdx = rIdx;
1793   PCOR(pcop)->r = pic14_regWithIdx(rIdx);
1794   pcop->type = PCOR(pcop)->r->pc_type;
1795
1796   return pcop;
1797 }
1798 pCodeOp *newpCodeOpRegFromStr(char *name)
1799 {
1800   pCodeOp *pcop;
1801
1802   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1803   PCOR(pcop)->r = allocRegByName(name);
1804   PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1805   pcop->type = PCOR(pcop)->r->pc_type;
1806   pcop->name = PCOR(pcop)->r->name;
1807
1808   return pcop;
1809 }
1810
1811 /*-----------------------------------------------------------------*/
1812 /*-----------------------------------------------------------------*/
1813
1814 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1815 {
1816   pCodeOp *pcop;
1817
1818   switch(type) {
1819   case PO_BIT:
1820   case PO_GPR_BIT:
1821     pcop = newpCodeOpBit(name, -1,0);
1822     break;
1823
1824   case PO_LITERAL:
1825     pcop = newpCodeOpLit(-1);
1826     break;
1827
1828   case PO_LABEL:
1829     pcop = newpCodeOpLabel(NULL,-1);
1830     break;
1831
1832   default:
1833     pcop = Safe_calloc(1,sizeof(pCodeOp) );
1834     pcop->type = type;
1835     if(name)
1836       pcop->name = Safe_strdup(name);   
1837     else
1838       pcop->name = NULL;
1839   }
1840
1841   return pcop;
1842 }
1843
1844 /*-----------------------------------------------------------------*/
1845 /*-----------------------------------------------------------------*/
1846 void pCodeConstString(char *name, char *value)
1847 {
1848   pBlock *pb;
1849
1850   //  fprintf(stderr, " %s  %s  %s\n",__FUNCTION__,name,value);
1851
1852   if(!name || !value)
1853     return;
1854
1855   pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
1856
1857   addpBlock(pb);
1858
1859   sprintf(buffer,"; %s = %s",name,value);
1860   
1861   addpCode2pBlock(pb,newpCodeCharP(buffer));
1862   addpCode2pBlock(pb,newpCodeLabel(name,-1));
1863
1864   do {
1865     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
1866   }while (*value++);
1867
1868
1869 }
1870
1871 /*-----------------------------------------------------------------*/
1872 /*-----------------------------------------------------------------*/
1873 void pCodeReadCodeTable(void)
1874 {
1875   pBlock *pb;
1876
1877   fprintf(stderr, " %s\n",__FUNCTION__);
1878
1879   pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
1880
1881   addpBlock(pb);
1882
1883   addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
1884   addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
1885   addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
1886   addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
1887
1888   addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
1889   addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
1890   addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
1891   addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
1892
1893
1894 }
1895
1896 /*-----------------------------------------------------------------*/
1897 /* addpCode2pBlock - place the pCode into the pBlock linked list   */
1898 /*-----------------------------------------------------------------*/
1899 void addpCode2pBlock(pBlock *pb, pCode *pc)
1900 {
1901   if(!pb->pcHead) {
1902     /* If this is the first pcode to be added to a block that
1903      * was initialized with a NULL pcode, then go ahead and
1904      * make this pcode the head and tail */
1905     pb->pcHead  = pb->pcTail = pc;
1906   } else {
1907     pb->pcTail->next = pc;
1908     pc->prev = pb->pcTail;
1909     //pc->next = NULL;
1910     pc->pb = pb;
1911     pb->pcTail = pc;
1912   }
1913 }
1914
1915 /*-----------------------------------------------------------------*/
1916 /* addpBlock - place a pBlock into the pFile                       */
1917 /*-----------------------------------------------------------------*/
1918 void addpBlock(pBlock *pb)
1919 {
1920   // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
1921
1922   if(!the_pFile) {
1923     /* First time called, we'll pass through here. */
1924     //_ALLOC(the_pFile,sizeof(pFile));
1925     the_pFile = Safe_calloc(1,sizeof(pFile));
1926     the_pFile->pbHead = the_pFile->pbTail = pb;
1927     the_pFile->functions = NULL;
1928     return;
1929   }
1930
1931   the_pFile->pbTail->next = pb;
1932   pb->prev = the_pFile->pbTail;
1933   pb->next = NULL;
1934   the_pFile->pbTail = pb;
1935 }
1936
1937 /*-----------------------------------------------------------------*/
1938 /* printpCode - write the contents of a pCode to a file            */
1939 /*-----------------------------------------------------------------*/
1940 void printpCode(FILE *of, pCode *pc)
1941 {
1942
1943   if(!pc || !of)
1944     return;
1945
1946   if(pc->print) {
1947     pc->print(of,pc);
1948     return;
1949   }
1950
1951   fprintf(of,"warning - unable to print pCode\n");
1952 }
1953
1954 /*-----------------------------------------------------------------*/
1955 /* printpBlock - write the contents of a pBlock to a file          */
1956 /*-----------------------------------------------------------------*/
1957 void printpBlock(FILE *of, pBlock *pb)
1958 {
1959   pCode *pc;
1960
1961   if(!pb)
1962     return;
1963
1964   if(!of)
1965     of = stderr;
1966
1967   for(pc = pb->pcHead; pc; pc = pc->next)
1968     printpCode(of,pc);
1969
1970 }
1971
1972 /*-----------------------------------------------------------------*/
1973 /*                                                                 */
1974 /*       pCode processing                                          */
1975 /*                                                                 */
1976 /*                                                                 */
1977 /*                                                                 */
1978 /*-----------------------------------------------------------------*/
1979
1980 static void unlinkPC(pCode *pc)
1981 {
1982
1983
1984   if(pc) {
1985     if(pc->prev) 
1986       pc->prev->next = pc->next;
1987     if(pc->next)
1988       pc->next->prev = pc->prev;
1989
1990     pc->prev = pc->next = NULL;
1991   }
1992 }
1993 static void genericDestruct(pCode *pc)
1994 {
1995   fprintf(stderr,"warning, calling default pCode destructor\n");
1996
1997   unlinkPC(pc);
1998
1999   free(pc);
2000
2001 }
2002
2003
2004 /*-----------------------------------------------------------------*/
2005 /*-----------------------------------------------------------------*/
2006 void pBlockRegs(FILE *of, pBlock *pb)
2007 {
2008
2009   regs  *r;
2010
2011   r = setFirstItem(pb->tregisters);
2012   while (r) {
2013     r = setNextItem(pb->tregisters);
2014   }
2015 }
2016
2017
2018 static char *get_op( pCodeInstruction *pcc)
2019 {
2020   regs *r;
2021   static char buffer[50];
2022   char *s;
2023   int size;
2024
2025   if(pcc && pcc->pcop) {
2026
2027
2028     switch(pcc->pcop->type) {
2029     case PO_INDF:
2030     case PO_FSR:
2031       //fprintf(stderr,"get_op getting register name rIdx=%d\n",PCOR(pcc->pcop)->rIdx);
2032       //r = pic14_regWithIdx(PCOR(pcc->pcop)->rIdx);
2033       //return r->name;
2034       return PCOR(pcc->pcop)->r->name;
2035       break;
2036     case PO_GPR_TEMP:
2037       r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
2038       //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
2039       pBlockRegs(stderr,pcc->pc.pb);
2040       return r->name;
2041
2042       //    case PO_GPR_BIT:
2043       //      return PCOR(pcc->pcop)->r)->name;
2044     case PO_IMMEDIATE:
2045       s = buffer;
2046       size = sizeof(buffer);
2047       if( PCOI(pcc->pcop)->offset && PCOI(pcc->pcop)->offset<4) {
2048         SAFE_snprintf(&s,&size,"((%s >> %d)&0xff)",
2049                       pcc->pcop->name,
2050                       8 * PCOI(pcc->pcop)->offset );
2051       } else
2052         SAFE_snprintf(&s,&size,"LOW(%s)",pcc->pcop->name);
2053
2054       
2055       return buffer;
2056
2057     default:
2058       if  (pcc->pcop->name)
2059         return pcc->pcop->name;
2060
2061     }
2062   }
2063
2064   return "NO operand";
2065 }
2066
2067 /*-----------------------------------------------------------------*/
2068 /*-----------------------------------------------------------------*/
2069 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
2070 {
2071
2072   fprintf(of,"pcodeopprint\n");
2073 }
2074
2075 char *pCode2str(char *str, int size, pCode *pc)
2076 {
2077   char *s = str;
2078
2079   switch(pc->type) {
2080
2081   case PC_OPCODE:
2082
2083     SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
2084
2085     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
2086
2087       if(PCI(pc)->isBitInst) {
2088         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2089           if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
2090             SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
2091                           PCI(pc)->pcop->name ,
2092                           PCI(pc)->pcop->name );
2093           else
2094             SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)), 
2095                           (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
2096         } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2097           SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
2098         }else
2099           SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
2100         //PCI(pc)->pcop->t.bit );
2101       } else {
2102
2103         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
2104           if( PCI(pc)->num_ops == 2)
2105             SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
2106           else
2107             SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
2108
2109         }else {
2110           SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
2111
2112           if( PCI(pc)->num_ops == 2)
2113             SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
2114         }
2115       }
2116
2117     }
2118     break;
2119
2120   case PC_COMMENT:
2121     /* assuming that comment ends with a \n */
2122     SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
2123     break;
2124
2125   case PC_LABEL:
2126     SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
2127     break;
2128   case PC_FUNCTION:
2129     SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
2130     break;
2131   case PC_WILD:
2132     SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
2133     break;
2134   case PC_FLOW:
2135     SAFE_snprintf(&s,&size,";\t--FLOW change\n");
2136     break;
2137   }
2138
2139   return str;
2140
2141 }
2142
2143 /*-----------------------------------------------------------------*/
2144 /* genericPrint - the contents of a pCode to a file                */
2145 /*-----------------------------------------------------------------*/
2146 static void genericPrint(FILE *of, pCode *pc)
2147 {
2148
2149   if(!pc || !of)
2150     return;
2151
2152   switch(pc->type) {
2153   case PC_COMMENT:
2154     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
2155     break;
2156
2157   case PC_OPCODE:
2158     // If the opcode has a label, print that first
2159     {
2160       pBranch *pbl = PCI(pc)->label;
2161       while(pbl && pbl->pc) {
2162         if(pbl->pc->type == PC_LABEL)
2163           pCodePrintLabel(of, pbl->pc);
2164         pbl = pbl->next;
2165       }
2166     }
2167
2168
2169     {
2170       char str[256];
2171       
2172       pCode2str(str, 256, pc);
2173
2174       fprintf(of,"%s",str);
2175
2176       /* Debug */
2177       fprintf(of, "\t;key=%03x",pc->seq);
2178       if(PCI(pc)->pcflow)
2179         fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
2180     }
2181 #if 0
2182     {
2183       pBranch *dpb = pc->to;   // debug
2184       while(dpb) {
2185         switch ( dpb->pc->type) {
2186         case PC_OPCODE:
2187           fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
2188           break;
2189         case PC_LABEL:
2190           fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
2191           break;
2192         case PC_FUNCTION:
2193           fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
2194           break;
2195         case PC_FLOW:
2196           fprintf(of, "\t;flow");
2197           break;
2198         case PC_COMMENT:
2199         case PC_WILD:
2200           break;
2201         }
2202         dpb = dpb->next;
2203       }
2204     }
2205 #endif
2206     fprintf(of,"\n");
2207     break;
2208
2209   case PC_WILD:
2210     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
2211     if(PCW(pc)->pci.label)
2212       pCodePrintLabel(of, PCW(pc)->pci.label->pc);
2213
2214     if(PCW(pc)->operand) {
2215       fprintf(of,";\toperand  ");
2216       pCodeOpPrint(of,PCW(pc)->operand );
2217     }
2218     break;
2219
2220   case PC_FLOW:
2221     fprintf(of,";Start of new flow, seq=%d\n",pc->seq);
2222     break;
2223
2224   case PC_LABEL:
2225   default:
2226     fprintf(of,"unknown pCode type %d\n",pc->type);
2227   }
2228
2229 }
2230
2231 /*-----------------------------------------------------------------*/
2232 /* pCodePrintFunction - prints function begin/end                  */
2233 /*-----------------------------------------------------------------*/
2234
2235 static void pCodePrintFunction(FILE *of, pCode *pc)
2236 {
2237
2238   if(!pc || !of)
2239     return;
2240
2241   if( ((pCodeFunction *)pc)->modname) 
2242     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
2243
2244   if(PCF(pc)->fname) {
2245     pBranch *exits = PCF(pc)->to;
2246     int i=0;
2247     fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
2248     while(exits) {
2249       i++;
2250       exits = exits->next;
2251     }
2252     //if(i) i--;
2253     fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
2254     
2255   }else {
2256     if((PCF(pc)->from && 
2257         PCF(pc)->from->pc->type == PC_FUNCTION &&
2258         PCF(PCF(pc)->from->pc)->fname) )
2259       fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
2260     else
2261       fprintf(of,"; exit point [can't find entry point]\n");
2262   }
2263 }
2264 /*-----------------------------------------------------------------*/
2265 /* pCodePrintLabel - prints label                                  */
2266 /*-----------------------------------------------------------------*/
2267
2268 static void pCodePrintLabel(FILE *of, pCode *pc)
2269 {
2270
2271   if(!pc || !of)
2272     return;
2273
2274   if(PCL(pc)->label) 
2275     fprintf(of,"%s\n",PCL(pc)->label);
2276   else if (PCL(pc)->key >=0) 
2277     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
2278   else
2279     fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
2280
2281 }
2282 /*-----------------------------------------------------------------*/
2283 /* unlinkpCodeFromBranch - Search for a label in a pBranch and     */
2284 /*                         remove it if it is found.               */
2285 /*-----------------------------------------------------------------*/
2286 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
2287 {
2288   pBranch *b, *bprev;
2289
2290
2291   bprev = NULL;
2292
2293   if(pcl->type == PC_OPCODE)
2294     b = PCI(pcl)->label;
2295   else {
2296     fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
2297     exit(1);
2298
2299   }
2300
2301   while(b) {
2302     if(b->pc == pc) {
2303
2304       /* Found a label */
2305       if(bprev) {
2306         bprev->next = b->next;  /* Not first pCode in chain */
2307         free(b);
2308       } else {
2309         pc->destruct(pc);
2310         PCI(pcl)->label = b->next;   /* First pCode in chain */
2311         free(b);
2312       }
2313       return;  /* A label can't occur more than once */
2314     }
2315     bprev = b;
2316     b = b->next;
2317   }
2318
2319 #if 0
2320
2321   original stuff:
2322
2323   bprev = NULL;
2324   b = pcl->label;
2325   while(b) {
2326     if(b->pc == pc) {
2327
2328       /* Found a label */
2329       if(bprev) {
2330         bprev->next = b->next;  /* Not first pCode in chain */
2331         free(b);
2332       } else {
2333         pc->destruct(pc);
2334         pcl->label = b->next;   /* First pCode in chain */
2335         free(b);
2336       }
2337       return;  /* A label can't occur more than once */
2338     }
2339     bprev = b;
2340     b = b->next;
2341   }
2342 #endif
2343 }
2344
2345 /*-----------------------------------------------------------------*/
2346 /*-----------------------------------------------------------------*/
2347 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
2348 {
2349   pBranch *b;
2350
2351   if(!h)
2352     return n;
2353
2354   b = h;
2355   while(b->next)
2356     b = b->next;
2357
2358   b->next = n;
2359
2360   return h;
2361   
2362 }  
2363 /*-----------------------------------------------------------------*/
2364 /* pBranchLink - given two pcodes, this function will link them    */
2365 /*               together through their pBranches                  */
2366 /*-----------------------------------------------------------------*/
2367 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
2368 {
2369   pBranch *b;
2370
2371   // Declare a new branch object for the 'from' pCode.
2372
2373   //_ALLOC(b,sizeof(pBranch));
2374   b = Safe_calloc(1,sizeof(pBranch));
2375   b->pc = PCODE(t);             // The link to the 'to' pCode.
2376   b->next = NULL;
2377
2378   f->to = pBranchAppend(f->to,b);
2379
2380   // Now do the same for the 'to' pCode.
2381
2382   //_ALLOC(b,sizeof(pBranch));
2383   b = Safe_calloc(1,sizeof(pBranch));
2384   b->pc = PCODE(f);
2385   b->next = NULL;
2386
2387   t->from = pBranchAppend(t->from,b);
2388   
2389 }
2390
2391 #if 0
2392 /*-----------------------------------------------------------------*/
2393 /* pBranchFind - find the pBranch in a pBranch chain that contains */
2394 /*               a pCode                                           */
2395 /*-----------------------------------------------------------------*/
2396 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
2397 {
2398   while(pb) {
2399
2400     if(pb->pc == pc)
2401       return pb;
2402
2403     pb = pb->next;
2404   }
2405
2406   return NULL;
2407 }
2408
2409 /*-----------------------------------------------------------------*/
2410 /* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
2411 /*-----------------------------------------------------------------*/
2412 static void pCodeUnlink(pCode *pc)
2413 {
2414   pBranch *pb1,*pb2;
2415   pCode *pc1;
2416
2417   if(!pc->prev || !pc->next) {
2418     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
2419     exit(1);
2420   }
2421
2422   /* first remove the pCode from the chain */
2423   pc->prev->next = pc->next;
2424   pc->next->prev = pc->prev;
2425
2426   /* Now for the hard part... */
2427
2428   /* Remove the branches */
2429
2430   pb1 = pc->from;
2431   while(pb1) {
2432     pc1 = pb1->pc;    /* Get the pCode that branches to the
2433                        * one we're unlinking */
2434
2435     /* search for the link back to this pCode (the one we're
2436      * unlinking) */
2437     if(pb2 = pBranchFind(pc1->to,pc)) {
2438       pb2->pc = pc->to->pc;  // make the replacement
2439
2440       /* if the pCode we're unlinking contains multiple 'to'
2441        * branches (e.g. this a skip instruction) then we need
2442        * to copy these extra branches to the chain. */
2443       if(pc->to->next)
2444         pBranchAppend(pb2, pc->to->next);
2445     }
2446     
2447     pb1 = pb1->next;
2448   }
2449
2450
2451 }
2452 #endif
2453 /*-----------------------------------------------------------------*/
2454 /*-----------------------------------------------------------------*/
2455 #if 0
2456 static void genericAnalyze(pCode *pc)
2457 {
2458   switch(pc->type) {
2459   case PC_WILD:
2460   case PC_COMMENT:
2461     return;
2462   case PC_LABEL:
2463   case PC_FUNCTION:
2464   case PC_OPCODE:
2465     {
2466       // Go through the pCodes that are in pCode chain and link
2467       // them together through the pBranches. Note, the pCodes
2468       // are linked together as a contiguous stream like the 
2469       // assembly source code lines. The linking here mimics this
2470       // except that comments are not linked in.
2471       // 
2472       pCode *npc = pc->next;
2473       while(npc) {
2474         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
2475           pBranchLink(pc,npc);
2476           return;
2477         } else
2478           npc = npc->next;
2479       }
2480       /* reached the end of the pcode chain without finding
2481        * an instruction we could link to. */
2482     }
2483     break;
2484   case PC_FLOW:
2485     fprintf(stderr,"analyze PC_FLOW\n");
2486
2487     return;
2488   }
2489 }
2490 #endif
2491
2492 /*-----------------------------------------------------------------*/
2493 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
2494 {
2495   pBranch *pbr;
2496
2497   if(pc->type == PC_LABEL) {
2498     if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
2499       return TRUE;
2500   }
2501   if(pc->type == PC_OPCODE) {
2502     pbr = PCI(pc)->label;
2503     while(pbr) {
2504       if(pbr->pc->type == PC_LABEL) {
2505         if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
2506           return TRUE;
2507       }
2508       pbr = pbr->next;
2509     }
2510   }
2511
2512   return FALSE;
2513 }
2514
2515 /*-----------------------------------------------------------------*/
2516 /* findLabel - Search the pCode for a particular label             */
2517 /*-----------------------------------------------------------------*/
2518 pCode * findLabel(pCodeOpLabel *pcop_label)
2519 {
2520   pBlock *pb;
2521   pCode  *pc;
2522
2523   if(!the_pFile)
2524     return NULL;
2525
2526   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2527     for(pc = pb->pcHead; pc; pc = pc->next) 
2528       if(compareLabel(pc,pcop_label))
2529         return pc;
2530     
2531   }
2532
2533   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
2534   return NULL;
2535 }
2536
2537 /*-----------------------------------------------------------------*/
2538 /* findNextpCode - given a pCode, find the next of type 'pct'      */
2539 /*                 in the linked list                              */
2540 /*-----------------------------------------------------------------*/
2541 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
2542 {
2543
2544   while(pc) {
2545     if(pc->type == pct)
2546       return pc;
2547
2548     pc = pc->next;
2549   }
2550
2551   return NULL;
2552 }
2553
2554 /*-----------------------------------------------------------------*/
2555 /* findPrevpCode - given a pCode, find the previous of type 'pct'  */
2556 /*                 in the linked list                              */
2557 /*-----------------------------------------------------------------*/
2558 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
2559 {
2560
2561   while(pc) {
2562     if(pc->type == pct)
2563       return pc;
2564
2565     pc = pc->prev;
2566   }
2567
2568   return NULL;
2569 }
2570 /*-----------------------------------------------------------------*/
2571 /* findNextInstruction - given a pCode, find the next instruction  */
2572 /*                       in the linked list                        */
2573 /*-----------------------------------------------------------------*/
2574 pCode * findNextInstruction(pCode *pc)
2575 {
2576
2577   while(pc) {
2578     if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
2579       return pc;
2580
2581     pc = pc->next;
2582   }
2583
2584   //fprintf(stderr,"Couldn't find instruction\n");
2585   return NULL;
2586 }
2587
2588 /*-----------------------------------------------------------------*/
2589 /* findFunctionEnd - given a pCode find the end of the function    */
2590 /*                   that contains it     t                        */
2591 /*-----------------------------------------------------------------*/
2592 pCode * findFunctionEnd(pCode *pc)
2593 {
2594
2595   while(pc) {
2596     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
2597       return pc;
2598
2599     pc = pc->next;
2600   }
2601
2602   fprintf(stderr,"Couldn't find function end\n");
2603   return NULL;
2604 }
2605
2606 #if 0
2607 /*-----------------------------------------------------------------*/
2608 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
2609 /*                instruction with which it is associated.         */
2610 /*-----------------------------------------------------------------*/
2611 static void AnalyzeLabel(pCode *pc)
2612 {
2613
2614   pCodeUnlink(pc);
2615
2616 }
2617 #endif
2618
2619 #if 0
2620 static void AnalyzeGOTO(pCode *pc)
2621 {
2622
2623   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
2624
2625 }
2626
2627 static void AnalyzeSKIP(pCode *pc)
2628 {
2629
2630   pBranchLink(pc,findNextInstruction(pc->next));
2631   pBranchLink(pc,findNextInstruction(pc->next->next));
2632
2633 }
2634
2635 static void AnalyzeRETURN(pCode *pc)
2636 {
2637
2638   //  branch_link(pc,findFunctionEnd(pc->next));
2639
2640 }
2641
2642 #endif
2643
2644 /*-----------------------------------------------------------------*/
2645 /*-----------------------------------------------------------------*/
2646 regs * getRegFromInstruction(pCode *pc)
2647 {
2648   if(!pc                   || 
2649      !isPCI(pc)            ||
2650      !PCI(pc)->pcop        ||
2651      PCI(pc)->num_ops == 0 )
2652     return NULL;
2653
2654   switch(PCI(pc)->pcop->type) {
2655   case PO_INDF:
2656   case PO_FSR:
2657     return pic14_regWithIdx(PCOR(PCI(pc)->pcop)->rIdx);
2658
2659   case PO_BIT:
2660   case PO_GPR_TEMP:
2661     fprintf(stderr, "getRegFromInstruction - bit or temp\n");
2662     return PCOR(PCI(pc)->pcop)->r;
2663
2664   case PO_IMMEDIATE:
2665     fprintf(stderr, "getRegFromInstruction - immediate\n");
2666     return NULL; // PCOR(PCI(pc)->pcop)->r;
2667
2668   case PO_GPR_BIT:
2669     return PCOR(PCI(pc)->pcop)->r;
2670
2671   case PO_DIR:
2672     fprintf(stderr, "getRegFromInstruction - dir\n");
2673     //return NULL; PCOR(PCI(pc)->pcop)->r;
2674     return PCOR(PCI(pc)->pcop)->r;
2675   case PO_LITERAL:
2676     fprintf(stderr, "getRegFromInstruction - literal\n");
2677     break;
2678
2679   default:
2680     fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
2681     genericPrint(stderr, pc);
2682     break;
2683   }
2684
2685   return NULL;
2686
2687 }
2688
2689 /*-----------------------------------------------------------------*/
2690 /*-----------------------------------------------------------------*/
2691
2692 void AnalyzepBlock(pBlock *pb)
2693 {
2694   pCode *pc;
2695
2696   if(!pb)
2697     return;
2698
2699   /* Find all of the registers used in this pBlock 
2700    * by looking at each instruction and examining it's
2701    * operands
2702    */
2703   for(pc = pb->pcHead; pc; pc = pc->next) {
2704
2705     /* Is this an instruction with operands? */
2706     if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
2707
2708       if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
2709
2710         /* Loop through all of the registers declared so far in
2711            this block and see if we find this one there */
2712
2713         regs *r = setFirstItem(pb->tregisters);
2714
2715         while(r) {
2716           if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
2717             PCOR(PCI(pc)->pcop)->r = r;
2718             break;
2719           }
2720           r = setNextItem(pb->tregisters);
2721         }
2722
2723         if(!r) {
2724           /* register wasn't found */
2725           r = Safe_calloc(1, sizeof(regs));
2726           memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
2727           addSet(&pb->tregisters, r);
2728           PCOR(PCI(pc)->pcop)->r = r;
2729           //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
2730         }/* else 
2731           fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
2732          */
2733       }
2734       if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
2735         if(PCOR(PCI(pc)->pcop)->r) {
2736           pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
2737           DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
2738         } else {
2739           if(PCI(pc)->pcop->name)
2740             fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
2741           else
2742             fprintf(stderr,"ERROR: NULL register\n");
2743         }
2744       }
2745     }
2746
2747
2748   }
2749 }
2750
2751 /*-----------------------------------------------------------------*/
2752 /* */
2753 /*-----------------------------------------------------------------*/
2754 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
2755
2756 void InsertpFlow(pCode *pc, pCode **pflow)
2757 {
2758   PCFL(*pflow)->end = pc;
2759
2760   if(!pc || !pc->next)
2761     return;
2762
2763   *pflow = newpCodeFlow();
2764   pCodeInsertAfter(pc, *pflow);
2765 }
2766
2767 /*-----------------------------------------------------------------*/
2768 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
2769 /*                         the flow blocks.                        */
2770 /*
2771  * BuildFlow inserts pCodeFlow objects into the pCode chain at each
2772  * point the instruction flow changes. 
2773  */
2774 /*-----------------------------------------------------------------*/
2775 void BuildFlow(pBlock *pb)
2776 {
2777   pCode *pc;
2778   pCode *last_pci=NULL;
2779   pCode *pflow;
2780   int seq = 0;
2781
2782   if(!pb)
2783     return;
2784
2785   //fprintf (stderr,"build flow start seq %d  ",GpcFlowSeq);
2786   /* Insert a pCodeFlow object at the beginning of a pBlock */
2787
2788   pflow = newpCodeFlow();    /* Create a new Flow object */
2789   pflow->next = pb->pcHead;  /* Make the current head the next object */
2790   pb->pcHead->prev = pflow;  /* let the current head point back to the flow object */
2791   pb->pcHead = pflow;        /* Make the Flow object the head */
2792   pflow->pb = pb;
2793
2794   for( pc = findNextInstruction(pb->pcHead); 
2795       (pc=findNextInstruction(pc)) != NULL; ) { 
2796
2797     pc->seq = seq++;
2798     PCI(pc)->pcflow = PCFL(pflow);
2799
2800     if(PCI(pc)->isSkip || PCI(pc)->isBranch)  {
2801
2802       /* The instruction immediately following this one 
2803        * marks the beginning of a new flow segment */
2804
2805       InsertpFlow(pc, &pflow);
2806       seq = 0;
2807           
2808     } else if (PCI_HAS_LABEL(pc)) {
2809
2810       /* This instruction marks the beginning of a
2811        * new flow segment */
2812
2813       pc->seq = 0;
2814       seq = 1; 
2815       InsertpFlow(pc->prev, &pflow);
2816
2817       PCI(pc)->pcflow = PCFL(pflow);
2818       
2819     }
2820     last_pci = pc;
2821     pc = pc->next;
2822   }
2823
2824   //fprintf (stderr,",end seq %d",GpcFlowSeq);
2825   PCFL(pflow)->end = pb->pcTail;
2826 }
2827
2828 /*-----------------------------------------------------------------*/
2829 /*-----------------------------------------------------------------*/
2830 void dumpCond(int cond)
2831 {
2832
2833   static char *pcc_str[] = {
2834     //"PCC_NONE",
2835     "PCC_REGISTER",
2836     "PCC_C",
2837     "PCC_Z",
2838     "PCC_DC",
2839     "PCC_W",
2840     "PCC_EXAMINE_PCOP",
2841     "PCC_REG_BANK0",
2842     "PCC_REG_BANK1",
2843     "PCC_REG_BANK2",
2844     "PCC_REG_BANK3"
2845   };
2846
2847   int ncond = sizeof(pcc_str) / sizeof(char *);
2848   int i,j;
2849
2850   fprintf(stderr, "0x%04X\n",cond);
2851
2852   for(i=0,j=1; i<ncond; i++, j<<=1)
2853     if(cond & j)
2854       fprintf(stderr, "  %s\n",pcc_str[i]);
2855
2856 }
2857
2858 /*-----------------------------------------------------------------*/
2859 /*-----------------------------------------------------------------*/
2860 void FillFlow(pCodeFlow *pcflow)
2861 {
2862
2863   pCode *pc;
2864   int cur_bank;
2865
2866   if(!isPCFL(pcflow))
2867     return;
2868
2869   //  fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
2870
2871   pc = findNextpCode(PCODE(pcflow), PC_OPCODE); 
2872   if(!pc) {
2873     //    fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
2874     return;
2875   }
2876
2877   cur_bank = -1;
2878
2879   do {
2880     //regs *reg;
2881
2882     int inCond = PCI(pc)->inCond;
2883     int outCond = PCI(pc)->outCond;
2884 #if 0
2885     if( (reg = getRegFromInstruction(pc)) != NULL) {
2886       if(isSTATUS_REG(reg)) {
2887
2888         //fprintf(stderr, "  FillFlow - Status register\n");
2889
2890         /* Check to see if the register banks are changing */
2891         if(PCI(pc)->isModReg) {
2892
2893           pCodeOp *pcop = PCI(pc)->pcop;
2894           switch(PCI(pc)->op) {
2895             case POC_BSF:
2896               if(PCORB(pcop)->bit == PIC_RP0_BIT)
2897                 fprintf(stderr, "  FillFlow - Set RP0\n");
2898               //outCond |= PCC_REG_BANK1;
2899               if(PCORB(pcop)->bit == PIC_RP1_BIT) 
2900                 fprintf(stderr, "  FillFlow - Set RP1\n");
2901               //outCond |= PCC_REG_BANK3;
2902               break;
2903
2904             case POC_BCF:
2905               if(PCORB(pcop)->bit == PIC_RP0_BIT)
2906                 fprintf(stderr, "  FillFlow - Clr RP0\n");
2907               //outCond |= PCC_REG_BANK1;
2908               if(PCORB(pcop)->bit == PIC_RP1_BIT) 
2909                 fprintf(stderr, "  FillFlow - Clr RP1\n");
2910               //outCond |= PCC_REG_BANK3;
2911               break;
2912
2913           default:
2914             fprintf(stderr, "  FillFlow - Status register is getting Modified by:\n");
2915             genericPrint(stderr, pc);
2916           }
2917         }
2918
2919       } else
2920         inCond |= PCC_REG_BANK0 << (REG_BANK(reg) & 3);
2921     }
2922 #endif
2923
2924     pcflow->inCond |= (inCond &  ~pcflow->outCond);
2925     pcflow->outCond |= outCond;
2926
2927     
2928
2929
2930     pc = findNextpCode(pc->next, PC_OPCODE);
2931   } while (pc && (pc != pcflow->end));
2932
2933 #if 0
2934   if(!pc)
2935     fprintf(stderr, "  FillFlow - Bad end of flow\n");
2936
2937
2938   fprintf(stderr, "  FillFlow inCond: ");
2939   dumpCond(pcflow->inCond);
2940   fprintf(stderr, "  FillFlow outCond: ");
2941   dumpCond(pcflow->outCond);
2942 #endif
2943 }
2944 /*-----------------------------------------------------------------*/
2945 /*-----------------------------------------------------------------*/
2946 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
2947 {
2948
2949   if(!from || !to || !to->pcflow || !from->pcflow)
2950     return;
2951
2952   addSet(&(from->pcflow->to), to->pcflow);
2953   addSet(&(to->pcflow->from), from->pcflow);
2954
2955 }
2956
2957 /*-----------------------------------------------------------------*/
2958 /*-----------------------------------------------------------------*/
2959 void LinkFlow(pBlock *pb)
2960 {
2961   pCode *pc=NULL;
2962   pCode *pcflow;
2963   pCode *pct;
2964
2965   
2966   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
2967       (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
2968       pcflow = pcflow->next) {
2969
2970     if(!isPCFL(pcflow))
2971       fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
2972
2973     //FillFlow(PCFL(pcflow));
2974
2975     pc = PCFL(pcflow)->end;
2976
2977     //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
2978     if(isPCI_SKIP(pc)) {
2979       //fprintf(stderr, "ends with skip\n");
2980       pct=findNextInstruction(pc->next);
2981       LinkFlow_pCode(PCI(pc),PCI(pct));
2982       pct=findNextInstruction(pct->next);
2983       LinkFlow_pCode(PCI(pc),PCI(pct));
2984       continue;
2985     }
2986
2987     if(isPCI_BRANCH(pc)) {
2988       //fprintf(stderr, "ends with branch\n");
2989
2990       continue;
2991     }
2992 #if 0
2993     if(pc) {
2994       fprintf(stderr, "has an unrecognized ending:\n");
2995       pc->print(stderr,pc);
2996     }
2997     else 
2998       fprintf(stderr, "has no end pcode\n");
2999 #endif 
3000     
3001   }
3002 }
3003 /*-----------------------------------------------------------------*/
3004 /*-----------------------------------------------------------------*/
3005 int OptimizepBlock(pBlock *pb)
3006 {
3007   pCode *pc;
3008   int matches =0;
3009
3010   if(!pb || !peepOptimizing)
3011     return 0;
3012
3013   DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
3014   for(pc = pb->pcHead; pc; pc = pc->next)
3015     matches += pCodePeepMatchRule(pc);
3016   if(matches)
3017     DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
3018   return matches;
3019
3020 }
3021
3022 /*-----------------------------------------------------------------*/
3023 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
3024 /*-----------------------------------------------------------------*/
3025 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
3026 {
3027   pCode *pc;
3028
3029   for(pc = pcs; pc; pc = pc->next) {
3030
3031     if((pc->type == PC_OPCODE) && 
3032        (PCI(pc)->pcop) && 
3033        (PCI(pc)->pcop->type == PO_LABEL) &&
3034        (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
3035       return pc;
3036   }
3037  
3038
3039   return NULL;
3040 }
3041
3042 /*-----------------------------------------------------------------*/
3043 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
3044 /*                            pCode chain if they're not used.     */
3045 /*-----------------------------------------------------------------*/
3046 void pBlockRemoveUnusedLabels(pBlock *pb)
3047 {
3048   pCode *pc; pCodeLabel *pcl;
3049
3050   if(!pb)
3051     return;
3052
3053   for(pc = pb->pcHead; pc; pc = pc->next) {
3054
3055     if(pc->type == PC_LABEL)
3056       pcl = PCL(pc);
3057     else if ((pc->type == PC_OPCODE) && PCI(pc)->label)
3058       pcl = PCL(PCI(pc)->label->pc);
3059     else continue;
3060
3061       /* This pCode is a label, so search the pBlock to see if anyone
3062        * refers to it */
3063
3064     if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
3065       /* Couldn't find an instruction that refers to this label
3066        * So, unlink the pCode label from it's pCode chain
3067        * and destroy the label */
3068
3069       DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d\n", pcl->key));
3070
3071       if(pc->type == PC_LABEL) {
3072         unlinkPC(pc);
3073         pCodeLabelDestruct(pc);
3074       } else {
3075         unlinkpCodeFromBranch(pc, PCODE(pcl));
3076         /*if(pc->label->next == NULL && pc->label->pc == NULL) {
3077           free(pc->label);
3078         }*/
3079       }
3080
3081     }
3082   }
3083
3084 }
3085
3086
3087 /*-----------------------------------------------------------------*/
3088 /* pBlockMergeLabels - remove the pCode labels from the pCode      */
3089 /*                     chain and put them into pBranches that are  */
3090 /*                     associated with the appropriate pCode       */
3091 /*                     instructions.                               */
3092 /*-----------------------------------------------------------------*/
3093 void pBlockMergeLabels(pBlock *pb)
3094 {
3095   pBranch *pbr;
3096   pCode *pc, *pcnext=NULL;
3097
3098   if(!pb)
3099     return;
3100
3101   /* First, Try to remove any unused labels */
3102   //pBlockRemoveUnusedLabels(pb);
3103
3104   /* Now loop through the pBlock and merge the labels with the opcodes */
3105
3106   for(pc = pb->pcHead; pc; pc = pc->next) {
3107
3108     if(pc->type == PC_LABEL) {
3109       //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
3110       if( !(pcnext = findNextInstruction(pc)) ) 
3111         return;  // Couldn't find an instruction associated with this label
3112
3113       // Unlink the pCode label from it's pCode chain
3114       unlinkPC(pc);
3115
3116       //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
3117       // And link it into the instruction's pBranch labels. (Note, since
3118       // it's possible to have multiple labels associated with one instruction
3119       // we must provide a means to accomodate the additional labels. Thus
3120       // the labels are placed into the singly-linked list "label" as 
3121       // opposed to being a single member of the pCodeInstruction.)
3122
3123       //_ALLOC(pbr,sizeof(pBranch));
3124       pbr = Safe_calloc(1,sizeof(pBranch));
3125       pbr->pc = pc;
3126       pbr->next = NULL;
3127
3128       PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
3129       if(pcnext->prev) 
3130         pc = pcnext->prev;
3131       else
3132         pc = pcnext;
3133     }
3134
3135   }
3136   pBlockRemoveUnusedLabels(pb);
3137
3138 }
3139
3140 /*-----------------------------------------------------------------*/
3141 /*-----------------------------------------------------------------*/
3142 void OptimizepCode(char dbName)
3143 {
3144 #define MAX_PASSES 4
3145
3146   int matches = 0;
3147   int passes = 0;
3148   pBlock *pb;
3149
3150   if(!the_pFile)
3151     return;
3152
3153   DFPRINTF((stderr," Optimizing pCode\n"));
3154
3155   do {
3156     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3157       if('*' == dbName || getpBlock_dbName(pb) == dbName)
3158         matches += OptimizepBlock(pb);
3159     }
3160   }
3161   while(matches && ++passes < MAX_PASSES);
3162
3163 }
3164
3165 /*-----------------------------------------------------------------*/
3166 /* popCopy - copy a pcode operator                                 */
3167 /*-----------------------------------------------------------------*/
3168 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
3169 {
3170   pCodeOp *pcop;
3171
3172   pcop = newpCodeOpBit(pc->name, bitval, 0);
3173
3174   if( !( (pcop->type == PO_LABEL) ||
3175          (pcop->type == PO_LITERAL) ||
3176          (pcop->type == PO_STR) ))
3177     PCOR(pcop)->r = PCOR(pc)->r;  /* This is dangerous... */
3178
3179   return pcop;
3180 }
3181
3182
3183
3184 #if 0
3185 /*-----------------------------------------------------------------*/
3186 /*-----------------------------------------------------------------*/
3187 int InstructionRegBank(pCode *pc)
3188 {
3189   regs *reg;
3190
3191   if( (reg = getRegFromInstruction(pc)) == NULL)
3192     return -1;
3193
3194   return REG_BANK(reg);
3195
3196 }
3197 #endif
3198
3199 /*-----------------------------------------------------------------*/
3200 /*-----------------------------------------------------------------*/
3201 void FixRegisterBanking(pBlock *pb)
3202 {
3203   pCode *pc=NULL;
3204   pCode *pcprev=NULL;
3205   pCode *new_pc;
3206
3207   int cur_bank;
3208   regs *reg;
3209   return;
3210   if(!pb)
3211     return;
3212
3213   pc = findNextpCode(pb->pcHead, PC_FLOW);
3214   if(!pc)
3215     return;
3216   /* loop through all of the flow blocks with in one pblock */
3217
3218   //  fprintf(stderr,"Register banking\n");
3219   cur_bank = 0;
3220   do {
3221     /* at this point, pc should point to a PC_FLOW object */
3222
3223
3224     /* for each flow block, determine the register banking 
3225        requirements */
3226
3227     do {
3228       if(isPCI(pc)) {
3229     genericPrint(stderr, pc);
3230
3231         reg = getRegFromInstruction(pc);
3232         //#if 0
3233         if(reg) {
3234           fprintf(stderr, "  %s  ",reg->name);
3235           fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg));
3236
3237         }
3238         //#endif
3239         if(reg && REG_BANK(reg)!=cur_bank) {
3240           /* Examine the instruction before this one to make sure it is
3241            * not a skip type instruction */
3242           pcprev = findPrevpCode(pc->prev, PC_OPCODE);
3243           if(pcprev && !isPCI_SKIP(pcprev)) {
3244             int b = cur_bank ^ REG_BANK(reg);
3245
3246             //fprintf(stderr, "Cool! can switch banks\n");
3247             cur_bank = REG_BANK(reg);
3248             if(b & 1) {
3249               new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF),
3250                                 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3251               pCodeInsertAfter(pc->prev, new_pc);
3252               if(PCI(pc)->label) { 
3253                 PCI(new_pc)->label = PCI(pc)->label;
3254                 PCI(pc)->label = NULL;
3255               }
3256               /*
3257                 new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF),
3258                 popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3259                 pCodeInsertAfter(pc, new_pc);
3260               */
3261
3262             }
3263
3264           } else
3265             fprintf(stderr, "Bummer can't switch banks\n");
3266         }
3267       }
3268
3269       pcprev = pc;
3270       pc = pc->next;
3271     } while(pc && !(isPCFL(pc))); 
3272
3273     if(pcprev && cur_bank) {
3274       /* Brute force - make sure that we point to bank 0 at the
3275        * end of each flow block */
3276       new_pc = newpCode(POC_BCF,
3277                         popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT));
3278       pCodeInsertAfter(pcprev, new_pc);
3279       cur_bank = 0;
3280     }
3281
3282   }while (pc);
3283
3284 }
3285
3286 void pBlockDestruct(pBlock *pb)
3287 {
3288
3289   if(!pb)
3290     return;
3291
3292
3293   free(pb);
3294
3295 }
3296
3297 /*-----------------------------------------------------------------*/
3298 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
3299 /*                                  name dbName and combine them   */
3300 /*                                  into one block                 */
3301 /*-----------------------------------------------------------------*/
3302 void mergepBlocks(char dbName)
3303 {
3304
3305   pBlock *pb, *pbmerged = NULL,*pbn;
3306
3307   pb = the_pFile->pbHead;
3308
3309   //fprintf(stderr," merging blocks named %c\n",dbName);
3310   while(pb) {
3311
3312     pbn = pb->next;
3313     //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
3314     if( getpBlock_dbName(pb) == dbName) {
3315
3316       //fprintf(stderr," merged block %c\n",dbName);
3317
3318       if(!pbmerged) {
3319         pbmerged = pb;
3320       } else {
3321         addpCode2pBlock(pbmerged, pb->pcHead);
3322         /* addpCode2pBlock doesn't handle the tail: */
3323         pbmerged->pcTail = pb->pcTail;
3324
3325         pb->prev->next = pbn;
3326         if(pbn) 
3327           pbn->prev = pb->prev;
3328
3329
3330         pBlockDestruct(pb);
3331       }
3332       //printpBlock(stderr, pbmerged);
3333     } 
3334     pb = pbn;
3335   }
3336
3337 }
3338
3339 /*-----------------------------------------------------------------*/
3340 /* AnalyzeBanking - Called after the memory addresses have been    */
3341 /*                  assigned to the registers.                     */
3342 /*                                                                 */
3343 /*-----------------------------------------------------------------*/
3344 void AnalyzeBanking(void)
3345 {
3346
3347   pBlock *pb;
3348
3349   if(!the_pFile)
3350     return;
3351
3352
3353   /* Phase 2 - Flow Analysis
3354    *
3355    * In this phase, the pCode is partition into pCodeFlow 
3356    * blocks. The flow blocks mark the points where a continuous
3357    * stream of instructions changes flow (e.g. because of
3358    * a call or goto or whatever).
3359    */
3360
3361   for(pb = the_pFile->pbHead; pb; pb = pb->next)
3362     BuildFlow(pb);
3363
3364   /* Phase 2 - Flow Analysis - linking flow blocks
3365    *
3366    * In this phase, the individual flow blocks are examined
3367    * to determine their order of excution.
3368    */
3369
3370   for(pb = the_pFile->pbHead; pb; pb = pb->next)
3371     LinkFlow(pb);
3372
3373   for(pb = the_pFile->pbHead; pb; pb = pb->next)
3374     FixRegisterBanking(pb);
3375
3376   /* debug stuff */ 
3377   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3378     pCode *pcflow;
3379     for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
3380          (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
3381          pcflow = pcflow->next) {
3382
3383       FillFlow(PCFL(pcflow));
3384     }
3385   }
3386
3387
3388 }
3389
3390 /*-----------------------------------------------------------------*/
3391 /* buildCallTree - look at the flow and extract all of the calls   */
3392 /*                                                                 */
3393 /*-----------------------------------------------------------------*/
3394 set *register_usage(pBlock *pb);
3395
3396 void buildCallTree(void    )
3397 {
3398   pBranch *pbr;
3399   pBlock  *pb;
3400   pCode   *pc;
3401
3402   if(!the_pFile)
3403     return;
3404
3405
3406
3407   /* Now build the call tree.
3408      First we examine all of the pCodes for functions.
3409      Keep in mind that the function boundaries coincide
3410      with pBlock boundaries. 
3411
3412      The algorithm goes something like this:
3413      We have two nested loops. The outer loop iterates
3414      through all of the pBlocks/functions. The inner
3415      loop iterates through all of the pCodes for
3416      a given pBlock. When we begin iterating through
3417      a pBlock, the variable pc_fstart, pCode of the start
3418      of a function, is cleared. We then search for pCodes
3419      of type PC_FUNCTION. When one is encountered, we
3420      initialize pc_fstart to this and at the same time
3421      associate a new pBranch object that signifies a 
3422      branch entry. If a return is found, then this signifies
3423      a function exit point. We'll link the pCodes of these
3424      returns to the matching pc_fstart.
3425
3426      When we're done, a doubly linked list of pBranches
3427      will exist. The head of this list is stored in
3428      `the_pFile', which is the meta structure for all
3429      of the pCode. Look at the printCallTree function
3430      on how the pBranches are linked together.
3431
3432    */
3433   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3434     pCode *pc_fstart=NULL;
3435     for(pc = pb->pcHead; pc; pc = pc->next) {
3436       if(isPCF(pc)) {  //pc->type == PC_FUNCTION) {
3437         if (PCF(pc)->fname) {
3438
3439           if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
3440             fprintf(stderr," found main \n");
3441             pb->cmemmap = NULL;  /* FIXME do we need to free ? */
3442             pb->dbName = 'M';
3443           }
3444
3445           //_ALLOC(pbr,sizeof(pBranch));
3446           pbr = Safe_calloc(1,sizeof(pBranch));
3447           pbr->pc = pc_fstart = pc;
3448           pbr->next = NULL;
3449
3450           the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
3451
3452           // Here's a better way of doing the same:
3453           addSet(&pb->function_entries, pc);
3454
3455         } else {
3456           // Found an exit point in a function, e.g. return
3457           // (Note, there may be more than one return per function)
3458           if(pc_fstart)
3459             pBranchLink(PCF(pc_fstart), PCF(pc));
3460
3461           addSet(&pb->function_exits, pc);
3462         }
3463       } else if(isCALL(pc)) {// if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3464         addSet(&pb->function_calls,pc);
3465       }
3466     }
3467   }
3468
3469   /* Re-allocate the registers so that there are no collisions
3470    * between local variables when one function call another */
3471
3472   pic14_deallocateAllRegs();
3473
3474   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3475     if(!pb->visited)
3476       register_usage(pb);
3477   }
3478
3479 }
3480
3481 /*-----------------------------------------------------------------*/
3482 /* AnalyzepCode - parse the pCode that has been generated and form */
3483 /*                all of the logical connections.                  */
3484 /*                                                                 */
3485 /* Essentially what's done here is that the pCode flow is          */
3486 /* determined.                                                     */
3487 /*-----------------------------------------------------------------*/
3488
3489 void AnalyzepCode(char dbName)
3490 {
3491   pBlock *pb;
3492   int i,changes;
3493
3494   if(!the_pFile)
3495     return;
3496
3497   mergepBlocks('D');
3498
3499
3500   /* Phase 1 - Register allocation and peep hole optimization
3501    *
3502    * The first part of the analysis is to determine the registers
3503    * that are used in the pCode. Once that is done, the peep rules
3504    * are applied to the code. We continue to loop until no more
3505    * peep rule optimizations are found (or until we exceed the
3506    * MAX_PASSES threshold). 
3507    *
3508    * When done, the required registers will be determined.
3509    *
3510    */
3511   i = 0;
3512   do {
3513
3514     DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
3515
3516     /* First, merge the labels with the instructions */
3517     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3518       if('*' == dbName || getpBlock_dbName(pb) == dbName) {
3519
3520         DFPRINTF((stderr," analyze and merging block %c\n",dbName));
3521         //fprintf(stderr," analyze and merging block %c\n",getpBlock_dbName(pb));
3522         pBlockMergeLabels(pb);
3523         AnalyzepBlock(pb);
3524       }
3525     }
3526
3527     changes = 0;
3528
3529     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3530       if('*' == dbName || getpBlock_dbName(pb) == dbName)
3531         changes += OptimizepBlock(pb);
3532     }
3533       
3534   } while(changes && (i++ < MAX_PASSES));
3535
3536   buildCallTree();
3537 }
3538
3539 /*-----------------------------------------------------------------*/
3540 /* ispCodeFunction - returns true if *pc is the pCode of a         */
3541 /*                   function                                      */
3542 /*-----------------------------------------------------------------*/
3543 bool ispCodeFunction(pCode *pc)
3544 {
3545
3546   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
3547     return 1;
3548
3549   return 0;
3550 }
3551
3552 /*-----------------------------------------------------------------*/
3553 /* findFunction - Search for a function by name (given the name)   */
3554 /*                in the set of all functions that are in a pBlock */
3555 /* (note - I expect this to change because I'm planning to limit   */
3556 /*  pBlock's to just one function declaration                      */
3557 /*-----------------------------------------------------------------*/
3558 pCode *findFunction(char *fname)
3559 {
3560   pBlock *pb;
3561   pCode *pc;
3562   if(!fname)
3563     return NULL;
3564
3565   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3566
3567     pc = setFirstItem(pb->function_entries);
3568     while(pc) {
3569     
3570       if((pc->type == PC_FUNCTION) &&
3571          (PCF(pc)->fname) && 
3572          (strcmp(fname, PCF(pc)->fname)==0))
3573         return pc;
3574
3575       pc = setNextItem(pb->function_entries);
3576
3577     }
3578
3579   }
3580   return NULL;
3581 }
3582
3583 void MarkUsedRegisters(set *regset)
3584 {
3585
3586   regs *r1,*r2;
3587
3588   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
3589     r2 = pic14_regWithIdx(r1->rIdx);
3590     r2->isFree = 0;
3591     r2->wasUsed = 1;
3592   }
3593 }
3594
3595 void pBlockStats(FILE *of, pBlock *pb)
3596 {
3597
3598   pCode *pc;
3599   regs  *r;
3600
3601   fprintf(of,";***\n;  pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
3602
3603   // for now just print the first element of each set
3604   pc = setFirstItem(pb->function_entries);
3605   if(pc) {
3606     fprintf(of,";entry:  ");
3607     pc->print(of,pc);
3608   }
3609   pc = setFirstItem(pb->function_exits);
3610   if(pc) {
3611     fprintf(of,";has an exit\n");
3612     //pc->print(of,pc);
3613   }
3614
3615   pc = setFirstItem(pb->function_calls);
3616   if(pc) {
3617     fprintf(of,";functions called:\n");
3618
3619     while(pc) {
3620       if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3621         fprintf(of,";   %s\n",get_op(PCI(pc)));
3622       }
3623       pc = setNextItem(pb->function_calls);
3624     }
3625   }
3626
3627   r = setFirstItem(pb->tregisters);
3628   if(r) {
3629     int n = elementsInSet(pb->tregisters);
3630
3631     fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
3632
3633     while (r) {
3634       fprintf(of,";   %s\n",r->name);
3635       r = setNextItem(pb->tregisters);
3636     }
3637   }
3638 }
3639
3640 /*-----------------------------------------------------------------*/
3641 /*-----------------------------------------------------------------*/
3642 static void sequencepCode(void)
3643 {
3644   pBlock *pb;
3645   pCode *pc;
3646
3647
3648   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3649
3650     pb->seq = GpCodeSequenceNumber+1;
3651
3652     for( pc = pb->pcHead; pc; pc = pc->next)
3653       pc->seq = ++GpCodeSequenceNumber;
3654   }
3655
3656 }
3657
3658 /*-----------------------------------------------------------------*/
3659 /*-----------------------------------------------------------------*/
3660 set *register_usage(pBlock *pb)
3661 {
3662   pCode *pc,*pcn;
3663   set *registers=NULL;
3664   set *registersInCallPath = NULL;
3665
3666   /* check recursion */
3667
3668   pc = setFirstItem(pb->function_entries);
3669
3670   if(!pc)
3671     return registers;
3672
3673   pb->visited = 1;
3674
3675   if(pc->type != PC_FUNCTION)
3676     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
3677
3678   pc = setFirstItem(pb->function_calls);
3679   for( ; pc; pc = setNextItem(pb->function_calls)) {
3680
3681     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3682       char *dest = get_op(PCI(pc));
3683
3684       pcn = findFunction(dest);
3685       if(pcn) 
3686         registersInCallPath = register_usage(pcn->pb);
3687     } else
3688       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
3689
3690   }
3691
3692 #ifdef PCODE_DEBUG
3693   pBlockStats(stderr,pb);  // debug
3694 #endif
3695
3696   // Mark the registers in this block as used.
3697
3698   MarkUsedRegisters(pb->tregisters);
3699   if(registersInCallPath) {
3700     /* registers were used in the functions this pBlock has called */
3701     /* so now, we need to see if these collide with the ones we are */
3702     /* using here */
3703
3704     regs *r1,*r2, *newreg;
3705
3706     DFPRINTF((stderr,"comparing registers\n"));
3707
3708     r1 = setFirstItem(registersInCallPath);
3709     while(r1) {
3710
3711       r2 = setFirstItem(pb->tregisters);
3712
3713       while(r2 && (r1->type != REG_STK)) {
3714
3715         if(r2->rIdx == r1->rIdx) {
3716           newreg = pic14_findFreeReg(REG_GPR);
3717
3718
3719           if(!newreg) {
3720             DFPRINTF((stderr,"Bummer, no more registers.\n"));
3721             exit(1);
3722           }
3723
3724           DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
3725                   r1->rIdx, newreg->rIdx));
3726           r2->rIdx = newreg->rIdx;
3727           //if(r2->name) free(r2->name);
3728           if(newreg->name)
3729             r2->name = Safe_strdup(newreg->name);
3730           else
3731             r2->name = NULL;
3732           newreg->isFree = 0;
3733           newreg->wasUsed = 1;
3734         }
3735         r2 = setNextItem(pb->tregisters);
3736       }
3737
3738       r1 = setNextItem(registersInCallPath);
3739     }
3740
3741     /* Collisions have been resolved. Now free the registers in the call path */
3742     r1 = setFirstItem(registersInCallPath);
3743     while(r1) {
3744       if(r1->type != REG_STK) {
3745         newreg = pic14_regWithIdx(r1->rIdx);
3746         newreg->isFree = 1;
3747       }
3748       r1 = setNextItem(registersInCallPath);
3749     }
3750
3751   }// else
3752   //    MarkUsedRegisters(pb->registers);
3753
3754   registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
3755 #ifdef PCODE_DEBUG
3756   if(registers) 
3757     DFPRINTF((stderr,"returning regs\n"));
3758   else
3759     DFPRINTF((stderr,"not returning regs\n"));
3760
3761   DFPRINTF((stderr,"pBlock after register optim.\n"));
3762   pBlockStats(stderr,pb);  // debug
3763 #endif
3764
3765   return registers;
3766 }
3767
3768 /*-----------------------------------------------------------------*/
3769 /* printCallTree - writes the call tree to a file                  */
3770 /*                                                                 */
3771 /*-----------------------------------------------------------------*/
3772 void pct2(FILE *of,pBlock *pb,int indent)
3773 {
3774   pCode *pc,*pcn;
3775   int i;
3776   //  set *registersInCallPath = NULL;
3777
3778   if(!of)
3779     return;// registers;
3780
3781   if(indent > 10)
3782     return; // registers;   //recursion ?
3783
3784   pc = setFirstItem(pb->function_entries);
3785
3786   if(!pc)
3787     return;
3788
3789   pb->visited = 0;
3790
3791   for(i=0;i<indent;i++)   // Indentation
3792     fputc(' ',of);
3793
3794   if(pc->type == PC_FUNCTION)
3795     fprintf(of,"%s\n",PCF(pc)->fname);
3796   else
3797     return;  // ???
3798
3799
3800   pc = setFirstItem(pb->function_calls);
3801   for( ; pc; pc = setNextItem(pb->function_calls)) {
3802
3803     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
3804       char *dest = get_op(PCI(pc));
3805
3806       pcn = findFunction(dest);
3807       if(pcn) 
3808         pct2(of,pcn->pb,indent+1);
3809     } else
3810       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
3811
3812   }
3813
3814
3815 }
3816
3817 #if 0
3818   fprintf(stderr,"pBlock before register optim.\n");
3819   pBlockStats(stderr,pb);  // debug
3820
3821   if(registersInCallPath) {
3822     /* registers were used in the functions this pBlock has called */
3823     /* so now, we need to see if these collide with the ones we are using here */
3824
3825     regs *r1,*r2, *newreg;
3826
3827     fprintf(stderr,"comparing registers\n");
3828
3829     r1 = setFirstItem(registersInCallPath);
3830     while(r1) {
3831
3832       r2 = setFirstItem(pb->registers);
3833
3834       while(r2) {
3835
3836         if(r2->rIdx == r1->rIdx) {
3837           newreg = pic14_findFreeReg();
3838
3839
3840           if(!newreg) {
3841             fprintf(stderr,"Bummer, no more registers.\n");
3842             exit(1);
3843           }
3844
3845           fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
3846                   r1->rIdx, newreg->rIdx);
3847           r2->rIdx = newreg->rIdx;
3848           //if(r2->name) free(r2->name);
3849           if(newreg->name)
3850             r2->name = Safe_strdup(newreg->name);
3851           else
3852             r2->name = NULL;
3853           newreg->isFree = 0;
3854           newreg->wasUsed = 1;
3855         }
3856         r2 = setNextItem(pb->registers);
3857       }
3858
3859       r1 = setNextItem(registersInCallPath);
3860     }
3861
3862     /* Collisions have been resolved. Now free the registers in the call path */
3863     r1 = setFirstItem(registersInCallPath);
3864     while(r1) {
3865       newreg = pic14_regWithIdx(r1->rIdx);
3866       newreg->isFree = 1;
3867       r1 = setNextItem(registersInCallPath);
3868     }
3869
3870   } else
3871     MarkUsedRegisters(pb->registers);
3872
3873   registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
3874
3875   if(registers) 
3876     fprintf(stderr,"returning regs\n");
3877   else
3878     fprintf(stderr,"not returning regs\n");
3879
3880   fprintf(stderr,"pBlock after register optim.\n");
3881   pBlockStats(stderr,pb);  // debug
3882
3883
3884   return registers;
3885
3886 #endif
3887
3888
3889 /*-----------------------------------------------------------------*/
3890 /* printCallTree - writes the call tree to a file                  */
3891 /*                                                                 */
3892 /*-----------------------------------------------------------------*/
3893
3894 void printCallTree(FILE *of)
3895 {
3896   pBranch *pbr;
3897   pBlock  *pb;
3898   pCode   *pc;
3899
3900   if(!the_pFile)
3901     return;
3902
3903   if(!of)
3904     of = stderr;
3905
3906   fprintf(of, "\npBlock statistics\n");
3907   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
3908     pBlockStats(of,pb);
3909
3910
3911
3912   fprintf(of,"Call Tree\n");
3913   pbr = the_pFile->functions;
3914   while(pbr) {
3915     if(pbr->pc) {
3916       pc = pbr->pc;
3917       if(!ispCodeFunction(pc))
3918         fprintf(of,"bug in call tree");
3919
3920
3921       fprintf(of,"Function: %s\n", PCF(pc)->fname);
3922
3923       while(pc->next && !ispCodeFunction(pc->next)) {
3924         pc = pc->next;
3925         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
3926           fprintf(of,"\t%s\n",get_op(PCI(pc)));
3927       }
3928     }
3929
3930     pbr = pbr->next;
3931   }
3932
3933
3934   /* Re-allocate the registers so that there are no collisions
3935    * between local variables when one function call another */
3936 #if 0
3937   pic14_deallocateAllRegs();
3938
3939   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3940     if(!pb->visited)
3941       register_usage(pb);
3942   }
3943 #endif
3944
3945   fprintf(of,"\n**************\n\na better call tree\n");
3946   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3947     if(pb->visited)
3948       pct2(of,pb,0);
3949   }
3950
3951   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3952     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
3953   }
3954 }