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