pCode peep is fully working for the PIC port.
[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 "ralloc.h"
29
30 #if defined(__BORLANDC__) || defined(_MSC_VER)
31 #define STRCASECMP stricmp
32 #else
33 #define STRCASECMP strcasecmp
34 #endif
35
36 // Eventually this will go into device dependent files:
37 pCodeOpReg pc_status    = {{PO_STATUS,  "STATUS"}, -1, NULL,NULL};
38 pCodeOpReg pc_indf      = {{PO_INDF,    "INDF"}, -1, NULL,NULL};
39 pCodeOpReg pc_fsr       = {{PO_FSR,     "FSR"}, -1, NULL,NULL};
40
41 static int mnemonics_initialized = 0;
42
43 #if 0
44 //static char *PIC_mnemonics[] = {
45 static char *scpADDLW = "ADDLW";
46 static char *scpADDWF = "ADDWF";
47 static char *scpANDLW = "ANDLW";
48 static char *scpANDWF = "ANDWF";
49 static char *scpBCF = "BCF";
50 static char *scpBSF = "BSF";
51 static char *scpBTFSC = "BTFSC";
52 static char *scpBTFSS = "BTFSS";
53 static char *scpCALL = "CALL";
54 static char *scpCOMF = "COMF";
55 static char *scpCLRF = "CLRF";
56 static char *scpCLRW = "CLRW";
57 static char *scpDECF = "DECF";
58 static char *scpDECFSZ = "DECFSZ";
59 static char *scpGOTO = "GOTO";
60 static char *scpINCF = "INCF";
61 static char *scpINCFSZ = "INCFSZ";
62 static char *scpIORLW = "IORLW";
63 static char *scpIORWF = "IORWF";
64 static char *scpMOVF = "MOVF";
65 static char *scpMOVLW = "MOVLW";
66 static char *scpMOVWF = "MOVWF";
67 static char *scpNEGF = "NEGF";
68 static char *scpRETLW = "RETLW";
69 static char *scpRETURN = "RETURN";
70 static char *scpSUBLW = "SUBLW";
71 static char *scpSUBWF = "SUBWF";
72 static char *scpTRIS = "TRIS";
73 static char *scpXORLW = "XORLW";
74 static char *scpXORWF = "XORWF";
75 #endif
76
77 static hTab *pic14MnemonicsHash = NULL;
78
79
80
81 static pFile *the_pFile = NULL;
82 static int peepOptimizing = 1;
83 static int GpCodeSequenceNumber = 1;
84
85 /****************************************************************/
86 /*                      Forward declarations                    */
87 /****************************************************************/
88
89 static void unlinkPC(pCode *pc);
90 static void genericAnalyze(pCode *pc);
91 static void AnalyzeGOTO(pCode *pc);
92 static void AnalyzeSKIP(pCode *pc);
93 static void AnalyzeRETURN(pCode *pc);
94
95 static void genericDestruct(pCode *pc);
96 static void genericPrint(FILE *of,pCode *pc);
97
98 static void pCodePrintLabel(FILE *of, pCode *pc);
99 static void pCodePrintFunction(FILE *of, pCode *pc);
100 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
101 static char *get_op( pCodeInstruction *pcc);
102 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
103 int pCodePeepMatchRule(pCode *pc);
104
105
106 pCodeInstruction pciADDWF = {
107   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
108    genericAnalyze,
109    genericDestruct,
110    genericPrint},
111   POC_ADDWF,
112   "ADDWF",
113   NULL, // operand
114   2,    // num ops
115   1,0,  // dest, bit instruction
116   (PCC_W | PCC_REGISTER),   // inCond
117   (PCC_REGISTER | PCC_Z) // outCond
118 };
119
120 pCodeInstruction pciADDFW = {
121   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
122    genericAnalyze,
123    genericDestruct,
124    genericPrint},
125   POC_ADDWF,
126   "ADDWF",
127   NULL, // operand
128   2,    // num ops
129   0,0,  // dest, bit instruction
130   (PCC_W | PCC_REGISTER),   // inCond
131   (PCC_W | PCC_Z) // outCond
132 };
133
134 pCodeInstruction pciADDLW = {
135   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
136    genericAnalyze,
137    genericDestruct,
138    genericPrint},
139   POC_ADDLW,
140   "ADDLW",
141   NULL, // operand
142   1,    // num ops
143   0,0,  // dest, bit instruction
144   PCC_W,   // inCond
145   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
146 };
147
148 pCodeInstruction pciANDLW = {
149   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
150    genericAnalyze,
151    genericDestruct,
152    genericPrint},
153   POC_ANDLW,
154   "ANDLW",
155   NULL, // operand
156   1,    // num ops
157   0,0,  // dest, bit instruction
158   PCC_W,   // inCond
159   (PCC_W | PCC_Z) // outCond
160 };
161
162 pCodeInstruction pciANDWF = {
163   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
164    genericAnalyze,
165    genericDestruct,
166    genericPrint},
167   POC_ANDWF,
168   "ANDWF",
169   NULL, // operand
170   2,    // num ops
171   1,0,  // dest, bit instruction
172   (PCC_W | PCC_REGISTER),   // inCond
173   (PCC_REGISTER | PCC_Z) // outCond
174 };
175
176 pCodeInstruction pciANDFW = {
177   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
178    genericAnalyze,
179    genericDestruct,
180    genericPrint},
181   POC_ANDWF,
182   "ANDWF",
183   NULL, // operand
184   2,    // num ops
185   0,0,  // dest, bit instruction
186   (PCC_W | PCC_REGISTER),   // inCond
187   (PCC_W | PCC_Z) // outCond
188 };
189
190 pCodeInstruction pciBCF = {
191   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
192    genericAnalyze,
193    genericDestruct,
194    genericPrint},
195   POC_BCF,
196   "BCF",
197   NULL, // operand
198   2,    // num ops
199   0,1,  // dest, bit instruction
200   PCC_NONE,   // inCond
201   PCC_EXAMINE_PCOP // outCond
202 };
203
204 pCodeInstruction pciBSF = {
205   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
206    genericAnalyze,
207    genericDestruct,
208    genericPrint},
209   POC_BSF,
210   "BSF",
211   NULL, // operand
212   2,    // num ops
213   0,1,  // dest, bit instruction
214   PCC_NONE,   // inCond
215   PCC_EXAMINE_PCOP // outCond
216 };
217
218 pCodeInstruction pciBTFSC = {
219   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
220    AnalyzeSKIP,
221    genericDestruct,
222    genericPrint},
223   POC_BTFSC,
224   "BTFSC",
225   NULL, // operand
226   2,    // num ops
227   0,1,  // dest, bit instruction
228   PCC_EXAMINE_PCOP,   // inCond
229   PCC_NONE // outCond
230 };
231
232 pCodeInstruction pciBTFSS = {
233   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
234    AnalyzeSKIP,
235    genericDestruct,
236    genericPrint},
237   POC_BTFSS,
238   "BTFSS",
239   NULL, // operand
240   2,    // num ops
241   0,1,  // dest, bit instruction
242   PCC_EXAMINE_PCOP,   // inCond
243   PCC_NONE // outCond
244 };
245
246 pCodeInstruction pciCALL = {
247   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
248    genericAnalyze,
249    genericDestruct,
250    genericPrint},
251   POC_CALL,
252   "CALL",
253   NULL, // operand
254   1,    // num ops
255   0,0,  // dest, bit instruction
256   PCC_NONE, // inCond
257   PCC_NONE  // outCond
258 };
259
260 //fixme - need a COMFW instruction.
261 pCodeInstruction pciCOMF = {
262   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
263    genericAnalyze,
264    genericDestruct,
265    genericPrint},
266   POC_COMF,
267   "COMF",
268   NULL, // operand
269   2,    // num ops
270   0,0,  // dest, bit instruction
271   PCC_NONE, // inCond
272   PCC_NONE  // outCond
273 };
274
275 pCodeInstruction pciCLRF = {
276   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
277    genericAnalyze,
278    genericDestruct,
279    genericPrint},
280   POC_CLRF,
281   "CLRF",
282   NULL, // operand
283   1,    // num ops
284   0,0,  // dest, bit instruction
285   PCC_REGISTER, // inCond
286   PCC_REGISTER  // outCond
287 };
288
289 pCodeInstruction pciCLRW = {
290   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
291    genericAnalyze,
292    genericDestruct,
293    genericPrint},
294   POC_CLRW,
295   "CLRW",
296   NULL, // operand
297   0,    // num ops
298   0,0,  // dest, bit instruction
299   PCC_W, // inCond
300   PCC_W  // outCond
301 };
302
303 pCodeInstruction pciDECF = {
304   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
305    genericAnalyze,
306    genericDestruct,
307    genericPrint},
308   POC_DECF,
309   "DECF",
310   NULL, // operand
311   2,    // num ops
312   1,0,  // dest, bit instruction
313   PCC_REGISTER,   // inCond
314   PCC_REGISTER    // outCond
315 };
316
317 pCodeInstruction pciDECFW = {
318   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
319    genericAnalyze,
320    genericDestruct,
321    genericPrint},
322   POC_DECFW,
323   "DECF",
324   NULL, // operand
325   2,    // num ops
326   0,0,  // dest, bit instruction
327   PCC_REGISTER,   // inCond
328   PCC_W    // outCond
329 };
330
331 pCodeInstruction pciDECFSZ = {
332   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
333    AnalyzeSKIP,
334    genericDestruct,
335    genericPrint},
336   POC_DECFSZ,
337   "DECFSZ",
338   NULL, // operand
339   2,    // num ops
340   1,0,  // dest, bit instruction
341   PCC_REGISTER,   // inCond
342   PCC_REGISTER    // outCond
343 };
344
345 pCodeInstruction pciDECFSZW = {
346   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
347    AnalyzeSKIP,
348    genericDestruct,
349    genericPrint},
350   POC_DECFSZW,
351   "DECFSZ",
352   NULL, // operand
353   2,    // num ops
354   0,0,  // dest, bit instruction
355   PCC_REGISTER,   // inCond
356   PCC_W           // outCond
357 };
358
359 pCodeInstruction pciGOTO = {
360   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
361    AnalyzeGOTO,
362    genericDestruct,
363    genericPrint},
364   POC_GOTO,
365   "GOTO",
366   NULL, // operand
367   1,    // num ops
368   0,0,  // dest, bit instruction
369   PCC_NONE,   // inCond
370   PCC_NONE    // outCond
371 };
372
373
374 pCodeInstruction pciINCF = {
375   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
376    genericAnalyze,
377    genericDestruct,
378    genericPrint},
379   POC_INCF,
380   "INCF",
381   NULL, // operand
382   2,    // num ops
383   1,0,  // dest, bit instruction
384   PCC_REGISTER,   // inCond
385   PCC_REGISTER    // outCond
386 };
387
388 pCodeInstruction pciINCFW = {
389   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
390    genericAnalyze,
391    genericDestruct,
392    genericPrint},
393   POC_INCFW,
394   "INCF",
395   NULL, // operand
396   2,    // num ops
397   0,0,  // dest, bit instruction
398   PCC_REGISTER,   // inCond
399   PCC_W    // outCond
400 };
401
402 pCodeInstruction pciINCFSZ = {
403   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
404    AnalyzeSKIP,
405    genericDestruct,
406    genericPrint},
407   POC_INCFSZ,
408   "INCFSZ",
409   NULL, // operand
410   2,    // num ops
411   1,0,  // dest, bit instruction
412   PCC_REGISTER,   // inCond
413   PCC_REGISTER    // outCond
414 };
415
416 pCodeInstruction pciINCFSZW = {
417   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
418    AnalyzeSKIP,
419    genericDestruct,
420    genericPrint},
421   POC_INCFSZW,
422   "INCFSZ",
423   NULL, // operand
424   2,    // num ops
425   0,0,  // dest, bit instruction
426   PCC_REGISTER,   // inCond
427   PCC_W           // outCond
428 };
429
430 pCodeInstruction pciIORWF = {
431   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
432    genericAnalyze,
433    genericDestruct,
434    genericPrint},
435   POC_IORWF,
436   "IORWF",
437   NULL, // operand
438   2,    // num ops
439   1,0,  // dest, bit instruction
440   (PCC_W | PCC_REGISTER),   // inCond
441   (PCC_REGISTER | PCC_Z) // outCond
442 };
443
444 pCodeInstruction pciIORFW = {
445   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
446    genericAnalyze,
447    genericDestruct,
448    genericPrint},
449   POC_IORWF,
450   "IORWF",
451   NULL, // operand
452   2,    // num ops
453   0,0,  // dest, bit instruction
454   (PCC_W | PCC_REGISTER),   // inCond
455   (PCC_W | PCC_Z) // outCond
456 };
457
458 pCodeInstruction pciIORLW = {
459   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
460    genericAnalyze,
461    genericDestruct,
462    genericPrint},
463   POC_IORLW,
464   "IORLW",
465   NULL, // operand
466   1,    // num ops
467   0,0,  // dest, bit instruction
468   PCC_W,   // inCond
469   (PCC_W | PCC_Z) // outCond
470 };
471
472 pCodeInstruction pciMOVF = {
473   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
474    genericAnalyze,
475    genericDestruct,
476    genericPrint},
477   POC_MOVF,
478   "MOVF",
479   NULL, // operand
480   2,    // num ops
481   1,0,  // dest, bit instruction
482   PCC_REGISTER,   // inCond
483   PCC_Z // outCond
484 };
485
486 pCodeInstruction pciMOVFW = {
487   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
488    genericAnalyze,
489    genericDestruct,
490    genericPrint},
491   POC_MOVFW,
492   "MOVF",
493   NULL, // operand
494   2,    // num ops
495   0,0,  // dest, bit instruction
496   PCC_REGISTER,   // inCond
497   (PCC_W | PCC_Z) // outCond
498 };
499
500 pCodeInstruction pciMOVWF = {
501   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
502    genericAnalyze,
503    genericDestruct,
504    genericPrint},
505   POC_MOVWF,
506   "MOVWF",
507   NULL, // operand
508   1,    // num ops
509   0,0,  // dest, bit instruction
510   PCC_W,   // inCond
511   0 // outCond
512 };
513
514 pCodeInstruction pciMOVLW = {
515   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
516    genericAnalyze,
517    genericDestruct,
518    genericPrint},
519   POC_MOVLW,
520   "MOVLW",
521   NULL, // operand
522   1,    // num ops
523   0,0,  // dest, bit instruction
524   PCC_NONE,   // inCond
525   PCC_W // outCond
526 };
527
528 pCodeInstruction pciNEGF = {
529   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
530    genericAnalyze,
531    genericDestruct,
532    genericPrint},
533   POC_NEGF,
534   "NEGF",
535   NULL, // operand
536   1,    // num ops
537   0,0,  // dest, bit instruction
538   PCC_REGISTER,   // inCond
539   PCC_NONE // outCond
540 };
541
542
543 pCodeInstruction pciRETLW = {
544   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
545    AnalyzeRETURN,
546    genericDestruct,
547    genericPrint},
548   POC_RETLW,
549   "RETLW",
550   NULL, // operand
551   1,    // num ops
552   0,0,  // dest, bit instruction
553   PCC_NONE,   // inCond
554   PCC_W // outCond
555 };
556
557 pCodeInstruction pciRETURN = {
558   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
559    AnalyzeRETURN,
560    genericDestruct,
561    genericPrint},
562   POC_RETURN,
563   "RETURN",
564   NULL, // operand
565   0,    // num ops
566   0,0,  // dest, bit instruction
567   PCC_NONE,   // inCond
568   PCC_W // outCond
569 };
570
571
572 pCodeInstruction pciSUBWF = {
573   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
574    genericAnalyze,
575    genericDestruct,
576    genericPrint},
577   POC_SUBWF,
578   "SUBWF",
579   NULL, // operand
580   2,    // num ops
581   1,0,  // dest, bit instruction
582   (PCC_W | PCC_REGISTER),   // inCond
583   (PCC_REGISTER | PCC_Z) // outCond
584 };
585
586 pCodeInstruction pciSUBFW = {
587   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
588    genericAnalyze,
589    genericDestruct,
590    genericPrint},
591   POC_SUBWF,
592   "SUBWF",
593   NULL, // operand
594   2,    // num ops
595   0,0,  // dest, bit instruction
596   (PCC_W | PCC_REGISTER),   // inCond
597   (PCC_W | PCC_Z) // outCond
598 };
599
600 pCodeInstruction pciSUBLW = {
601   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
602    genericAnalyze,
603    genericDestruct,
604    genericPrint},
605   POC_SUBLW,
606   "SUBLW",
607   NULL, // operand
608   1,    // num ops
609   0,0,  // dest, bit instruction
610   PCC_W,   // inCond
611   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
612 };
613
614 pCodeInstruction pciTRIS = {
615   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
616    genericAnalyze,
617    genericDestruct,
618    genericPrint},
619   POC_TRIS,
620   "TRIS",
621   NULL, // operand
622   1,    // num ops
623   0,0,  // dest, bit instruction
624   PCC_NONE,   // inCond
625   PCC_NONE
626 };
627
628
629 pCodeInstruction pciXORWF = {
630   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
631    genericAnalyze,
632    genericDestruct,
633    genericPrint},
634   POC_XORWF,
635   "XORWF",
636   NULL, // operand
637   2,    // num ops
638   1,0,  // dest, bit instruction
639   (PCC_W | PCC_REGISTER),   // inCond
640   (PCC_REGISTER | PCC_Z) // outCond
641 };
642
643 pCodeInstruction pciXORFW = {
644   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
645    genericAnalyze,
646    genericDestruct,
647    genericPrint},
648   POC_XORWF,
649   "XORWF",
650   NULL, // operand
651   2,    // num ops
652   0,0,  // dest, bit instruction
653   (PCC_W | PCC_REGISTER),   // inCond
654   (PCC_W | PCC_Z) // outCond
655 };
656
657 pCodeInstruction pciXORLW = {
658   {PC_OPCODE, NULL, NULL, 0, NULL, NULL, NULL, NULL, 
659    genericAnalyze,
660    genericDestruct,
661    genericPrint},
662   POC_XORLW,
663   "XORLW",
664   NULL, // operand
665   1,    // num ops
666   0,0,  // dest, bit instruction
667   PCC_W,   // inCond
668   (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
669 };
670
671
672 #define MAX_PIC14MNEMONICS 100
673 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
674
675 char *Safe_strdup(char *str)
676 {
677   char *copy;
678
679   if(!str)
680     return NULL;
681
682   copy = strdup(str);
683   if(!copy) {
684     fprintf(stderr, "out of memory %s,%d\n",__FUNCTION__,__LINE__);
685     exit(1);
686   }
687
688   return copy;
689     
690 }
691
692
693 /*-----------------------------------------------------------------*/
694 /* SAFE_snprintf - like snprintf except the string pointer is      */
695 /*                 after the string has been printed to. This is   */
696 /*                 useful for printing to string as though if it   */
697 /*                 were a stream.                                  */
698 /*-----------------------------------------------------------------*/
699 void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
700 {
701   va_list val;
702   int len;
703
704   if(!str || !*str)
705     return;
706
707   va_start(val, format);
708   vsnprintf(*str, *size, format, val);
709   va_end (val);
710
711   len = strlen(*str);
712   *str += len;
713   *size -= len;
714
715 }
716
717 void  pCodeInitRegisters(void)
718 {
719
720   pc_fsr.rIdx = 4;
721   pc_fsr.r = pic14_regWithIdx(4);
722
723 }
724
725 /*-----------------------------------------------------------------*/
726 /*  mnem2key - convert a pic mnemonic into a hash key              */
727 /*   (BTW - this spreads the mnemonics quite well)                 */
728 /*                                                                 */
729 /*-----------------------------------------------------------------*/
730
731 int mnem2key(char const *mnem)
732 {
733   int key = 0;
734
735   if(!mnem)
736     return 0;
737
738   while(*mnem) {
739
740     key += toupper(*mnem++) +1;
741
742   }
743
744   return (key & 0x1f);
745
746 }
747
748 void pic14initMnemonics(void)
749 {
750   int i = 0;
751   int key;
752   //  char *str;
753   pCodeInstruction *pci;
754
755   if(mnemonics_initialized)
756     return;
757
758   pic14Mnemonics[POC_ADDLW] = &pciADDLW;
759   pic14Mnemonics[POC_ADDWF] = &pciADDWF;
760   pic14Mnemonics[POC_ADDFW] = &pciADDFW;
761   pic14Mnemonics[POC_ANDLW] = &pciANDLW;
762   pic14Mnemonics[POC_ANDWF] = &pciANDWF;
763   pic14Mnemonics[POC_ANDFW] = &pciANDFW;
764   pic14Mnemonics[POC_BCF] = &pciBCF;
765   pic14Mnemonics[POC_BSF] = &pciBSF;
766   pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
767   pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
768   pic14Mnemonics[POC_CALL] = &pciCALL;
769   pic14Mnemonics[POC_COMF] = &pciCOMF;
770   pic14Mnemonics[POC_CLRF] = &pciCLRF;
771   pic14Mnemonics[POC_CLRW] = &pciCLRW;
772   pic14Mnemonics[POC_DECF] = &pciDECF;
773   pic14Mnemonics[POC_DECFW] = &pciDECFW;
774   pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
775   pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
776   pic14Mnemonics[POC_GOTO] = &pciGOTO;
777   pic14Mnemonics[POC_INCF] = &pciINCF;
778   pic14Mnemonics[POC_INCFW] = &pciINCFW;
779   pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
780   pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
781   pic14Mnemonics[POC_IORLW] = &pciIORLW;
782   pic14Mnemonics[POC_IORWF] = &pciIORWF;
783   pic14Mnemonics[POC_IORFW] = &pciIORFW;
784   pic14Mnemonics[POC_MOVF] = &pciMOVF;
785   pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
786   pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
787   pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
788   pic14Mnemonics[POC_NEGF] = &pciNEGF;
789   pic14Mnemonics[POC_RETLW] = &pciRETLW;
790   pic14Mnemonics[POC_RETURN] = &pciRETURN;
791   pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
792   pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
793   pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
794   pic14Mnemonics[POC_TRIS] = &pciTRIS;
795   pic14Mnemonics[POC_XORLW] = &pciXORLW;
796   pic14Mnemonics[POC_XORWF] = &pciXORWF;
797   pic14Mnemonics[POC_XORFW] = &pciXORFW;
798
799   for(i=0; i<MAX_PIC14MNEMONICS; i++)
800     if(pic14Mnemonics[i])
801       hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
802   pci = hTabFirstItem(pic14MnemonicsHash, &key);
803
804   while(pci) {
805     fprintf( stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic);
806     pci = hTabNextItem(pic14MnemonicsHash, &key);
807   }
808
809   mnemonics_initialized = 1;
810 }
811
812 int getpCode(char *mnem,unsigned dest)
813 {
814
815   pCodeInstruction *pci;
816   int key = mnem2key(mnem);
817
818   if(!mnemonics_initialized)
819     pic14initMnemonics();
820
821   pci = hTabFirstItemWK(pic14MnemonicsHash, key);
822
823   while(pci) {
824
825     if(STRCASECMP(pci->mnemonic, mnem) == 0) {
826       if((pci->num_ops <= 1) || (pci->dest == dest))
827         return(pci->op);
828     }
829
830     pci = hTabNextItemWK (pic14MnemonicsHash);
831   
832   }
833
834   return -1;
835 }
836
837 char getpBlock_dbName(pBlock *pb)
838 {
839   if(!pb)
840     return 0;
841
842   if(pb->cmemmap)
843     return pb->cmemmap->dbName;
844
845   return pb->dbName;
846 }
847 /*-----------------------------------------------------------------*/
848 /* movepBlock2Head - given the dbname of a pBlock, move all        */
849 /*                   instances to the front of the doubly linked   */
850 /*                   list of pBlocks                               */
851 /*-----------------------------------------------------------------*/
852
853 void movepBlock2Head(char dbName)
854 {
855   pBlock *pb;
856
857   pb = the_pFile->pbHead;
858
859   while(pb) {
860
861     if(getpBlock_dbName(pb) == dbName) {
862       pBlock *pbn = pb->next;
863       pb->next = the_pFile->pbHead;
864       the_pFile->pbHead->prev = pb;
865       the_pFile->pbHead = pb;
866
867       if(pb->prev)
868         pb->prev->next = pbn;
869
870       // If the pBlock that we just moved was the last
871       // one in the link of all of the pBlocks, then we
872       // need to point the tail to the block just before
873       // the one we moved.
874       // Note: if pb->next is NULL, then pb must have 
875       // been the last pBlock in the chain.
876
877       if(pbn)
878         pbn->prev = pb->prev;
879       else
880         the_pFile->pbTail = pb->prev;
881
882       pb = pbn;
883
884     } else
885       pb = pb->next;
886
887   }
888
889 }
890
891 void copypCode(FILE *of, char dbName)
892 {
893   pBlock *pb;
894
895   if(!of || !the_pFile)
896     return;
897
898   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
899     if(getpBlock_dbName(pb) == dbName)
900       printpBlock(of,pb);
901   }
902
903 }
904 void pcode_test(void)
905 {
906
907   printf("pcode is alive!\n");
908
909   //initMnemonics();
910
911   if(the_pFile) {
912
913     pBlock *pb;
914     FILE *pFile;
915     char buffer[100];
916
917     /* create the file name */
918     strcpy(buffer,srcFileName);
919     strcat(buffer,".p");
920
921     if( !(pFile = fopen(buffer, "w" ))) {
922       werror(E_FILE_OPEN_ERR,buffer);
923       exit(1);
924     }
925
926     fprintf(pFile,"pcode dump\n\n");
927
928     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
929       fprintf(pFile,"\n\tNew pBlock\n\n");
930       if(pb->cmemmap)
931         fprintf(pFile,"%s",pb->cmemmap->sname);
932       else
933         fprintf(pFile,"internal pblock");
934
935       fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
936       printpBlock(pFile,pb);
937     }
938   }
939 }
940 static int RegCond(pCodeOp *pcop)
941 {
942
943   if(!pcop)
944     return 0;
945
946   if(pcop->type == PO_BIT  && !strcmp(pcop->name, pc_status.pcop.name)) {
947     switch(PCOB(pcop)->bit) {
948     case PIC_C_BIT:
949       return PCC_C;
950     case PIC_DC_BIT:
951         return PCC_DC;
952     case PIC_Z_BIT:
953       return PCC_Z;
954     }
955
956   }
957
958   return 0;
959 }
960
961 /*-----------------------------------------------------------------*/
962 /* newpCode - create and return a newly initialized pCode          */
963 /*                                                                 */
964 /*  fixme - rename this                                            */
965 /*                                                                 */
966 /* The purpose of this routine is to create a new Instruction      */
967 /* pCode. This is called by gen.c while the assembly code is being */
968 /* generated.                                                      */
969 /*                                                                 */
970 /* Inouts:                                                         */
971 /*  PIC_OPCODE op - the assembly instruction we wish to create.    */
972 /*                  (note that the op is analogous to but not the  */
973 /*                  same thing as the opcode of the instruction.)  */
974 /*  pCdoeOp *pcop - pointer to the operand of the instruction.     */
975 /*                                                                 */
976 /* Outputs:                                                        */
977 /*  a pointer to the new malloc'd pCode is returned.               */
978 /*                                                                 */
979 /*                                                                 */
980 /*                                                                 */
981 /*-----------------------------------------------------------------*/
982 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
983 {
984   pCodeInstruction *pci ;
985
986   if(!mnemonics_initialized)
987     pic14initMnemonics();
988     
989   pci = Safe_calloc(1, sizeof(pCodeInstruction));
990
991   if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
992     memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
993     pci->pcop = pcop;
994
995     if(pci->inCond == PCC_EXAMINE_PCOP)
996       pci->inCond   = RegCond(pcop);
997
998     if(pci->outCond == PCC_EXAMINE_PCOP)
999       pci->outCond   = RegCond(pcop);
1000
1001     return (pCode *)pci;
1002   }
1003
1004   fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1005   exit(1);
1006
1007   return NULL;
1008 }       
1009
1010 /*-----------------------------------------------------------------*/
1011 /* newpCodeWild - create a "wild" as in wild card pCode            */
1012 /*                                                                 */
1013 /* Wild pcodes are used during the peep hole optimizer to serve    */
1014 /* as place holders for any instruction. When a snippet of code is */
1015 /* compared to a peep hole rule, the wild card opcode will match   */
1016 /* any instruction. However, the optional operand and label are    */
1017 /* additional qualifiers that must also be matched before the      */
1018 /* line (of assembly code) is declared matched. Note that the      */
1019 /* operand may be wild too.                                        */
1020 /*                                                                 */
1021 /*   Note, a wild instruction is specified just like a wild var:   */
1022 /*      %4     ; A wild instruction,                               */
1023 /*  See the peeph.def file for additional examples                 */
1024 /*                                                                 */
1025 /*-----------------------------------------------------------------*/
1026
1027 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1028 {
1029
1030   pCodeWild *pcw;
1031     
1032   pcw = Safe_calloc(1,sizeof(pCodeWild));
1033
1034   pcw->pc.type = PC_WILD;
1035   pcw->pc.prev = pcw->pc.next = NULL;
1036   pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
1037   pcw->pc.pb = NULL;
1038
1039   pcw->pc.analyze = genericAnalyze;
1040   pcw->pc.destruct = genericDestruct;
1041   pcw->pc.print = genericPrint;
1042
1043   pcw->id = pCodeID;              // this is the 'n' in %n
1044   pcw->operand = optional_operand;
1045   pcw->label   = optional_label;
1046
1047   return ( (pCode *)pcw);
1048   
1049 }
1050
1051 /*-----------------------------------------------------------------*/
1052 /* newPcodeCharP - create a new pCode from a char string           */
1053 /*-----------------------------------------------------------------*/
1054
1055 pCode *newpCodeCharP(char *cP)
1056 {
1057
1058   pCodeComment *pcc ;
1059     
1060   pcc = Safe_calloc(1,sizeof(pCodeComment));
1061
1062   pcc->pc.type = PC_COMMENT;
1063   pcc->pc.prev = pcc->pc.next = NULL;
1064   pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1065   pcc->pc.pb = NULL;
1066
1067   pcc->pc.analyze = genericAnalyze;
1068   pcc->pc.destruct = genericDestruct;
1069   pcc->pc.print = genericPrint;
1070
1071   pcc->comment = Safe_strdup(cP);
1072
1073   return ( (pCode *)pcc);
1074
1075 }
1076
1077 /*-----------------------------------------------------------------*/
1078 /* newpCodeGLabel - create a new global label                      */
1079 /*-----------------------------------------------------------------*/
1080
1081
1082 pCode *newpCodeFunction(char *mod,char *f)
1083 {
1084   pCodeFunction *pcf;
1085
1086   _ALLOC(pcf,sizeof(pCodeFunction));
1087
1088   pcf->pc.type = PC_FUNCTION;
1089   pcf->pc.prev = pcf->pc.next = NULL;
1090   pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1091   pcf->pc.pb = NULL;
1092
1093   pcf->pc.analyze = genericAnalyze;
1094   pcf->pc.destruct = genericDestruct;
1095   pcf->pc.print = pCodePrintFunction;
1096
1097   if(mod) {
1098     _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1099     strcpy(pcf->modname,mod);
1100   } else
1101     pcf->modname = NULL;
1102
1103   if(f) {
1104     _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1105     strcpy(pcf->fname,f);
1106   } else
1107     pcf->fname = NULL;
1108
1109   return ( (pCode *)pcf);
1110
1111 }
1112
1113 static void pCodeLabelDestruct(pCode *pc)
1114 {
1115
1116   if(!pc)
1117     return;
1118
1119   unlinkPC(pc);
1120
1121   if(PCL(pc)->label)
1122     free(PCL(pc)->label);
1123
1124   free(pc);
1125
1126 }
1127
1128 pCode *newpCodeLabel(int key)
1129 {
1130
1131   char *s = buffer;
1132   pCodeLabel *pcl;
1133     
1134   pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1135
1136   pcl->pc.type = PC_LABEL;
1137   pcl->pc.prev = pcl->pc.next = NULL;
1138   pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1139   pcl->pc.pb = NULL;
1140
1141   pcl->pc.analyze = genericAnalyze;
1142   pcl->pc.destruct = pCodeLabelDestruct;
1143   pcl->pc.print = pCodePrintLabel;
1144
1145   pcl->key = key;
1146
1147   if(key>0) {
1148     sprintf(s,"_%05d_DS_",key);
1149     pcl->label = Safe_strdup(s);
1150   } else
1151     pcl->label = NULL;
1152
1153   return ( (pCode *)pcl);
1154
1155 }
1156 pCode *newpCodeLabelStr(char *str)
1157 {
1158   pCode *pc = newpCodeLabel(-1);
1159
1160   PCL(pc)->label = Safe_strdup(str);
1161
1162   return pc;
1163 }
1164
1165 /*-----------------------------------------------------------------*/
1166 /* newpBlock - create and return a pointer to a new pBlock         */
1167 /*-----------------------------------------------------------------*/
1168 pBlock *newpBlock(void)
1169 {
1170
1171   pBlock *PpB;
1172
1173   PpB = Safe_calloc(1,sizeof(pBlock) );
1174   PpB->next = PpB->prev = NULL;
1175
1176   PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1177   PpB->registers = NULL;
1178   PpB->visited = 0;
1179
1180   return PpB;
1181
1182 }
1183
1184 /*-----------------------------------------------------------------*/
1185 /* newpCodeChai0n - create a new chain of pCodes                    */
1186 /*-----------------------------------------------------------------*
1187  *
1188  *  This function will create a new pBlock and the pointer to the
1189  *  pCode that is passed in will be the first pCode in the block.
1190  *-----------------------------------------------------------------*/
1191
1192
1193 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1194 {
1195
1196   pBlock *pB  = newpBlock();
1197
1198   pB->pcHead  = pB->pcTail = pc;
1199   pB->cmemmap = cm;
1200   pB->dbName  = c;
1201
1202   return pB;
1203 }
1204
1205 /*-----------------------------------------------------------------*/
1206 /* newpCodeOpLabel - Create a new label given the key              */
1207 /*  Note, a negative key means that the label is part of wild card */
1208 /*  (and hence a wild card label) used in the pCodePeep            */
1209 /*   optimizations).                                               */
1210 /*-----------------------------------------------------------------*/
1211
1212 pCodeOp *newpCodeOpLabel(int key)
1213 {
1214   char *s = buffer;
1215   pCodeOp *pcop;
1216
1217   pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1218   pcop->type = PO_LABEL;
1219
1220   if(key>0) {
1221     sprintf(s,"_%05d_DS_",key);
1222     pcop->name = Safe_strdup(s);
1223   } else
1224     pcop->name = NULL;
1225
1226   ((pCodeOpLabel *)pcop)->key = key;
1227
1228   return pcop;
1229 }
1230
1231 pCodeOp *newpCodeOpLit(int lit)
1232 {
1233   char *s = buffer;
1234   pCodeOp *pcop;
1235
1236
1237   pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1238   pcop->type = PO_LITERAL;
1239   if(lit>=0) {
1240     sprintf(s,"0x%02x",lit);
1241     pcop->name = Safe_strdup(s);
1242   } else
1243     pcop->name = NULL;
1244
1245   ((pCodeOpLit *)pcop)->lit = lit;
1246
1247   return pcop;
1248 }
1249
1250 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1251 {
1252   char *s = buffer;
1253   pCodeOp *pcop;
1254
1255
1256   if(!pcp || !subtype) {
1257     fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1258     exit(1);
1259   }
1260
1261   pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1262   pcop->type = PO_WILD;
1263   sprintf(s,"%%%d",id);
1264   pcop->name = Safe_strdup(s);
1265
1266   PCOW(pcop)->id = id;
1267   PCOW(pcop)->pcp = pcp;
1268   PCOW(pcop)->subtype = subtype;
1269   PCOW(pcop)->matched = NULL;
1270
1271   return pcop;
1272 }
1273
1274 pCodeOp *newpCodeOpBit(char *s, int bit)
1275 {
1276   pCodeOp *pcop;
1277
1278   pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1279   pcop->type = PO_BIT;
1280   pcop->name = Safe_strdup(s);   
1281
1282   PCOB(pcop)->bit = bit;
1283   if(bit>=0)
1284     PCOB(pcop)->inBitSpace = 1;
1285   else
1286     PCOB(pcop)->inBitSpace = 0;
1287
1288   return pcop;
1289 }
1290
1291 /*-----------------------------------------------------------------*/
1292 /*-----------------------------------------------------------------*/
1293
1294 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1295 {
1296   pCodeOp *pcop;
1297
1298   switch(type) {
1299   case PO_BIT:
1300     pcop = newpCodeOpBit(name, -1);
1301     break;
1302
1303   case PO_LITERAL:
1304     pcop = newpCodeOpLit(-1);
1305     break;
1306
1307   case PO_LABEL:
1308     pcop = newpCodeOpLabel(-1);
1309     break;
1310
1311   default:
1312     pcop = Safe_calloc(1,sizeof(pCodeOp) );
1313     pcop->type = type;
1314     pcop->name = Safe_strdup(name);   
1315   }
1316
1317   return pcop;
1318 }
1319
1320 /*-----------------------------------------------------------------*/
1321 /* addpCode2pBlock - place the pCode into the pBlock linked list   */
1322 /*-----------------------------------------------------------------*/
1323 void addpCode2pBlock(pBlock *pb, pCode *pc)
1324 {
1325   if(!pb->pcHead) {
1326     /* If this is the first pcode to be added to a block that
1327      * was initialized with a NULL pcode, then go ahead and
1328      * make this pcode the head and tail */
1329     pb->pcHead  = pb->pcTail = pc;
1330   } else {
1331     pb->pcTail->next = pc;
1332     pc->prev = pb->pcTail;
1333     pc->next = NULL;
1334     pc->pb = pb;
1335     pb->pcTail = pc;
1336   }
1337 }
1338
1339 /*-----------------------------------------------------------------*/
1340 /* addpBlock - place a pBlock into the pFile                       */
1341 /*-----------------------------------------------------------------*/
1342 void addpBlock(pBlock *pb)
1343 {
1344
1345   if(!the_pFile) {
1346     /* First time called, we'll pass through here. */
1347     _ALLOC(the_pFile,sizeof(the_pFile));
1348     the_pFile->pbHead = the_pFile->pbTail = pb;
1349     the_pFile->functions = NULL;
1350     return;
1351   }
1352
1353   the_pFile->pbTail->next = pb;
1354   pb->prev = the_pFile->pbTail;
1355   pb->next = NULL;
1356   the_pFile->pbTail = pb;
1357 }
1358
1359 /*-----------------------------------------------------------------*/
1360 /* printpCode - write the contents of a pCode to a file            */
1361 /*-----------------------------------------------------------------*/
1362 void printpCode(FILE *of, pCode *pc)
1363 {
1364
1365   if(!pc || !of)
1366     return;
1367
1368   if(pc->print) {
1369     pc->print(of,pc);
1370     return;
1371   }
1372
1373   fprintf(of,"warning - unable to print pCode\n");
1374 }
1375
1376 /*-----------------------------------------------------------------*/
1377 /* printpBlock - write the contents of a pBlock to a file          */
1378 /*-----------------------------------------------------------------*/
1379 void printpBlock(FILE *of, pBlock *pb)
1380 {
1381   pCode *pc;
1382
1383   if(!pb)
1384     return;
1385
1386   if(!of)
1387     of = stderr;
1388
1389   for(pc = pb->pcHead; pc; pc = pc->next)
1390     printpCode(of,pc);
1391
1392 }
1393
1394 /*-----------------------------------------------------------------*/
1395 /*                                                                 */
1396 /*       pCode processing                                          */
1397 /*                                                                 */
1398 /*                                                                 */
1399 /*                                                                 */
1400 /*-----------------------------------------------------------------*/
1401
1402 static void unlinkPC(pCode *pc)
1403 {
1404   if(pc  && pc->prev && pc->next) {
1405
1406     pc->prev->next = pc->next;
1407     pc->next->prev = pc->prev;
1408   }
1409 }
1410 static void genericDestruct(pCode *pc)
1411 {
1412   fprintf(stderr,"warning, calling default pCode destructor\n");
1413
1414   unlinkPC(pc);
1415
1416   free(pc);
1417
1418 }
1419
1420
1421 void pBlockRegs(FILE *of, pBlock *pb)
1422 {
1423
1424   regs  *r;
1425
1426   r = setFirstItem(pb->registers);
1427   while (r) {
1428     r = setNextItem(pb->registers);
1429   }
1430 }
1431
1432
1433 static char *get_op( pCodeInstruction *pcc)
1434 {
1435   regs *r;
1436
1437   if(pcc && pcc->pcop) {
1438
1439
1440     switch(pcc->pcop->type) {
1441
1442     case PO_FSR:
1443     case PO_GPR_TEMP:
1444       r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1445       //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1446       pBlockRegs(stderr,pcc->pc.pb);
1447       return r->name;
1448
1449     default:
1450       if  (pcc->pcop->name)
1451         return pcc->pcop->name;
1452
1453     }
1454   }
1455
1456   return "NO operand";
1457 }
1458
1459 /*-----------------------------------------------------------------*/
1460 /*-----------------------------------------------------------------*/
1461 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1462 {
1463
1464   fprintf(of,"pcodeopprint\n");
1465 }
1466
1467 char *pCode2str(char *str, int size, pCode *pc)
1468 {
1469   char *s = str;
1470
1471   switch(pc->type) {
1472
1473   case PC_OPCODE:
1474
1475     SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
1476
1477     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1478
1479       if(PCI(pc)->bit_inst) {
1480         if(PCI(pc)->pcop->type == PO_BIT) {
1481           if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1482             SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
1483                           PCI(pc)->pcop->name ,
1484                           PCI(pc)->pcop->name );
1485           else
1486             SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)), 
1487                           (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1488         } else
1489           SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
1490         //PCI(pc)->pcop->t.bit );
1491       } else {
1492
1493         if(PCI(pc)->pcop->type == PO_BIT) {
1494           if( PCI(pc)->num_ops == 2)
1495             SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1496           else
1497             SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
1498
1499         }else {
1500           SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
1501
1502           if( PCI(pc)->num_ops == 2)
1503             SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1504         }
1505       }
1506
1507     }
1508     break;
1509
1510   case PC_COMMENT:
1511     /* assuming that comment ends with a \n */
1512     SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
1513     break;
1514
1515   case PC_LABEL:
1516     SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
1517     break;
1518   case PC_FUNCTION:
1519     SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
1520     break;
1521   case PC_WILD:
1522     SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
1523     break;
1524
1525   }
1526
1527   return str;
1528
1529 }
1530
1531 /*-----------------------------------------------------------------*/
1532 /* genericPrint - the contents of a pCode to a file                */
1533 /*-----------------------------------------------------------------*/
1534 static void genericPrint(FILE *of, pCode *pc)
1535 {
1536
1537   if(!pc || !of)
1538     return;
1539
1540   switch(pc->type) {
1541   case PC_COMMENT:
1542     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1543     break;
1544
1545   case PC_OPCODE:
1546     // If the opcode has a label, print that first
1547     {
1548       pBranch *pbl = pc->label;
1549       while(pbl) {
1550         if(pbl->pc->type == PC_LABEL)
1551           pCodePrintLabel(of, pbl->pc);
1552         pbl = pbl->next;
1553       }
1554     }
1555
1556
1557     {
1558       char str[256];
1559       
1560       pCode2str(str, 256, pc);
1561
1562       fprintf(of,"%s",str);
1563     }
1564
1565     {
1566       pBranch *dpb = pc->to;   // debug
1567       while(dpb) {
1568         switch ( dpb->pc->type) {
1569         case PC_OPCODE:
1570           fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1571           break;
1572         case PC_LABEL:
1573           fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1574           break;
1575         case PC_FUNCTION:
1576           fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1577           break;
1578         case PC_COMMENT:
1579         case PC_WILD:
1580           break;
1581         }
1582         dpb = dpb->next;
1583       }
1584       fprintf(of,"\n");
1585     }
1586
1587     break;
1588
1589   case PC_WILD:
1590     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1591     if(pc->label)
1592       pCodePrintLabel(of, pc->label->pc);
1593
1594     if(PCW(pc)->operand) {
1595       fprintf(of,";\toperand  ");
1596       pCodeOpPrint(of,PCW(pc)->operand );
1597     }
1598     break;
1599
1600   case PC_LABEL:
1601   default:
1602     fprintf(of,"unknown pCode type %d\n",pc->type);
1603   }
1604
1605 }
1606
1607 /*-----------------------------------------------------------------*/
1608 /* pCodePrintFunction - prints function begin/end                  */
1609 /*-----------------------------------------------------------------*/
1610
1611 static void pCodePrintFunction(FILE *of, pCode *pc)
1612 {
1613
1614   if(!pc || !of)
1615     return;
1616
1617   if( ((pCodeFunction *)pc)->modname) 
1618     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1619
1620   if(PCF(pc)->fname) {
1621     pBranch *exits = pc->to;
1622     int i=0;
1623     fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1624     while(exits) {
1625       i++;
1626       exits = exits->next;
1627     }
1628     //if(i) i--;
1629     fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1630     
1631   }else {
1632     if(pc->from && 
1633        pc->from->pc->type == PC_FUNCTION &&
1634        PCF(pc->from->pc)->fname) 
1635       fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1636     else
1637       fprintf(of,"; exit point [can't find entry point]\n");
1638   }
1639 }
1640 /*-----------------------------------------------------------------*/
1641 /* pCodePrintLabel - prints label                                  */
1642 /*-----------------------------------------------------------------*/
1643
1644 static void pCodePrintLabel(FILE *of, pCode *pc)
1645 {
1646
1647   if(!pc || !of)
1648     return;
1649
1650   if(PCL(pc)->label) 
1651     fprintf(of,"%s\n",PCL(pc)->label);
1652   else if (PCL(pc)->key >=0) 
1653     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1654   else
1655     fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
1656
1657 }
1658 /*-----------------------------------------------------------------*/
1659
1660 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1661 {
1662   pBranch *b;
1663
1664   if(!h)
1665     return n;
1666
1667   b = h;
1668   while(b->next)
1669     b = b->next;
1670
1671   b->next = n;
1672
1673   return h;
1674   
1675 }  
1676 /*-----------------------------------------------------------------*/
1677 /* pBranchLink - given two pcodes, this function will link them    */
1678 /*               together through their pBranches                  */
1679 /*-----------------------------------------------------------------*/
1680 static void pBranchLink(pCode *f, pCode *t)
1681 {
1682   pBranch *b;
1683
1684   // Declare a new branch object for the 'from' pCode.
1685
1686   _ALLOC(b,sizeof(pBranch));
1687   b->pc = t;                    // The link to the 'to' pCode.
1688   b->next = NULL;
1689
1690   f->to = pBranchAppend(f->to,b);
1691
1692   // Now do the same for the 'to' pCode.
1693
1694   _ALLOC(b,sizeof(pBranch));
1695   b->pc = f;
1696   b->next = NULL;
1697
1698   t->from = pBranchAppend(t->from,b);
1699   
1700 }
1701
1702 #if 0
1703 /*-----------------------------------------------------------------*/
1704 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1705 /*               a pCode                                           */
1706 /*-----------------------------------------------------------------*/
1707 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1708 {
1709   while(pb) {
1710
1711     if(pb->pc == pc)
1712       return pb;
1713
1714     pb = pb->next;
1715   }
1716
1717   return NULL;
1718 }
1719
1720 /*-----------------------------------------------------------------*/
1721 /* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
1722 /*-----------------------------------------------------------------*/
1723 static void pCodeUnlink(pCode *pc)
1724 {
1725   pBranch *pb1,*pb2;
1726   pCode *pc1;
1727
1728   if(!pc->prev || !pc->next) {
1729     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1730     exit(1);
1731   }
1732
1733   /* first remove the pCode from the chain */
1734   pc->prev->next = pc->next;
1735   pc->next->prev = pc->prev;
1736
1737   /* Now for the hard part... */
1738
1739   /* Remove the branches */
1740
1741   pb1 = pc->from;
1742   while(pb1) {
1743     pc1 = pb1->pc;    /* Get the pCode that branches to the
1744                        * one we're unlinking */
1745
1746     /* search for the link back to this pCode (the one we're
1747      * unlinking) */
1748     if(pb2 = pBranchFind(pc1->to,pc)) {
1749       pb2->pc = pc->to->pc;  // make the replacement
1750
1751       /* if the pCode we're unlinking contains multiple 'to'
1752        * branches (e.g. this a skip instruction) then we need
1753        * to copy these extra branches to the chain. */
1754       if(pc->to->next)
1755         pBranchAppend(pb2, pc->to->next);
1756     }
1757     
1758     pb1 = pb1->next;
1759   }
1760
1761
1762 }
1763 #endif
1764 /*-----------------------------------------------------------------*/
1765 /*-----------------------------------------------------------------*/
1766 static void genericAnalyze(pCode *pc)
1767 {
1768   switch(pc->type) {
1769   case PC_WILD:
1770   case PC_COMMENT:
1771     return;
1772   case PC_LABEL:
1773   case PC_FUNCTION:
1774   case PC_OPCODE:
1775     {
1776       // Go through the pCodes that are in pCode chain and link
1777       // them together through the pBranches. Note, the pCodes
1778       // are linked together as a contiguous stream like the 
1779       // assembly source code lines. The linking here mimics this
1780       // except that comments are not linked in.
1781       // 
1782       pCode *npc = pc->next;
1783       while(npc) {
1784         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1785           pBranchLink(pc,npc);
1786           return;
1787         } else
1788           npc = npc->next;
1789       }
1790     }
1791   }
1792 }
1793
1794 /*-----------------------------------------------------------------*/
1795 /* findLabel - Search the pCode for a particular label             */
1796 /*-----------------------------------------------------------------*/
1797 pCode * findLabel(pCodeOpLabel *pcop_label)
1798 {
1799   pBlock *pb;
1800   pCode  *pc;
1801   pBranch *pbr;
1802
1803   if(!the_pFile)
1804     return NULL;
1805
1806   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1807     for(pc = pb->pcHead; pc; pc = pc->next) {
1808       if(pc->type == PC_LABEL) {
1809         if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
1810           return pc;
1811       }
1812       if(pc->type == PC_OPCODE) {
1813         pbr = pc->label;
1814         while(pbr) {
1815           if(pbr->pc->type == PC_LABEL) {
1816             if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
1817               return pc;
1818           }
1819           pbr = pbr->next;
1820         }
1821       }
1822
1823     }
1824   }
1825
1826   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1827   return NULL;
1828 }
1829
1830 /*-----------------------------------------------------------------*/
1831 /* findNextInstruction - given a pCode, find the next instruction  */
1832 /*                       in the linked list                        */
1833 /*-----------------------------------------------------------------*/
1834 pCode * findNextInstruction(pCode *pc)
1835 {
1836
1837   while(pc) {
1838     if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
1839       return pc;
1840
1841     pc = pc->next;
1842   }
1843
1844   fprintf(stderr,"Couldn't find instruction\n");
1845   return NULL;
1846 }
1847
1848 /*-----------------------------------------------------------------*/
1849 /* findFunctionEnd - given a pCode find the end of the function    */
1850 /*                   that contains it     t                        */
1851 /*-----------------------------------------------------------------*/
1852 pCode * findFunctionEnd(pCode *pc)
1853 {
1854
1855   while(pc) {
1856     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
1857       return pc;
1858
1859     pc = pc->next;
1860   }
1861
1862   fprintf(stderr,"Couldn't find function end\n");
1863   return NULL;
1864 }
1865
1866 #if 0
1867 /*-----------------------------------------------------------------*/
1868 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
1869 /*                instruction with which it is associated.         */
1870 /*-----------------------------------------------------------------*/
1871 static void AnalyzeLabel(pCode *pc)
1872 {
1873
1874   pCodeUnlink(pc);
1875
1876 }
1877 #endif
1878
1879 static void AnalyzeGOTO(pCode *pc)
1880 {
1881
1882   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
1883
1884 }
1885
1886 static void AnalyzeSKIP(pCode *pc)
1887 {
1888
1889   pBranchLink(pc,findNextInstruction(pc->next));
1890   pBranchLink(pc,findNextInstruction(pc->next->next));
1891
1892 }
1893
1894 static void AnalyzeRETURN(pCode *pc)
1895 {
1896
1897   //  branch_link(pc,findFunctionEnd(pc->next));
1898
1899 }
1900
1901
1902 void AnalyzepBlock(pBlock *pb)
1903 {
1904   pCode *pc;
1905
1906   if(!pb)
1907     return;
1908
1909   /* Find all of the registers used in this pBlock */
1910   for(pc = pb->pcHead; pc; pc = pc->next) {
1911     if(pc->type == PC_OPCODE) {
1912       if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
1913
1914         /* Loop through all of the registers declared so far in
1915            this block and see if we find this new there */
1916
1917         regs *r = setFirstItem(pb->registers);
1918
1919         while(r) {
1920           if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
1921             PCOR(PCI(pc)->pcop)->r = r;
1922             break;
1923           }
1924           r = setNextItem(pb->registers);
1925         }
1926
1927         if(!r) {
1928           /* register wasn't found */
1929           r = Safe_calloc(1, sizeof(regs));
1930           memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
1931           addSet(&pb->registers, r);
1932           PCOR(PCI(pc)->pcop)->r = r;
1933           fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
1934         } else 
1935           fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
1936       }
1937     }
1938   }
1939 }
1940
1941 int OptimizepBlock(pBlock *pb)
1942 {
1943   pCode *pc;
1944   int matches =0;
1945
1946   if(!pb || !peepOptimizing)
1947     return 0;
1948
1949   fprintf(stderr," Optimizing pBlock\n");
1950
1951   for(pc = pb->pcHead; pc; pc = pc->next)
1952     matches += pCodePeepMatchRule(pc);
1953
1954   return matches;
1955
1956 }
1957 /*-----------------------------------------------------------------*/
1958 /* pBlockMergeLabels - remove the pCode labels from the pCode      */
1959 /*                     chain and put them into pBranches that are  */
1960 /*                     associated with the appropriate pCode       */
1961 /*                     instructions.                               */
1962 /*-----------------------------------------------------------------*/
1963 void pBlockMergeLabels(pBlock *pb)
1964 {
1965   pBranch *pbr;
1966   pCode *pc, *pcnext=NULL;
1967
1968   if(!pb)
1969     return;
1970
1971   for(pc = pb->pcHead; pc; pc = pc->next) {
1972
1973     if(pc->type == PC_LABEL) {
1974       if( !(pcnext = findNextInstruction(pc)) ) 
1975         return;  // Couldn't find an instruction associated with this label
1976
1977       // Unlink the pCode label from it's pCode chain
1978       if(pc->prev) 
1979         pc->prev->next = pc->next;
1980       if(pc->next)
1981         pc->next->prev = pc->prev;
1982
1983       // And link it into the instruction's pBranch labels. (Note, since
1984       // it's possible to have multiple labels associated with one instruction
1985       // we must provide a means to accomodate the additional labels. Thus
1986       // the labels are placed into the singly-linked list "label" as 
1987       // opposed to being a single member of the pCodeInstruction.)
1988
1989       _ALLOC(pbr,sizeof(pBranch));
1990       pbr->pc = pc;
1991       pbr->next = NULL;
1992
1993       pcnext->label = pBranchAppend(pcnext->label,pbr);
1994     }
1995
1996   }
1997
1998 }
1999
2000 /*-----------------------------------------------------------------*/
2001 /*-----------------------------------------------------------------*/
2002 void OptimizepCode(char dbName)
2003 {
2004 #define MAX_PASSES 4
2005
2006   int matches = 0;
2007   int passes = 0;
2008   pBlock *pb;
2009
2010   if(!the_pFile)
2011     return;
2012
2013   fprintf(stderr," Optimizing pCode\n");
2014
2015   do {
2016     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2017       if('*' == dbName || getpBlock_dbName(pb) == dbName)
2018         matches += OptimizepBlock(pb);
2019     }
2020   }
2021   while(matches && ++passes < MAX_PASSES);
2022
2023 }
2024
2025 /*-----------------------------------------------------------------*/
2026 /* AnalyzepCode - parse the pCode that has been generated and form */
2027 /*                all of the logical connections.                  */
2028 /*                                                                 */
2029 /* Essentially what's done here is that the pCode flow is          */
2030 /* determined.                                                     */
2031 /*-----------------------------------------------------------------*/
2032
2033 void AnalyzepCode(char dbName)
2034 {
2035   pBlock *pb;
2036   pCode *pc;
2037   pBranch *pbr;
2038
2039   if(!the_pFile)
2040     return;
2041
2042   fprintf(stderr," Analyzing pCode");
2043
2044   /* First, merge the labels with the instructions */
2045   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2046     if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2047       pBlockMergeLabels(pb);
2048       AnalyzepBlock(pb);
2049     }
2050   }
2051
2052   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2053     if('*' == dbName || getpBlock_dbName(pb) == dbName)
2054       OptimizepBlock(pb);
2055   }
2056
2057   /* Now build the call tree.
2058      First we examine all of the pCodes for functions.
2059      Keep in mind that the function boundaries coincide
2060      with pBlock boundaries. 
2061
2062      The algorithm goes something like this:
2063      We have two nested loops. The outer loop iterates
2064      through all of the pBlocks/functions. The inner
2065      loop iterates through all of the pCodes for
2066      a given pBlock. When we begin iterating through
2067      a pBlock, the variable pc_fstart, pCode of the start
2068      of a function, is cleared. We then search for pCodes
2069      of type PC_FUNCTION. When one is encountered, we
2070      initialize pc_fstart to this and at the same time
2071      associate a new pBranch object that signifies a 
2072      branch entry. If a return is found, then this signifies
2073      a function exit point. We'll link the pCodes of these
2074      returns to the matching pc_fstart.
2075
2076      When we're done, a doubly linked list of pBranches
2077      will exist. The head of this list is stored in
2078      `the_pFile', which is the meta structure for all
2079      of the pCode. Look at the printCallTree function
2080      on how the pBranches are linked together.
2081
2082    */
2083   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2084     if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2085       pCode *pc_fstart=NULL;
2086       for(pc = pb->pcHead; pc; pc = pc->next) {
2087         if(pc->type == PC_FUNCTION) {
2088           if (PCF(pc)->fname) {
2089             // I'm not liking this....
2090             // Found the beginning of a function.
2091             _ALLOC(pbr,sizeof(pBranch));
2092             pbr->pc = pc_fstart = pc;
2093             pbr->next = NULL;
2094
2095             the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2096
2097             // Here's a better way of doing the same:
2098             addSet(&pb->function_entries, pc);
2099
2100           } else {
2101             // Found an exit point in a function, e.g. return
2102             // (Note, there may be more than one return per function)
2103             if(pc_fstart)
2104               pBranchLink(pc_fstart, pc);
2105
2106             addSet(&pb->function_exits, pc);
2107           }
2108         } else  if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2109           addSet(&pb->function_calls,pc);
2110         }
2111       }
2112     }
2113   }
2114 }
2115
2116 /*-----------------------------------------------------------------*/
2117 /* ispCodeFunction - returns true if *pc is the pCode of a         */
2118 /*                   function                                      */
2119 /*-----------------------------------------------------------------*/
2120 bool ispCodeFunction(pCode *pc)
2121 {
2122
2123   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2124     return 1;
2125
2126   return 0;
2127 }
2128
2129 /*-----------------------------------------------------------------*/
2130 /* findFunction - Search for a function by name (given the name)   */
2131 /*                in the set of all functions that are in a pBlock */
2132 /* (note - I expect this to change because I'm planning to limit   */
2133 /*  pBlock's to just one function declaration                      */
2134 /*-----------------------------------------------------------------*/
2135 pCode *findFunction(char *fname)
2136 {
2137   pBlock *pb;
2138   pCode *pc;
2139   if(!fname)
2140     return NULL;
2141
2142   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2143
2144     pc = setFirstItem(pb->function_entries);
2145     while(pc) {
2146     
2147       if((pc->type == PC_FUNCTION) &&
2148          (PCF(pc)->fname) && 
2149          (strcmp(fname, PCF(pc)->fname)==0))
2150         return pc;
2151
2152       pc = setNextItem(pb->function_entries);
2153
2154     }
2155
2156   }
2157   return NULL;
2158 }
2159
2160 void MarkUsedRegisters(set *regset)
2161 {
2162
2163   regs *r1,*r2;
2164
2165   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2166     r2 = pic14_regWithIdx(r1->rIdx);
2167     r2->isFree = 0;
2168     r2->wasUsed = 1;
2169   }
2170 }
2171
2172 void pBlockStats(FILE *of, pBlock *pb)
2173 {
2174
2175   pCode *pc;
2176   regs  *r;
2177
2178   fprintf(of,"***\n  pBlock Stats\n***\n");
2179
2180   // for now just print the first element of each set
2181   pc = setFirstItem(pb->function_entries);
2182   if(pc) {
2183     fprintf(of,"entry\n");
2184     pc->print(of,pc);
2185   }
2186   pc = setFirstItem(pb->function_exits);
2187   if(pc) {
2188     fprintf(of,"has an exit\n");
2189     pc->print(of,pc);
2190   }
2191
2192   pc = setFirstItem(pb->function_calls);
2193   if(pc) {
2194     fprintf(of,"functions called\n");
2195
2196     while(pc) {
2197       pc->print(of,pc);
2198       pc = setNextItem(pb->function_calls);
2199     }
2200   }
2201
2202   r = setFirstItem(pb->registers);
2203   if(r) {
2204     int n = elementsInSet(pb->registers);
2205
2206     fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2207
2208     while (r) {
2209       fprintf(of,"   %s\n",r->name);
2210       r = setNextItem(pb->registers);
2211     }
2212   }
2213 }
2214
2215 /*-----------------------------------------------------------------*/
2216 /*-----------------------------------------------------------------*/
2217 void sequencepCode(void)
2218 {
2219   pBlock *pb;
2220   pCode *pc;
2221
2222
2223   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2224
2225     pb->seq = GpCodeSequenceNumber+1;
2226
2227     for( pc = pb->pcHead; pc; pc = pc->next)
2228       pc->seq = ++GpCodeSequenceNumber;
2229   }
2230
2231 }
2232
2233 /*-----------------------------------------------------------------*/
2234 /*-----------------------------------------------------------------*/
2235 set *register_usage(pBlock *pb)
2236 {
2237   pCode *pc,*pcn;
2238   set *registers=NULL;
2239   set *registersInCallPath = NULL;
2240
2241   /* check recursion */
2242
2243   pc = setFirstItem(pb->function_entries);
2244
2245   if(!pc)
2246     return registers;
2247
2248   pb->visited = 1;
2249
2250   if(pc->type != PC_FUNCTION)
2251     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2252
2253   pc = setFirstItem(pb->function_calls);
2254   for( ; pc; pc = setNextItem(pb->function_calls)) {
2255
2256     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2257       char *dest = get_op(PCI(pc));
2258
2259       pcn = findFunction(dest);
2260       if(pcn) 
2261         registersInCallPath = register_usage(pcn->pb);
2262     } else
2263       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2264
2265   }
2266
2267
2268   pBlockStats(stderr,pb);  // debug
2269   if(registersInCallPath) {
2270     /* registers were used in the functions this pBlock has called */
2271     /* so now, we need to see if these collide with the ones we are */
2272     /* using here */
2273
2274     regs *r1,*r2, *newreg;
2275
2276     fprintf(stderr,"comparing registers\n");
2277
2278     r1 = setFirstItem(registersInCallPath);
2279     while(r1) {
2280
2281       r2 = setFirstItem(pb->registers);
2282
2283       while(r2) {
2284
2285         if(r2->rIdx == r1->rIdx) {
2286           newreg = pic14_findFreeReg();
2287
2288
2289           if(!newreg) {
2290             fprintf(stderr,"Bummer, no more registers.\n");
2291             exit(1);
2292           }
2293
2294           fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2295                   r1->rIdx, newreg->rIdx);
2296           r2->rIdx = newreg->rIdx;
2297           //if(r2->name) free(r2->name);
2298           r2->name = Safe_strdup(newreg->name);
2299           newreg->isFree = 0;
2300           newreg->wasUsed = 1;
2301         }
2302         r2 = setNextItem(pb->registers);
2303       }
2304
2305       r1 = setNextItem(registersInCallPath);
2306     }
2307
2308     /* Collisions have been resolved. Now free the registers in the call path */
2309     r1 = setFirstItem(registersInCallPath);
2310     while(r1) {
2311       newreg = pic14_regWithIdx(r1->rIdx);
2312       newreg->isFree = 1;
2313       r1 = setNextItem(registersInCallPath);
2314     }
2315
2316   } else
2317     MarkUsedRegisters(pb->registers);
2318
2319   registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2320
2321   if(registers) 
2322     fprintf(stderr,"returning regs\n");
2323   else
2324     fprintf(stderr,"not returning regs\n");
2325
2326   fprintf(stderr,"pBlock after register optim.\n");
2327   pBlockStats(stderr,pb);  // debug
2328
2329
2330   return registers;
2331 }
2332
2333 /*-----------------------------------------------------------------*/
2334 /* printCallTree - writes the call tree to a file                  */
2335 /*                                                                 */
2336 /*-----------------------------------------------------------------*/
2337 void pct2(FILE *of,pBlock *pb,int indent)
2338 {
2339   pCode *pc,*pcn;
2340   int i;
2341   //  set *registersInCallPath = NULL;
2342
2343   if(!of)
2344     return;// registers;
2345
2346   if(indent > 10)
2347     return; // registers;   //recursion ?
2348
2349   pc = setFirstItem(pb->function_entries);
2350
2351   if(!pc)
2352     return;
2353
2354   pb->visited = 0;
2355
2356   for(i=0;i<indent;i++)   // Indentation
2357     fputc(' ',of);
2358
2359   if(pc->type == PC_FUNCTION)
2360     fprintf(of,"%s\n",PCF(pc)->fname);
2361   else
2362     return;  // ???
2363
2364
2365   pc = setFirstItem(pb->function_calls);
2366   for( ; pc; pc = setNextItem(pb->function_calls)) {
2367
2368     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2369       char *dest = get_op(PCI(pc));
2370
2371       pcn = findFunction(dest);
2372       if(pcn) 
2373         pct2(of,pcn->pb,indent+1);
2374     } else
2375       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2376
2377   }
2378
2379
2380 }
2381
2382 #if 0
2383   fprintf(stderr,"pBlock before register optim.\n");
2384   pBlockStats(stderr,pb);  // debug
2385
2386   if(registersInCallPath) {
2387     /* registers were used in the functions this pBlock has called */
2388     /* so now, we need to see if these collide with the ones we are using here */
2389
2390     regs *r1,*r2, *newreg;
2391
2392     fprintf(stderr,"comparing registers\n");
2393
2394     r1 = setFirstItem(registersInCallPath);
2395     while(r1) {
2396
2397       r2 = setFirstItem(pb->registers);
2398
2399       while(r2) {
2400
2401         if(r2->rIdx == r1->rIdx) {
2402           newreg = pic14_findFreeReg();
2403
2404
2405           if(!newreg) {
2406             fprintf(stderr,"Bummer, no more registers.\n");
2407             exit(1);
2408           }
2409
2410           fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2411                   r1->rIdx, newreg->rIdx);
2412           r2->rIdx = newreg->rIdx;
2413           //if(r2->name) free(r2->name);
2414           r2->name = Safe_strdup(newreg->name);
2415           newreg->isFree = 0;
2416           newreg->wasUsed = 1;
2417         }
2418         r2 = setNextItem(pb->registers);
2419       }
2420
2421       r1 = setNextItem(registersInCallPath);
2422     }
2423
2424     /* Collisions have been resolved. Now free the registers in the call path */
2425     r1 = setFirstItem(registersInCallPath);
2426     while(r1) {
2427       newreg = pic14_regWithIdx(r1->rIdx);
2428       newreg->isFree = 1;
2429       r1 = setNextItem(registersInCallPath);
2430     }
2431
2432   } else
2433     MarkUsedRegisters(pb->registers);
2434
2435   registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2436
2437   if(registers) 
2438     fprintf(stderr,"returning regs\n");
2439   else
2440     fprintf(stderr,"not returning regs\n");
2441
2442   fprintf(stderr,"pBlock after register optim.\n");
2443   pBlockStats(stderr,pb);  // debug
2444
2445
2446   return registers;
2447
2448 #endif
2449
2450
2451 /*-----------------------------------------------------------------*/
2452 /* printCallTree - writes the call tree to a file                  */
2453 /*                                                                 */
2454 /*-----------------------------------------------------------------*/
2455
2456 void printCallTree(FILE *of)
2457 {
2458   pBranch *pbr;
2459   pBlock  *pb;
2460   pCode   *pc;
2461
2462   if(!the_pFile)
2463     return;
2464
2465   if(!of)
2466     of = stderr;
2467
2468   fprintf(of, "\npBlock statistics\n");
2469   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
2470     pBlockStats(stderr,pb);
2471
2472
2473
2474   fprintf(of,"Call Tree\n");
2475   pbr = the_pFile->functions;
2476   while(pbr) {
2477     if(pbr->pc) {
2478       pc = pbr->pc;
2479       if(!ispCodeFunction(pc))
2480         fprintf(of,"bug in call tree");
2481
2482
2483       fprintf(of,"Function: %s\n", PCF(pc)->fname);
2484
2485       while(pc->next && !ispCodeFunction(pc->next)) {
2486         pc = pc->next;
2487         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2488           fprintf(of,"\t%s\n",get_op(PCI(pc)));
2489       }
2490     }
2491
2492     pbr = pbr->next;
2493   }
2494
2495
2496   /* Re-allocate the registers so that there are no collisions
2497    * between local variables when one function call another */
2498
2499   pic14_deallocateAllRegs();
2500
2501   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2502     if(!pb->visited)
2503       register_usage(pb);
2504   }
2505
2506   fprintf(of,"\n**************\n\na better call tree\n");
2507   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2508     if(pb->visited)
2509       pct2(of,pb,0);
2510   }
2511
2512   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2513     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
2514   }
2515 }