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