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