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