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