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