vsnprintf is not standard
[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 #if 0
709   // Alas, vsnprintf is not ANSI standard, and does not exist
710   // on Solaris (and probably other non-Gnu flavored Unixes).
711   vsnprintf(*str, *size, format, val);
712 #else
713   // This, of course, is *not* safe, despite the name.
714   vsprintf(*str, format, val);
715 #endif
716     
717   va_end (val);
718
719   len = strlen(*str);
720   *str += len;
721   *size -= len;
722
723 }
724
725 void  pCodeInitRegisters(void)
726 {
727
728   pc_fsr.rIdx = 4;
729   pc_fsr.r = pic14_regWithIdx(4);
730
731 }
732
733 /*-----------------------------------------------------------------*/
734 /*  mnem2key - convert a pic mnemonic into a hash key              */
735 /*   (BTW - this spreads the mnemonics quite well)                 */
736 /*                                                                 */
737 /*-----------------------------------------------------------------*/
738
739 int mnem2key(char const *mnem)
740 {
741   int key = 0;
742
743   if(!mnem)
744     return 0;
745
746   while(*mnem) {
747
748     key += toupper(*mnem++) +1;
749
750   }
751
752   return (key & 0x1f);
753
754 }
755
756 void pic14initMnemonics(void)
757 {
758   int i = 0;
759   int key;
760   //  char *str;
761   pCodeInstruction *pci;
762
763   if(mnemonics_initialized)
764     return;
765
766   pic14Mnemonics[POC_ADDLW] = &pciADDLW;
767   pic14Mnemonics[POC_ADDWF] = &pciADDWF;
768   pic14Mnemonics[POC_ADDFW] = &pciADDFW;
769   pic14Mnemonics[POC_ANDLW] = &pciANDLW;
770   pic14Mnemonics[POC_ANDWF] = &pciANDWF;
771   pic14Mnemonics[POC_ANDFW] = &pciANDFW;
772   pic14Mnemonics[POC_BCF] = &pciBCF;
773   pic14Mnemonics[POC_BSF] = &pciBSF;
774   pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
775   pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
776   pic14Mnemonics[POC_CALL] = &pciCALL;
777   pic14Mnemonics[POC_COMF] = &pciCOMF;
778   pic14Mnemonics[POC_CLRF] = &pciCLRF;
779   pic14Mnemonics[POC_CLRW] = &pciCLRW;
780   pic14Mnemonics[POC_DECF] = &pciDECF;
781   pic14Mnemonics[POC_DECFW] = &pciDECFW;
782   pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
783   pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
784   pic14Mnemonics[POC_GOTO] = &pciGOTO;
785   pic14Mnemonics[POC_INCF] = &pciINCF;
786   pic14Mnemonics[POC_INCFW] = &pciINCFW;
787   pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
788   pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
789   pic14Mnemonics[POC_IORLW] = &pciIORLW;
790   pic14Mnemonics[POC_IORWF] = &pciIORWF;
791   pic14Mnemonics[POC_IORFW] = &pciIORFW;
792   pic14Mnemonics[POC_MOVF] = &pciMOVF;
793   pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
794   pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
795   pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
796   pic14Mnemonics[POC_NEGF] = &pciNEGF;
797   pic14Mnemonics[POC_RETLW] = &pciRETLW;
798   pic14Mnemonics[POC_RETURN] = &pciRETURN;
799   pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
800   pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
801   pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
802   pic14Mnemonics[POC_TRIS] = &pciTRIS;
803   pic14Mnemonics[POC_XORLW] = &pciXORLW;
804   pic14Mnemonics[POC_XORWF] = &pciXORWF;
805   pic14Mnemonics[POC_XORFW] = &pciXORFW;
806
807   for(i=0; i<MAX_PIC14MNEMONICS; i++)
808     if(pic14Mnemonics[i])
809       hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
810   pci = hTabFirstItem(pic14MnemonicsHash, &key);
811
812   while(pci) {
813     fprintf( stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic);
814     pci = hTabNextItem(pic14MnemonicsHash, &key);
815   }
816
817   mnemonics_initialized = 1;
818 }
819
820 int getpCode(char *mnem,unsigned dest)
821 {
822
823   pCodeInstruction *pci;
824   int key = mnem2key(mnem);
825
826   if(!mnemonics_initialized)
827     pic14initMnemonics();
828
829   pci = hTabFirstItemWK(pic14MnemonicsHash, key);
830
831   while(pci) {
832
833     if(STRCASECMP(pci->mnemonic, mnem) == 0) {
834       if((pci->num_ops <= 1) || (pci->dest == dest))
835         return(pci->op);
836     }
837
838     pci = hTabNextItemWK (pic14MnemonicsHash);
839   
840   }
841
842   return -1;
843 }
844
845 char getpBlock_dbName(pBlock *pb)
846 {
847   if(!pb)
848     return 0;
849
850   if(pb->cmemmap)
851     return pb->cmemmap->dbName;
852
853   return pb->dbName;
854 }
855 /*-----------------------------------------------------------------*/
856 /* movepBlock2Head - given the dbname of a pBlock, move all        */
857 /*                   instances to the front of the doubly linked   */
858 /*                   list of pBlocks                               */
859 /*-----------------------------------------------------------------*/
860
861 void movepBlock2Head(char dbName)
862 {
863   pBlock *pb;
864
865   pb = the_pFile->pbHead;
866
867   while(pb) {
868
869     if(getpBlock_dbName(pb) == dbName) {
870       pBlock *pbn = pb->next;
871       pb->next = the_pFile->pbHead;
872       the_pFile->pbHead->prev = pb;
873       the_pFile->pbHead = pb;
874
875       if(pb->prev)
876         pb->prev->next = pbn;
877
878       // If the pBlock that we just moved was the last
879       // one in the link of all of the pBlocks, then we
880       // need to point the tail to the block just before
881       // the one we moved.
882       // Note: if pb->next is NULL, then pb must have 
883       // been the last pBlock in the chain.
884
885       if(pbn)
886         pbn->prev = pb->prev;
887       else
888         the_pFile->pbTail = pb->prev;
889
890       pb = pbn;
891
892     } else
893       pb = pb->next;
894
895   }
896
897 }
898
899 void copypCode(FILE *of, char dbName)
900 {
901   pBlock *pb;
902
903   if(!of || !the_pFile)
904     return;
905
906   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
907     if(getpBlock_dbName(pb) == dbName)
908       printpBlock(of,pb);
909   }
910
911 }
912 void pcode_test(void)
913 {
914
915   printf("pcode is alive!\n");
916
917   //initMnemonics();
918
919   if(the_pFile) {
920
921     pBlock *pb;
922     FILE *pFile;
923     char buffer[100];
924
925     /* create the file name */
926     strcpy(buffer,srcFileName);
927     strcat(buffer,".p");
928
929     if( !(pFile = fopen(buffer, "w" ))) {
930       werror(E_FILE_OPEN_ERR,buffer);
931       exit(1);
932     }
933
934     fprintf(pFile,"pcode dump\n\n");
935
936     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
937       fprintf(pFile,"\n\tNew pBlock\n\n");
938       if(pb->cmemmap)
939         fprintf(pFile,"%s",pb->cmemmap->sname);
940       else
941         fprintf(pFile,"internal pblock");
942
943       fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
944       printpBlock(pFile,pb);
945     }
946   }
947 }
948 static int RegCond(pCodeOp *pcop)
949 {
950
951   if(!pcop)
952     return 0;
953
954   if(pcop->type == PO_BIT  && !strcmp(pcop->name, pc_status.pcop.name)) {
955     switch(PCOB(pcop)->bit) {
956     case PIC_C_BIT:
957       return PCC_C;
958     case PIC_DC_BIT:
959         return PCC_DC;
960     case PIC_Z_BIT:
961       return PCC_Z;
962     }
963
964   }
965
966   return 0;
967 }
968
969 /*-----------------------------------------------------------------*/
970 /* newpCode - create and return a newly initialized pCode          */
971 /*                                                                 */
972 /*  fixme - rename this                                            */
973 /*                                                                 */
974 /* The purpose of this routine is to create a new Instruction      */
975 /* pCode. This is called by gen.c while the assembly code is being */
976 /* generated.                                                      */
977 /*                                                                 */
978 /* Inouts:                                                         */
979 /*  PIC_OPCODE op - the assembly instruction we wish to create.    */
980 /*                  (note that the op is analogous to but not the  */
981 /*                  same thing as the opcode of the instruction.)  */
982 /*  pCdoeOp *pcop - pointer to the operand of the instruction.     */
983 /*                                                                 */
984 /* Outputs:                                                        */
985 /*  a pointer to the new malloc'd pCode is returned.               */
986 /*                                                                 */
987 /*                                                                 */
988 /*                                                                 */
989 /*-----------------------------------------------------------------*/
990 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
991 {
992   pCodeInstruction *pci ;
993
994   if(!mnemonics_initialized)
995     pic14initMnemonics();
996     
997   pci = Safe_calloc(1, sizeof(pCodeInstruction));
998
999   if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1000     memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1001     pci->pcop = pcop;
1002
1003     if(pci->inCond == PCC_EXAMINE_PCOP)
1004       pci->inCond   = RegCond(pcop);
1005
1006     if(pci->outCond == PCC_EXAMINE_PCOP)
1007       pci->outCond   = RegCond(pcop);
1008
1009     return (pCode *)pci;
1010   }
1011
1012   fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1013   exit(1);
1014
1015   return NULL;
1016 }       
1017
1018 /*-----------------------------------------------------------------*/
1019 /* newpCodeWild - create a "wild" as in wild card pCode            */
1020 /*                                                                 */
1021 /* Wild pcodes are used during the peep hole optimizer to serve    */
1022 /* as place holders for any instruction. When a snippet of code is */
1023 /* compared to a peep hole rule, the wild card opcode will match   */
1024 /* any instruction. However, the optional operand and label are    */
1025 /* additional qualifiers that must also be matched before the      */
1026 /* line (of assembly code) is declared matched. Note that the      */
1027 /* operand may be wild too.                                        */
1028 /*                                                                 */
1029 /*   Note, a wild instruction is specified just like a wild var:   */
1030 /*      %4     ; A wild instruction,                               */
1031 /*  See the peeph.def file for additional examples                 */
1032 /*                                                                 */
1033 /*-----------------------------------------------------------------*/
1034
1035 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1036 {
1037
1038   pCodeWild *pcw;
1039     
1040   pcw = Safe_calloc(1,sizeof(pCodeWild));
1041
1042   pcw->pc.type = PC_WILD;
1043   pcw->pc.prev = pcw->pc.next = NULL;
1044   pcw->pc.from = pcw->pc.to = pcw->pc.label = NULL;
1045   pcw->pc.pb = NULL;
1046
1047   pcw->pc.analyze = genericAnalyze;
1048   pcw->pc.destruct = genericDestruct;
1049   pcw->pc.print = genericPrint;
1050
1051   pcw->id = pCodeID;              // this is the 'n' in %n
1052   pcw->operand = optional_operand;
1053   pcw->label   = optional_label;
1054
1055   return ( (pCode *)pcw);
1056   
1057 }
1058
1059 /*-----------------------------------------------------------------*/
1060 /* newPcodeCharP - create a new pCode from a char string           */
1061 /*-----------------------------------------------------------------*/
1062
1063 pCode *newpCodeCharP(char *cP)
1064 {
1065
1066   pCodeComment *pcc ;
1067     
1068   pcc = Safe_calloc(1,sizeof(pCodeComment));
1069
1070   pcc->pc.type = PC_COMMENT;
1071   pcc->pc.prev = pcc->pc.next = NULL;
1072   pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1073   pcc->pc.pb = NULL;
1074
1075   pcc->pc.analyze = genericAnalyze;
1076   pcc->pc.destruct = genericDestruct;
1077   pcc->pc.print = genericPrint;
1078
1079   pcc->comment = Safe_strdup(cP);
1080
1081   return ( (pCode *)pcc);
1082
1083 }
1084
1085 /*-----------------------------------------------------------------*/
1086 /* newpCodeGLabel - create a new global label                      */
1087 /*-----------------------------------------------------------------*/
1088
1089
1090 pCode *newpCodeFunction(char *mod,char *f)
1091 {
1092   pCodeFunction *pcf;
1093
1094   _ALLOC(pcf,sizeof(pCodeFunction));
1095
1096   pcf->pc.type = PC_FUNCTION;
1097   pcf->pc.prev = pcf->pc.next = NULL;
1098   pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1099   pcf->pc.pb = NULL;
1100
1101   pcf->pc.analyze = genericAnalyze;
1102   pcf->pc.destruct = genericDestruct;
1103   pcf->pc.print = pCodePrintFunction;
1104
1105   if(mod) {
1106     _ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1107     strcpy(pcf->modname,mod);
1108   } else
1109     pcf->modname = NULL;
1110
1111   if(f) {
1112     _ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1113     strcpy(pcf->fname,f);
1114   } else
1115     pcf->fname = NULL;
1116
1117   return ( (pCode *)pcf);
1118
1119 }
1120
1121 static void pCodeLabelDestruct(pCode *pc)
1122 {
1123
1124   if(!pc)
1125     return;
1126
1127   unlinkPC(pc);
1128
1129   if(PCL(pc)->label)
1130     free(PCL(pc)->label);
1131
1132   free(pc);
1133
1134 }
1135
1136 pCode *newpCodeLabel(int key)
1137 {
1138
1139   char *s = buffer;
1140   pCodeLabel *pcl;
1141     
1142   pcl = Safe_calloc(1,sizeof(pCodeLabel) );
1143
1144   pcl->pc.type = PC_LABEL;
1145   pcl->pc.prev = pcl->pc.next = NULL;
1146   pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
1147   pcl->pc.pb = NULL;
1148
1149   pcl->pc.analyze = genericAnalyze;
1150   pcl->pc.destruct = pCodeLabelDestruct;
1151   pcl->pc.print = pCodePrintLabel;
1152
1153   pcl->key = key;
1154
1155   if(key>0) {
1156     sprintf(s,"_%05d_DS_",key);
1157     pcl->label = Safe_strdup(s);
1158   } else
1159     pcl->label = NULL;
1160
1161   return ( (pCode *)pcl);
1162
1163 }
1164 pCode *newpCodeLabelStr(char *str)
1165 {
1166   pCode *pc = newpCodeLabel(-1);
1167
1168   PCL(pc)->label = Safe_strdup(str);
1169
1170   return pc;
1171 }
1172
1173 /*-----------------------------------------------------------------*/
1174 /* newpBlock - create and return a pointer to a new pBlock         */
1175 /*-----------------------------------------------------------------*/
1176 pBlock *newpBlock(void)
1177 {
1178
1179   pBlock *PpB;
1180
1181   PpB = Safe_calloc(1,sizeof(pBlock) );
1182   PpB->next = PpB->prev = NULL;
1183
1184   PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
1185   PpB->registers = NULL;
1186   PpB->visited = 0;
1187
1188   return PpB;
1189
1190 }
1191
1192 /*-----------------------------------------------------------------*/
1193 /* newpCodeChai0n - create a new chain of pCodes                    */
1194 /*-----------------------------------------------------------------*
1195  *
1196  *  This function will create a new pBlock and the pointer to the
1197  *  pCode that is passed in will be the first pCode in the block.
1198  *-----------------------------------------------------------------*/
1199
1200
1201 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
1202 {
1203
1204   pBlock *pB  = newpBlock();
1205
1206   pB->pcHead  = pB->pcTail = pc;
1207   pB->cmemmap = cm;
1208   pB->dbName  = c;
1209
1210   return pB;
1211 }
1212
1213 /*-----------------------------------------------------------------*/
1214 /* newpCodeOpLabel - Create a new label given the key              */
1215 /*  Note, a negative key means that the label is part of wild card */
1216 /*  (and hence a wild card label) used in the pCodePeep            */
1217 /*   optimizations).                                               */
1218 /*-----------------------------------------------------------------*/
1219
1220 pCodeOp *newpCodeOpLabel(int key)
1221 {
1222   char *s = buffer;
1223   pCodeOp *pcop;
1224
1225   pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
1226   pcop->type = PO_LABEL;
1227
1228   if(key>0) {
1229     sprintf(s,"_%05d_DS_",key);
1230     pcop->name = Safe_strdup(s);
1231   } else
1232     pcop->name = NULL;
1233
1234   ((pCodeOpLabel *)pcop)->key = key;
1235
1236   return pcop;
1237 }
1238
1239 pCodeOp *newpCodeOpLit(int lit)
1240 {
1241   char *s = buffer;
1242   pCodeOp *pcop;
1243
1244
1245   pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
1246   pcop->type = PO_LITERAL;
1247   if(lit>=0) {
1248     sprintf(s,"0x%02x",lit);
1249     pcop->name = Safe_strdup(s);
1250   } else
1251     pcop->name = NULL;
1252
1253   ((pCodeOpLit *)pcop)->lit = lit;
1254
1255   return pcop;
1256 }
1257
1258 pCodeOp *newpCodeOpWild(int id, pCodePeep *pcp, pCodeOp *subtype)
1259 {
1260   char *s = buffer;
1261   pCodeOp *pcop;
1262
1263
1264   if(!pcp || !subtype) {
1265     fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
1266     exit(1);
1267   }
1268
1269   pcop = Safe_calloc(1,sizeof(pCodeOpWild));
1270   pcop->type = PO_WILD;
1271   sprintf(s,"%%%d",id);
1272   pcop->name = Safe_strdup(s);
1273
1274   PCOW(pcop)->id = id;
1275   PCOW(pcop)->pcp = pcp;
1276   PCOW(pcop)->subtype = subtype;
1277   PCOW(pcop)->matched = NULL;
1278
1279   return pcop;
1280 }
1281
1282 pCodeOp *newpCodeOpBit(char *s, int bit)
1283 {
1284   pCodeOp *pcop;
1285
1286   pcop = Safe_calloc(1,sizeof(pCodeOpBit) );
1287   pcop->type = PO_BIT;
1288   pcop->name = Safe_strdup(s);   
1289
1290   PCOB(pcop)->bit = bit;
1291   if(bit>=0)
1292     PCOB(pcop)->inBitSpace = 1;
1293   else
1294     PCOB(pcop)->inBitSpace = 0;
1295
1296   return pcop;
1297 }
1298
1299 /*-----------------------------------------------------------------*/
1300 /*-----------------------------------------------------------------*/
1301
1302 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
1303 {
1304   pCodeOp *pcop;
1305
1306   switch(type) {
1307   case PO_BIT:
1308     pcop = newpCodeOpBit(name, -1);
1309     break;
1310
1311   case PO_LITERAL:
1312     pcop = newpCodeOpLit(-1);
1313     break;
1314
1315   case PO_LABEL:
1316     pcop = newpCodeOpLabel(-1);
1317     break;
1318
1319   default:
1320     pcop = Safe_calloc(1,sizeof(pCodeOp) );
1321     pcop->type = type;
1322     pcop->name = Safe_strdup(name);   
1323   }
1324
1325   return pcop;
1326 }
1327
1328 /*-----------------------------------------------------------------*/
1329 /* addpCode2pBlock - place the pCode into the pBlock linked list   */
1330 /*-----------------------------------------------------------------*/
1331 void addpCode2pBlock(pBlock *pb, pCode *pc)
1332 {
1333   if(!pb->pcHead) {
1334     /* If this is the first pcode to be added to a block that
1335      * was initialized with a NULL pcode, then go ahead and
1336      * make this pcode the head and tail */
1337     pb->pcHead  = pb->pcTail = pc;
1338   } else {
1339     pb->pcTail->next = pc;
1340     pc->prev = pb->pcTail;
1341     pc->next = NULL;
1342     pc->pb = pb;
1343     pb->pcTail = pc;
1344   }
1345 }
1346
1347 /*-----------------------------------------------------------------*/
1348 /* addpBlock - place a pBlock into the pFile                       */
1349 /*-----------------------------------------------------------------*/
1350 void addpBlock(pBlock *pb)
1351 {
1352
1353   if(!the_pFile) {
1354     /* First time called, we'll pass through here. */
1355     _ALLOC(the_pFile,sizeof(the_pFile));
1356     the_pFile->pbHead = the_pFile->pbTail = pb;
1357     the_pFile->functions = NULL;
1358     return;
1359   }
1360
1361   the_pFile->pbTail->next = pb;
1362   pb->prev = the_pFile->pbTail;
1363   pb->next = NULL;
1364   the_pFile->pbTail = pb;
1365 }
1366
1367 /*-----------------------------------------------------------------*/
1368 /* printpCode - write the contents of a pCode to a file            */
1369 /*-----------------------------------------------------------------*/
1370 void printpCode(FILE *of, pCode *pc)
1371 {
1372
1373   if(!pc || !of)
1374     return;
1375
1376   if(pc->print) {
1377     pc->print(of,pc);
1378     return;
1379   }
1380
1381   fprintf(of,"warning - unable to print pCode\n");
1382 }
1383
1384 /*-----------------------------------------------------------------*/
1385 /* printpBlock - write the contents of a pBlock to a file          */
1386 /*-----------------------------------------------------------------*/
1387 void printpBlock(FILE *of, pBlock *pb)
1388 {
1389   pCode *pc;
1390
1391   if(!pb)
1392     return;
1393
1394   if(!of)
1395     of = stderr;
1396
1397   for(pc = pb->pcHead; pc; pc = pc->next)
1398     printpCode(of,pc);
1399
1400 }
1401
1402 /*-----------------------------------------------------------------*/
1403 /*                                                                 */
1404 /*       pCode processing                                          */
1405 /*                                                                 */
1406 /*                                                                 */
1407 /*                                                                 */
1408 /*-----------------------------------------------------------------*/
1409
1410 static void unlinkPC(pCode *pc)
1411 {
1412   if(pc  && pc->prev && pc->next) {
1413
1414     pc->prev->next = pc->next;
1415     pc->next->prev = pc->prev;
1416   }
1417 }
1418 static void genericDestruct(pCode *pc)
1419 {
1420   fprintf(stderr,"warning, calling default pCode destructor\n");
1421
1422   unlinkPC(pc);
1423
1424   free(pc);
1425
1426 }
1427
1428
1429 void pBlockRegs(FILE *of, pBlock *pb)
1430 {
1431
1432   regs  *r;
1433
1434   r = setFirstItem(pb->registers);
1435   while (r) {
1436     r = setNextItem(pb->registers);
1437   }
1438 }
1439
1440
1441 static char *get_op( pCodeInstruction *pcc)
1442 {
1443   regs *r;
1444
1445   if(pcc && pcc->pcop) {
1446
1447
1448     switch(pcc->pcop->type) {
1449
1450     case PO_FSR:
1451     case PO_GPR_TEMP:
1452       r = pic14_regWithIdx(PCOR(pcc->pcop)->r->rIdx);
1453       //fprintf(stderr,"getop: getting %s\nfrom:\n",r->name); //pcc->pcop->name);
1454       pBlockRegs(stderr,pcc->pc.pb);
1455       return r->name;
1456
1457     default:
1458       if  (pcc->pcop->name)
1459         return pcc->pcop->name;
1460
1461     }
1462   }
1463
1464   return "NO operand";
1465 }
1466
1467 /*-----------------------------------------------------------------*/
1468 /*-----------------------------------------------------------------*/
1469 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
1470 {
1471
1472   fprintf(of,"pcodeopprint\n");
1473 }
1474
1475 char *pCode2str(char *str, int size, pCode *pc)
1476 {
1477   char *s = str;
1478
1479   switch(pc->type) {
1480
1481   case PC_OPCODE:
1482
1483     SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
1484
1485     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
1486
1487       if(PCI(pc)->bit_inst) {
1488         if(PCI(pc)->pcop->type == PO_BIT) {
1489           if( (((pCodeOpBit *)(PCI(pc)->pcop))->inBitSpace) )
1490             SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
1491                           PCI(pc)->pcop->name ,
1492                           PCI(pc)->pcop->name );
1493           else
1494             SAFE_snprintf(&s,&size,"%s,%d", get_op(PCI(pc)), 
1495                           (((pCodeOpBit *)(PCI(pc)->pcop))->bit ));
1496         } else
1497           SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op(PCI(pc)));
1498         //PCI(pc)->pcop->t.bit );
1499       } else {
1500
1501         if(PCI(pc)->pcop->type == PO_BIT) {
1502           if( PCI(pc)->num_ops == 2)
1503             SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op(PCI(pc)),((PCI(pc)->dest) ? 'F':'W'));
1504           else
1505             SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op(PCI(pc)));
1506
1507         }else {
1508           SAFE_snprintf(&s,&size,"%s",get_op(PCI(pc)));
1509
1510           if( PCI(pc)->num_ops == 2)
1511             SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->dest) ? 'F':'W'));
1512         }
1513       }
1514
1515     }
1516     break;
1517
1518   case PC_COMMENT:
1519     /* assuming that comment ends with a \n */
1520     SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
1521     break;
1522
1523   case PC_LABEL:
1524     SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
1525     break;
1526   case PC_FUNCTION:
1527     SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
1528     break;
1529   case PC_WILD:
1530     SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
1531     break;
1532
1533   }
1534
1535   return str;
1536
1537 }
1538
1539 /*-----------------------------------------------------------------*/
1540 /* genericPrint - the contents of a pCode to a file                */
1541 /*-----------------------------------------------------------------*/
1542 static void genericPrint(FILE *of, pCode *pc)
1543 {
1544
1545   if(!pc || !of)
1546     return;
1547
1548   switch(pc->type) {
1549   case PC_COMMENT:
1550     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
1551     break;
1552
1553   case PC_OPCODE:
1554     // If the opcode has a label, print that first
1555     {
1556       pBranch *pbl = pc->label;
1557       while(pbl) {
1558         if(pbl->pc->type == PC_LABEL)
1559           pCodePrintLabel(of, pbl->pc);
1560         pbl = pbl->next;
1561       }
1562     }
1563
1564
1565     {
1566       char str[256];
1567       
1568       pCode2str(str, 256, pc);
1569
1570       fprintf(of,"%s",str);
1571     }
1572
1573     {
1574       pBranch *dpb = pc->to;   // debug
1575       while(dpb) {
1576         switch ( dpb->pc->type) {
1577         case PC_OPCODE:
1578           fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
1579           break;
1580         case PC_LABEL:
1581           fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
1582           break;
1583         case PC_FUNCTION:
1584           fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
1585           break;
1586         case PC_COMMENT:
1587         case PC_WILD:
1588           break;
1589         }
1590         dpb = dpb->next;
1591       }
1592       fprintf(of,"\n");
1593     }
1594
1595     break;
1596
1597   case PC_WILD:
1598     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
1599     if(pc->label)
1600       pCodePrintLabel(of, pc->label->pc);
1601
1602     if(PCW(pc)->operand) {
1603       fprintf(of,";\toperand  ");
1604       pCodeOpPrint(of,PCW(pc)->operand );
1605     }
1606     break;
1607
1608   case PC_LABEL:
1609   default:
1610     fprintf(of,"unknown pCode type %d\n",pc->type);
1611   }
1612
1613 }
1614
1615 /*-----------------------------------------------------------------*/
1616 /* pCodePrintFunction - prints function begin/end                  */
1617 /*-----------------------------------------------------------------*/
1618
1619 static void pCodePrintFunction(FILE *of, pCode *pc)
1620 {
1621
1622   if(!pc || !of)
1623     return;
1624
1625   if( ((pCodeFunction *)pc)->modname) 
1626     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
1627
1628   if(PCF(pc)->fname) {
1629     pBranch *exits = pc->to;
1630     int i=0;
1631     fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
1632     while(exits) {
1633       i++;
1634       exits = exits->next;
1635     }
1636     //if(i) i--;
1637     fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
1638     
1639   }else {
1640     if(pc->from && 
1641        pc->from->pc->type == PC_FUNCTION &&
1642        PCF(pc->from->pc)->fname) 
1643       fprintf(of,"; exit point of %s\n",PCF(pc->from->pc)->fname);
1644     else
1645       fprintf(of,"; exit point [can't find entry point]\n");
1646   }
1647 }
1648 /*-----------------------------------------------------------------*/
1649 /* pCodePrintLabel - prints label                                  */
1650 /*-----------------------------------------------------------------*/
1651
1652 static void pCodePrintLabel(FILE *of, pCode *pc)
1653 {
1654
1655   if(!pc || !of)
1656     return;
1657
1658   if(PCL(pc)->label) 
1659     fprintf(of,"%s\n",PCL(pc)->label);
1660   else if (PCL(pc)->key >=0) 
1661     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
1662   else
1663     fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
1664
1665 }
1666 /*-----------------------------------------------------------------*/
1667
1668 static pBranch * pBranchAppend(pBranch *h, pBranch *n)
1669 {
1670   pBranch *b;
1671
1672   if(!h)
1673     return n;
1674
1675   b = h;
1676   while(b->next)
1677     b = b->next;
1678
1679   b->next = n;
1680
1681   return h;
1682   
1683 }  
1684 /*-----------------------------------------------------------------*/
1685 /* pBranchLink - given two pcodes, this function will link them    */
1686 /*               together through their pBranches                  */
1687 /*-----------------------------------------------------------------*/
1688 static void pBranchLink(pCode *f, pCode *t)
1689 {
1690   pBranch *b;
1691
1692   // Declare a new branch object for the 'from' pCode.
1693
1694   _ALLOC(b,sizeof(pBranch));
1695   b->pc = t;                    // The link to the 'to' pCode.
1696   b->next = NULL;
1697
1698   f->to = pBranchAppend(f->to,b);
1699
1700   // Now do the same for the 'to' pCode.
1701
1702   _ALLOC(b,sizeof(pBranch));
1703   b->pc = f;
1704   b->next = NULL;
1705
1706   t->from = pBranchAppend(t->from,b);
1707   
1708 }
1709
1710 #if 0
1711 /*-----------------------------------------------------------------*/
1712 /* pBranchFind - find the pBranch in a pBranch chain that contains */
1713 /*               a pCode                                           */
1714 /*-----------------------------------------------------------------*/
1715 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
1716 {
1717   while(pb) {
1718
1719     if(pb->pc == pc)
1720       return pb;
1721
1722     pb = pb->next;
1723   }
1724
1725   return NULL;
1726 }
1727
1728 /*-----------------------------------------------------------------*/
1729 /* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
1730 /*-----------------------------------------------------------------*/
1731 static void pCodeUnlink(pCode *pc)
1732 {
1733   pBranch *pb1,*pb2;
1734   pCode *pc1;
1735
1736   if(!pc->prev || !pc->next) {
1737     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
1738     exit(1);
1739   }
1740
1741   /* first remove the pCode from the chain */
1742   pc->prev->next = pc->next;
1743   pc->next->prev = pc->prev;
1744
1745   /* Now for the hard part... */
1746
1747   /* Remove the branches */
1748
1749   pb1 = pc->from;
1750   while(pb1) {
1751     pc1 = pb1->pc;    /* Get the pCode that branches to the
1752                        * one we're unlinking */
1753
1754     /* search for the link back to this pCode (the one we're
1755      * unlinking) */
1756     if(pb2 = pBranchFind(pc1->to,pc)) {
1757       pb2->pc = pc->to->pc;  // make the replacement
1758
1759       /* if the pCode we're unlinking contains multiple 'to'
1760        * branches (e.g. this a skip instruction) then we need
1761        * to copy these extra branches to the chain. */
1762       if(pc->to->next)
1763         pBranchAppend(pb2, pc->to->next);
1764     }
1765     
1766     pb1 = pb1->next;
1767   }
1768
1769
1770 }
1771 #endif
1772 /*-----------------------------------------------------------------*/
1773 /*-----------------------------------------------------------------*/
1774 static void genericAnalyze(pCode *pc)
1775 {
1776   switch(pc->type) {
1777   case PC_WILD:
1778   case PC_COMMENT:
1779     return;
1780   case PC_LABEL:
1781   case PC_FUNCTION:
1782   case PC_OPCODE:
1783     {
1784       // Go through the pCodes that are in pCode chain and link
1785       // them together through the pBranches. Note, the pCodes
1786       // are linked together as a contiguous stream like the 
1787       // assembly source code lines. The linking here mimics this
1788       // except that comments are not linked in.
1789       // 
1790       pCode *npc = pc->next;
1791       while(npc) {
1792         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
1793           pBranchLink(pc,npc);
1794           return;
1795         } else
1796           npc = npc->next;
1797       }
1798     }
1799   }
1800 }
1801
1802 /*-----------------------------------------------------------------*/
1803 /* findLabel - Search the pCode for a particular label             */
1804 /*-----------------------------------------------------------------*/
1805 pCode * findLabel(pCodeOpLabel *pcop_label)
1806 {
1807   pBlock *pb;
1808   pCode  *pc;
1809   pBranch *pbr;
1810
1811   if(!the_pFile)
1812     return NULL;
1813
1814   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1815     for(pc = pb->pcHead; pc; pc = pc->next) {
1816       if(pc->type == PC_LABEL) {
1817         if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
1818           return pc;
1819       }
1820       if(pc->type == PC_OPCODE) {
1821         pbr = pc->label;
1822         while(pbr) {
1823           if(pbr->pc->type == PC_LABEL) {
1824             if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
1825               return pc;
1826           }
1827           pbr = pbr->next;
1828         }
1829       }
1830
1831     }
1832   }
1833
1834   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
1835   return NULL;
1836 }
1837
1838 /*-----------------------------------------------------------------*/
1839 /* findNextInstruction - given a pCode, find the next instruction  */
1840 /*                       in the linked list                        */
1841 /*-----------------------------------------------------------------*/
1842 pCode * findNextInstruction(pCode *pc)
1843 {
1844
1845   while(pc) {
1846     if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
1847       return pc;
1848
1849     pc = pc->next;
1850   }
1851
1852   fprintf(stderr,"Couldn't find instruction\n");
1853   return NULL;
1854 }
1855
1856 /*-----------------------------------------------------------------*/
1857 /* findFunctionEnd - given a pCode find the end of the function    */
1858 /*                   that contains it     t                        */
1859 /*-----------------------------------------------------------------*/
1860 pCode * findFunctionEnd(pCode *pc)
1861 {
1862
1863   while(pc) {
1864     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
1865       return pc;
1866
1867     pc = pc->next;
1868   }
1869
1870   fprintf(stderr,"Couldn't find function end\n");
1871   return NULL;
1872 }
1873
1874 #if 0
1875 /*-----------------------------------------------------------------*/
1876 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
1877 /*                instruction with which it is associated.         */
1878 /*-----------------------------------------------------------------*/
1879 static void AnalyzeLabel(pCode *pc)
1880 {
1881
1882   pCodeUnlink(pc);
1883
1884 }
1885 #endif
1886
1887 static void AnalyzeGOTO(pCode *pc)
1888 {
1889
1890   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
1891
1892 }
1893
1894 static void AnalyzeSKIP(pCode *pc)
1895 {
1896
1897   pBranchLink(pc,findNextInstruction(pc->next));
1898   pBranchLink(pc,findNextInstruction(pc->next->next));
1899
1900 }
1901
1902 static void AnalyzeRETURN(pCode *pc)
1903 {
1904
1905   //  branch_link(pc,findFunctionEnd(pc->next));
1906
1907 }
1908
1909
1910 void AnalyzepBlock(pBlock *pb)
1911 {
1912   pCode *pc;
1913
1914   if(!pb)
1915     return;
1916
1917   /* Find all of the registers used in this pBlock */
1918   for(pc = pb->pcHead; pc; pc = pc->next) {
1919     if(pc->type == PC_OPCODE) {
1920       if(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_TEMP) {
1921
1922         /* Loop through all of the registers declared so far in
1923            this block and see if we find this new there */
1924
1925         regs *r = setFirstItem(pb->registers);
1926
1927         while(r) {
1928           if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
1929             PCOR(PCI(pc)->pcop)->r = r;
1930             break;
1931           }
1932           r = setNextItem(pb->registers);
1933         }
1934
1935         if(!r) {
1936           /* register wasn't found */
1937           r = Safe_calloc(1, sizeof(regs));
1938           memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
1939           addSet(&pb->registers, r);
1940           PCOR(PCI(pc)->pcop)->r = r;
1941           fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
1942         } else 
1943           fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
1944       }
1945     }
1946   }
1947 }
1948
1949 int OptimizepBlock(pBlock *pb)
1950 {
1951   pCode *pc;
1952   int matches =0;
1953
1954   if(!pb || !peepOptimizing)
1955     return 0;
1956
1957   fprintf(stderr," Optimizing pBlock\n");
1958
1959   for(pc = pb->pcHead; pc; pc = pc->next)
1960     matches += pCodePeepMatchRule(pc);
1961
1962   return matches;
1963
1964 }
1965 /*-----------------------------------------------------------------*/
1966 /* pBlockMergeLabels - remove the pCode labels from the pCode      */
1967 /*                     chain and put them into pBranches that are  */
1968 /*                     associated with the appropriate pCode       */
1969 /*                     instructions.                               */
1970 /*-----------------------------------------------------------------*/
1971 void pBlockMergeLabels(pBlock *pb)
1972 {
1973   pBranch *pbr;
1974   pCode *pc, *pcnext=NULL;
1975
1976   if(!pb)
1977     return;
1978
1979   for(pc = pb->pcHead; pc; pc = pc->next) {
1980
1981     if(pc->type == PC_LABEL) {
1982       if( !(pcnext = findNextInstruction(pc)) ) 
1983         return;  // Couldn't find an instruction associated with this label
1984
1985       // Unlink the pCode label from it's pCode chain
1986       if(pc->prev) 
1987         pc->prev->next = pc->next;
1988       if(pc->next)
1989         pc->next->prev = pc->prev;
1990
1991       // And link it into the instruction's pBranch labels. (Note, since
1992       // it's possible to have multiple labels associated with one instruction
1993       // we must provide a means to accomodate the additional labels. Thus
1994       // the labels are placed into the singly-linked list "label" as 
1995       // opposed to being a single member of the pCodeInstruction.)
1996
1997       _ALLOC(pbr,sizeof(pBranch));
1998       pbr->pc = pc;
1999       pbr->next = NULL;
2000
2001       pcnext->label = pBranchAppend(pcnext->label,pbr);
2002     }
2003
2004   }
2005
2006 }
2007
2008 /*-----------------------------------------------------------------*/
2009 /*-----------------------------------------------------------------*/
2010 void OptimizepCode(char dbName)
2011 {
2012 #define MAX_PASSES 4
2013
2014   int matches = 0;
2015   int passes = 0;
2016   pBlock *pb;
2017
2018   if(!the_pFile)
2019     return;
2020
2021   fprintf(stderr," Optimizing pCode\n");
2022
2023   do {
2024     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2025       if('*' == dbName || getpBlock_dbName(pb) == dbName)
2026         matches += OptimizepBlock(pb);
2027     }
2028   }
2029   while(matches && ++passes < MAX_PASSES);
2030
2031 }
2032
2033 /*-----------------------------------------------------------------*/
2034 /* AnalyzepCode - parse the pCode that has been generated and form */
2035 /*                all of the logical connections.                  */
2036 /*                                                                 */
2037 /* Essentially what's done here is that the pCode flow is          */
2038 /* determined.                                                     */
2039 /*-----------------------------------------------------------------*/
2040
2041 void AnalyzepCode(char dbName)
2042 {
2043   pBlock *pb;
2044   pCode *pc;
2045   pBranch *pbr;
2046
2047   if(!the_pFile)
2048     return;
2049
2050   fprintf(stderr," Analyzing pCode");
2051
2052   /* First, merge the labels with the instructions */
2053   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2054     if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2055       pBlockMergeLabels(pb);
2056       AnalyzepBlock(pb);
2057     }
2058   }
2059
2060   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2061     if('*' == dbName || getpBlock_dbName(pb) == dbName)
2062       OptimizepBlock(pb);
2063   }
2064
2065   /* Now build the call tree.
2066      First we examine all of the pCodes for functions.
2067      Keep in mind that the function boundaries coincide
2068      with pBlock boundaries. 
2069
2070      The algorithm goes something like this:
2071      We have two nested loops. The outer loop iterates
2072      through all of the pBlocks/functions. The inner
2073      loop iterates through all of the pCodes for
2074      a given pBlock. When we begin iterating through
2075      a pBlock, the variable pc_fstart, pCode of the start
2076      of a function, is cleared. We then search for pCodes
2077      of type PC_FUNCTION. When one is encountered, we
2078      initialize pc_fstart to this and at the same time
2079      associate a new pBranch object that signifies a 
2080      branch entry. If a return is found, then this signifies
2081      a function exit point. We'll link the pCodes of these
2082      returns to the matching pc_fstart.
2083
2084      When we're done, a doubly linked list of pBranches
2085      will exist. The head of this list is stored in
2086      `the_pFile', which is the meta structure for all
2087      of the pCode. Look at the printCallTree function
2088      on how the pBranches are linked together.
2089
2090    */
2091   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2092     if('*' == dbName || getpBlock_dbName(pb) == dbName) {
2093       pCode *pc_fstart=NULL;
2094       for(pc = pb->pcHead; pc; pc = pc->next) {
2095         if(pc->type == PC_FUNCTION) {
2096           if (PCF(pc)->fname) {
2097             // I'm not liking this....
2098             // Found the beginning of a function.
2099             _ALLOC(pbr,sizeof(pBranch));
2100             pbr->pc = pc_fstart = pc;
2101             pbr->next = NULL;
2102
2103             the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
2104
2105             // Here's a better way of doing the same:
2106             addSet(&pb->function_entries, pc);
2107
2108           } else {
2109             // Found an exit point in a function, e.g. return
2110             // (Note, there may be more than one return per function)
2111             if(pc_fstart)
2112               pBranchLink(pc_fstart, pc);
2113
2114             addSet(&pb->function_exits, pc);
2115           }
2116         } else  if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2117           addSet(&pb->function_calls,pc);
2118         }
2119       }
2120     }
2121   }
2122 }
2123
2124 /*-----------------------------------------------------------------*/
2125 /* ispCodeFunction - returns true if *pc is the pCode of a         */
2126 /*                   function                                      */
2127 /*-----------------------------------------------------------------*/
2128 bool ispCodeFunction(pCode *pc)
2129 {
2130
2131   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
2132     return 1;
2133
2134   return 0;
2135 }
2136
2137 /*-----------------------------------------------------------------*/
2138 /* findFunction - Search for a function by name (given the name)   */
2139 /*                in the set of all functions that are in a pBlock */
2140 /* (note - I expect this to change because I'm planning to limit   */
2141 /*  pBlock's to just one function declaration                      */
2142 /*-----------------------------------------------------------------*/
2143 pCode *findFunction(char *fname)
2144 {
2145   pBlock *pb;
2146   pCode *pc;
2147   if(!fname)
2148     return NULL;
2149
2150   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2151
2152     pc = setFirstItem(pb->function_entries);
2153     while(pc) {
2154     
2155       if((pc->type == PC_FUNCTION) &&
2156          (PCF(pc)->fname) && 
2157          (strcmp(fname, PCF(pc)->fname)==0))
2158         return pc;
2159
2160       pc = setNextItem(pb->function_entries);
2161
2162     }
2163
2164   }
2165   return NULL;
2166 }
2167
2168 void MarkUsedRegisters(set *regset)
2169 {
2170
2171   regs *r1,*r2;
2172
2173   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
2174     r2 = pic14_regWithIdx(r1->rIdx);
2175     r2->isFree = 0;
2176     r2->wasUsed = 1;
2177   }
2178 }
2179
2180 void pBlockStats(FILE *of, pBlock *pb)
2181 {
2182
2183   pCode *pc;
2184   regs  *r;
2185
2186   fprintf(of,"***\n  pBlock Stats\n***\n");
2187
2188   // for now just print the first element of each set
2189   pc = setFirstItem(pb->function_entries);
2190   if(pc) {
2191     fprintf(of,"entry\n");
2192     pc->print(of,pc);
2193   }
2194   pc = setFirstItem(pb->function_exits);
2195   if(pc) {
2196     fprintf(of,"has an exit\n");
2197     pc->print(of,pc);
2198   }
2199
2200   pc = setFirstItem(pb->function_calls);
2201   if(pc) {
2202     fprintf(of,"functions called\n");
2203
2204     while(pc) {
2205       pc->print(of,pc);
2206       pc = setNextItem(pb->function_calls);
2207     }
2208   }
2209
2210   r = setFirstItem(pb->registers);
2211   if(r) {
2212     int n = elementsInSet(pb->registers);
2213
2214     fprintf(of,"%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
2215
2216     while (r) {
2217       fprintf(of,"   %s\n",r->name);
2218       r = setNextItem(pb->registers);
2219     }
2220   }
2221 }
2222
2223 /*-----------------------------------------------------------------*/
2224 /*-----------------------------------------------------------------*/
2225 void sequencepCode(void)
2226 {
2227   pBlock *pb;
2228   pCode *pc;
2229
2230
2231   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2232
2233     pb->seq = GpCodeSequenceNumber+1;
2234
2235     for( pc = pb->pcHead; pc; pc = pc->next)
2236       pc->seq = ++GpCodeSequenceNumber;
2237   }
2238
2239 }
2240
2241 /*-----------------------------------------------------------------*/
2242 /*-----------------------------------------------------------------*/
2243 set *register_usage(pBlock *pb)
2244 {
2245   pCode *pc,*pcn;
2246   set *registers=NULL;
2247   set *registersInCallPath = NULL;
2248
2249   /* check recursion */
2250
2251   pc = setFirstItem(pb->function_entries);
2252
2253   if(!pc)
2254     return registers;
2255
2256   pb->visited = 1;
2257
2258   if(pc->type != PC_FUNCTION)
2259     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
2260
2261   pc = setFirstItem(pb->function_calls);
2262   for( ; pc; pc = setNextItem(pb->function_calls)) {
2263
2264     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2265       char *dest = get_op(PCI(pc));
2266
2267       pcn = findFunction(dest);
2268       if(pcn) 
2269         registersInCallPath = register_usage(pcn->pb);
2270     } else
2271       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2272
2273   }
2274
2275
2276   pBlockStats(stderr,pb);  // debug
2277   if(registersInCallPath) {
2278     /* registers were used in the functions this pBlock has called */
2279     /* so now, we need to see if these collide with the ones we are */
2280     /* using here */
2281
2282     regs *r1,*r2, *newreg;
2283
2284     fprintf(stderr,"comparing registers\n");
2285
2286     r1 = setFirstItem(registersInCallPath);
2287     while(r1) {
2288
2289       r2 = setFirstItem(pb->registers);
2290
2291       while(r2) {
2292
2293         if(r2->rIdx == r1->rIdx) {
2294           newreg = pic14_findFreeReg();
2295
2296
2297           if(!newreg) {
2298             fprintf(stderr,"Bummer, no more registers.\n");
2299             exit(1);
2300           }
2301
2302           fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2303                   r1->rIdx, newreg->rIdx);
2304           r2->rIdx = newreg->rIdx;
2305           //if(r2->name) free(r2->name);
2306           r2->name = Safe_strdup(newreg->name);
2307           newreg->isFree = 0;
2308           newreg->wasUsed = 1;
2309         }
2310         r2 = setNextItem(pb->registers);
2311       }
2312
2313       r1 = setNextItem(registersInCallPath);
2314     }
2315
2316     /* Collisions have been resolved. Now free the registers in the call path */
2317     r1 = setFirstItem(registersInCallPath);
2318     while(r1) {
2319       newreg = pic14_regWithIdx(r1->rIdx);
2320       newreg->isFree = 1;
2321       r1 = setNextItem(registersInCallPath);
2322     }
2323
2324   } else
2325     MarkUsedRegisters(pb->registers);
2326
2327   registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2328
2329   if(registers) 
2330     fprintf(stderr,"returning regs\n");
2331   else
2332     fprintf(stderr,"not returning regs\n");
2333
2334   fprintf(stderr,"pBlock after register optim.\n");
2335   pBlockStats(stderr,pb);  // debug
2336
2337
2338   return registers;
2339 }
2340
2341 /*-----------------------------------------------------------------*/
2342 /* printCallTree - writes the call tree to a file                  */
2343 /*                                                                 */
2344 /*-----------------------------------------------------------------*/
2345 void pct2(FILE *of,pBlock *pb,int indent)
2346 {
2347   pCode *pc,*pcn;
2348   int i;
2349   //  set *registersInCallPath = NULL;
2350
2351   if(!of)
2352     return;// registers;
2353
2354   if(indent > 10)
2355     return; // registers;   //recursion ?
2356
2357   pc = setFirstItem(pb->function_entries);
2358
2359   if(!pc)
2360     return;
2361
2362   pb->visited = 0;
2363
2364   for(i=0;i<indent;i++)   // Indentation
2365     fputc(' ',of);
2366
2367   if(pc->type == PC_FUNCTION)
2368     fprintf(of,"%s\n",PCF(pc)->fname);
2369   else
2370     return;  // ???
2371
2372
2373   pc = setFirstItem(pb->function_calls);
2374   for( ; pc; pc = setNextItem(pb->function_calls)) {
2375
2376     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
2377       char *dest = get_op(PCI(pc));
2378
2379       pcn = findFunction(dest);
2380       if(pcn) 
2381         pct2(of,pcn->pb,indent+1);
2382     } else
2383       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
2384
2385   }
2386
2387
2388 }
2389
2390 #if 0
2391   fprintf(stderr,"pBlock before register optim.\n");
2392   pBlockStats(stderr,pb);  // debug
2393
2394   if(registersInCallPath) {
2395     /* registers were used in the functions this pBlock has called */
2396     /* so now, we need to see if these collide with the ones we are using here */
2397
2398     regs *r1,*r2, *newreg;
2399
2400     fprintf(stderr,"comparing registers\n");
2401
2402     r1 = setFirstItem(registersInCallPath);
2403     while(r1) {
2404
2405       r2 = setFirstItem(pb->registers);
2406
2407       while(r2) {
2408
2409         if(r2->rIdx == r1->rIdx) {
2410           newreg = pic14_findFreeReg();
2411
2412
2413           if(!newreg) {
2414             fprintf(stderr,"Bummer, no more registers.\n");
2415             exit(1);
2416           }
2417
2418           fprintf(stderr,"Cool found register collision nIdx=%d moving to %d\n",
2419                   r1->rIdx, newreg->rIdx);
2420           r2->rIdx = newreg->rIdx;
2421           //if(r2->name) free(r2->name);
2422           r2->name = Safe_strdup(newreg->name);
2423           newreg->isFree = 0;
2424           newreg->wasUsed = 1;
2425         }
2426         r2 = setNextItem(pb->registers);
2427       }
2428
2429       r1 = setNextItem(registersInCallPath);
2430     }
2431
2432     /* Collisions have been resolved. Now free the registers in the call path */
2433     r1 = setFirstItem(registersInCallPath);
2434     while(r1) {
2435       newreg = pic14_regWithIdx(r1->rIdx);
2436       newreg->isFree = 1;
2437       r1 = setNextItem(registersInCallPath);
2438     }
2439
2440   } else
2441     MarkUsedRegisters(pb->registers);
2442
2443   registers = unionSets(pb->registers, registersInCallPath, THROW_NONE);
2444
2445   if(registers) 
2446     fprintf(stderr,"returning regs\n");
2447   else
2448     fprintf(stderr,"not returning regs\n");
2449
2450   fprintf(stderr,"pBlock after register optim.\n");
2451   pBlockStats(stderr,pb);  // debug
2452
2453
2454   return registers;
2455
2456 #endif
2457
2458
2459 /*-----------------------------------------------------------------*/
2460 /* printCallTree - writes the call tree to a file                  */
2461 /*                                                                 */
2462 /*-----------------------------------------------------------------*/
2463
2464 void printCallTree(FILE *of)
2465 {
2466   pBranch *pbr;
2467   pBlock  *pb;
2468   pCode   *pc;
2469
2470   if(!the_pFile)
2471     return;
2472
2473   if(!of)
2474     of = stderr;
2475
2476   fprintf(of, "\npBlock statistics\n");
2477   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
2478     pBlockStats(stderr,pb);
2479
2480
2481
2482   fprintf(of,"Call Tree\n");
2483   pbr = the_pFile->functions;
2484   while(pbr) {
2485     if(pbr->pc) {
2486       pc = pbr->pc;
2487       if(!ispCodeFunction(pc))
2488         fprintf(of,"bug in call tree");
2489
2490
2491       fprintf(of,"Function: %s\n", PCF(pc)->fname);
2492
2493       while(pc->next && !ispCodeFunction(pc->next)) {
2494         pc = pc->next;
2495         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
2496           fprintf(of,"\t%s\n",get_op(PCI(pc)));
2497       }
2498     }
2499
2500     pbr = pbr->next;
2501   }
2502
2503
2504   /* Re-allocate the registers so that there are no collisions
2505    * between local variables when one function call another */
2506
2507   pic14_deallocateAllRegs();
2508
2509   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2510     if(!pb->visited)
2511       register_usage(pb);
2512   }
2513
2514   fprintf(of,"\n**************\n\na better call tree\n");
2515   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2516     if(pb->visited)
2517       pct2(of,pb,0);
2518   }
2519
2520   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
2521     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
2522   }
2523 }