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