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