Bit operands were not being handled properly in the pic14 port.
[fw/sdcc] / src / pic / pcode.c
1 /*-------------------------------------------------------------------------
2
3    pcode.c - post code generation
4    Written By -  Scott Dattalo scott@dattalo.com
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
20
21 #include <stdio.h>
22
23 #include "common.h"   // Include everything in the SDCC src directory
24 #include "newalloc.h"
25
26
27 #include "pcode.h"
28 #include "pcodeflow.h"
29 #include "ralloc.h"
30 #include "device.h"
31
32 pCode *findFunction(char *fname);
33
34 static void FixRegisterBanking(pBlock *pb,int cur_bank);
35
36 #if defined(__BORLANDC__) || defined(_MSC_VER)
37 #define STRCASECMP stricmp
38 #else
39 #define STRCASECMP strcasecmp
40 #endif
41
42 /****************************************************************/
43 /****************************************************************/
44
45 peepCommand peepCommands[] = {
46   
47   {NOTBITSKIP, "_NOTBITSKIP_"},
48   {BITSKIP, "_BITSKIP_"},
49   {INVERTBITSKIP, "_INVERTBITSKIP_"},
50   
51   {-1, NULL}
52 };
53
54
55
56 // Eventually this will go into device dependent files:
57 pCodeOpReg pc_status    = {{PO_STATUS,  "STATUS"}, -1, NULL,0,NULL};
58 pCodeOpReg pc_indf      = {{PO_INDF,    "INDF"}, -1, NULL,0,NULL};
59 pCodeOpReg pc_fsr       = {{PO_FSR,     "FSR"}, -1, NULL,0,NULL};
60 pCodeOpReg pc_intcon    = {{PO_INTCON,  ""}, -1, NULL,0,NULL};
61 pCodeOpReg pc_pcl       = {{PO_PCL,     "PCL"}, -1, NULL,0,NULL};
62 pCodeOpReg pc_pclath    = {{PO_PCLATH,  "PCLATH"}, -1, NULL,0,NULL};
63
64 pCodeOpReg pc_wsave     = {{PO_GPR_REGISTER,  "WSAVE"}, -1, NULL,0,NULL};
65 pCodeOpReg pc_ssave     = {{PO_GPR_REGISTER,  "SSAVE"}, -1, NULL,0,NULL};
66 pCodeOpReg pc_psave     = {{PO_GPR_REGISTER,  "PSAVE"}, -1, NULL,0,NULL};
67
68 static int mnemonics_initialized = 0;
69
70 static hTab *pic14MnemonicsHash = NULL;
71 static hTab *pic14pCodePeepCommandsHash = NULL;
72
73
74 static pFile *the_pFile = NULL;
75 static pBlock *pb_dead_pcodes = NULL;
76
77 /* Hardcoded flags to change the behavior of the PIC port */
78 static int peepOptimizing = 0;        /* run the peephole optimizer if nonzero */
79 static int functionInlining = 1;      /* inline functions if nonzero */
80 int debug_verbose = 1;                /* Set true to inundate .asm file */
81
82 // static int GpCodeSequenceNumber = 1;
83 int GpcFlowSeq = 1;
84
85 unsigned maxIdx; /* This keeps track of the maximum register index for call tree register reuse */
86 unsigned peakIdx; /* This keeps track of the peak register index for call tree register reuse */
87
88 extern void RemoveUnusedRegisters(void);
89 extern void RegsUnMapLiveRanges(void);
90 extern void BuildFlowTree(pBlock *pb);
91 extern void pCodeRegOptimizeRegUsage(int level);
92 extern int picIsInitialized(void);
93 extern const char *pCodeOpType(pCodeOp *pcop);
94
95 /****************************************************************/
96 /*                      Forward declarations                    */
97 /****************************************************************/
98
99 void unlinkpCode(pCode *pc);
100 #if 0
101 static void genericAnalyze(pCode *pc);
102 static void AnalyzeGOTO(pCode *pc);
103 static void AnalyzeSKIP(pCode *pc);
104 static void AnalyzeRETURN(pCode *pc);
105 #endif
106
107 static void genericDestruct(pCode *pc);
108 static void genericPrint(FILE *of,pCode *pc);
109
110 static void pCodePrintLabel(FILE *of, pCode *pc);
111 static void pCodePrintFunction(FILE *of, pCode *pc);
112 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
113 static char *get_op_from_instruction( pCodeInstruction *pcc);
114 char *get_op( pCodeOp *pcop,char *buff,size_t buf_size);
115 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
116 int pCodePeepMatchRule(pCode *pc);
117 void pBlockStats(FILE *of, pBlock *pb);
118 pBlock *newpBlock(void);
119 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval);
120 void pCodeRegMapLiveRanges(pBlock *pb);
121
122
123 /****************************************************************/
124 /*                    PIC Instructions                          */
125 /****************************************************************/
126
127 pCodeInstruction pciADDWF = {
128   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
129     //   genericAnalyze,
130     genericDestruct,
131     genericPrint},
132     POC_ADDWF,
133     "ADDWF",
134     NULL, // from branch
135     NULL, // to branch
136     NULL, // label
137     NULL, // operand
138     NULL, // flow block
139     NULL, // C source 
140     2,    // num ops
141     1,0,  // dest, bit instruction
142     0,0,  // branch, skip
143     0,    // literal operand
144     POC_NOP,
145     (PCC_W | PCC_REGISTER),   // inCond
146     (PCC_REGISTER | PCC_Z) // outCond
147 };
148
149 pCodeInstruction pciADDFW = {
150   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
151     //   genericAnalyze,
152     genericDestruct,
153     genericPrint},
154     POC_ADDFW,
155     "ADDWF",
156     NULL, // from branch
157     NULL, // to branch
158     NULL, // label
159     NULL, // operand
160     NULL, // flow block
161     NULL, // C source 
162     2,    // num ops
163     0,0,  // dest, bit instruction
164     0,0,  // branch, skip
165     0,    // literal operand
166     POC_NOP,
167     (PCC_W | PCC_REGISTER),   // inCond
168     (PCC_W | PCC_Z) // outCond
169 };
170
171 pCodeInstruction pciADDLW = {
172   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
173     //   genericAnalyze,
174     genericDestruct,
175     genericPrint},
176     POC_ADDLW,
177     "ADDLW",
178     NULL, // from branch
179     NULL, // to branch
180     NULL, // label
181     NULL, // operand
182     NULL, // flow block
183     NULL, // C source 
184     1,    // num ops
185     0,0,  // dest, bit instruction
186     0,0,  // branch, skip
187     1,    // literal operand
188     POC_NOP,
189     (PCC_W | PCC_LITERAL),   // inCond
190     (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
191 };
192
193 pCodeInstruction pciANDLW = {
194   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
195     //   genericAnalyze,
196     genericDestruct,
197     genericPrint},
198     POC_ANDLW,
199     "ANDLW",
200     NULL, // from branch
201     NULL, // to branch
202     NULL, // label
203     NULL, // operand
204     NULL, // flow block
205     NULL, // C source 
206     1,    // num ops
207     0,0,  // dest, bit instruction
208     0,0,  // branch, skip
209     1,    // literal operand
210     POC_NOP,
211     (PCC_W | PCC_LITERAL),   // inCond
212     (PCC_W | PCC_Z) // outCond
213 };
214
215 pCodeInstruction pciANDWF = {
216   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
217     //   genericAnalyze,
218     genericDestruct,
219     genericPrint},
220     POC_ANDWF,
221     "ANDWF",
222     NULL, // from branch
223     NULL, // to branch
224     NULL, // label
225     NULL, // operand
226     NULL, // flow block
227     NULL, // C source 
228     2,    // num ops
229     1,0,  // dest, bit instruction
230     0,0,  // branch, skip
231     0,    // literal operand
232     POC_NOP,
233     (PCC_W | PCC_REGISTER),   // inCond
234     (PCC_REGISTER | PCC_Z) // outCond
235 };
236
237 pCodeInstruction pciANDFW = {
238   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
239     //   genericAnalyze,
240     genericDestruct,
241     genericPrint},
242     POC_ANDFW,
243     "ANDWF",
244     NULL, // from branch
245     NULL, // to branch
246     NULL, // label
247     NULL, // operand
248     NULL, // flow block
249     NULL, // C source 
250     2,    // num ops
251     0,0,  // dest, bit instruction
252     0,0,  // branch, skip
253     0,    // literal operand
254     POC_NOP,
255     (PCC_W | PCC_REGISTER),   // inCond
256     (PCC_W | PCC_Z) // outCond
257 };
258
259 pCodeInstruction pciBCF = {
260   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
261     //   genericAnalyze,
262     genericDestruct,
263     genericPrint},
264     POC_BCF,
265     "BCF",
266     NULL, // from branch
267     NULL, // to branch
268     NULL, // label
269     NULL, // operand
270     NULL, // flow block
271     NULL, // C source 
272     2,    // num ops
273     1,1,  // dest, bit instruction
274     0,0,  // branch, skip
275     0,    // literal operand
276     POC_BSF,
277     (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
278     PCC_REGISTER // outCond
279 };
280
281 pCodeInstruction pciBSF = {
282   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
283     //   genericAnalyze,
284     genericDestruct,
285     genericPrint},
286     POC_BSF,
287     "BSF",
288     NULL, // from branch
289     NULL, // to branch
290     NULL, // label
291     NULL, // operand
292     NULL, // flow block
293     NULL, // C source 
294     2,    // num ops
295     1,1,  // dest, bit instruction
296     0,0,  // branch, skip
297     0,    // literal operand
298     POC_BCF,
299     (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
300     (PCC_REGISTER | PCC_EXAMINE_PCOP) // outCond
301 };
302
303 pCodeInstruction pciBTFSC = {
304   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
305     //   AnalyzeSKIP,
306     genericDestruct,
307     genericPrint},
308     POC_BTFSC,
309     "BTFSC",
310     NULL, // from branch
311     NULL, // to branch
312     NULL, // label
313     NULL, // operand
314     NULL, // flow block
315     NULL, // C source 
316     2,    // num ops
317     0,1,  // dest, bit instruction
318     1,1,  // branch, skip
319     0,    // literal operand
320     POC_BTFSS,
321     (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
322     PCC_EXAMINE_PCOP // outCond
323 };
324
325 pCodeInstruction pciBTFSS = {
326   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
327     //   AnalyzeSKIP,
328     genericDestruct,
329     genericPrint},
330     POC_BTFSS,
331     "BTFSS",
332     NULL, // from branch
333     NULL, // to branch
334     NULL, // label
335     NULL, // operand
336     NULL, // flow block
337     NULL, // C source 
338     2,    // num ops
339     0,1,  // dest, bit instruction
340     1,1,  // branch, skip
341     0,    // literal operand
342     POC_BTFSC,
343     (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
344     PCC_EXAMINE_PCOP // outCond
345 };
346
347 pCodeInstruction pciCALL = {
348   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
349     //   genericAnalyze,
350     genericDestruct,
351     genericPrint},
352     POC_CALL,
353     "CALL",
354     NULL, // from branch
355     NULL, // to branch
356     NULL, // label
357     NULL, // operand
358     NULL, // flow block
359     NULL, // C source 
360     1,    // num ops
361     0,0,  // dest, bit instruction
362     1,0,  // branch, skip
363     0,    // literal operand
364     POC_NOP,
365     PCC_NONE, // inCond
366     PCC_NONE  // outCond
367 };
368
369 pCodeInstruction pciCOMF = {
370   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
371     //   genericAnalyze,
372     genericDestruct,
373     genericPrint},
374     POC_COMF,
375     "COMF",
376     NULL, // from branch
377     NULL, // to branch
378     NULL, // label
379     NULL, // operand
380     NULL, // flow block
381     NULL, // C source 
382     2,    // num ops
383     1,0,  // dest, bit instruction
384     0,0,  // branch, skip
385     0,    // literal operand
386     POC_NOP,
387     PCC_REGISTER,  // inCond
388     PCC_REGISTER   // outCond
389 };
390
391 pCodeInstruction pciCOMFW = {
392   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
393     //   genericAnalyze,
394     genericDestruct,
395     genericPrint},
396     POC_COMFW,
397     "COMF",
398     NULL, // from branch
399     NULL, // to branch
400     NULL, // label
401     NULL, // operand
402     NULL, // flow block
403     NULL, // C source 
404     2,    // num ops
405     0,0,  // dest, bit instruction
406     0,0,  // branch, skip
407     0,    // literal operand
408     POC_NOP,
409     PCC_REGISTER,  // inCond
410     PCC_W   // outCond
411 };
412
413 pCodeInstruction pciCLRF = {
414   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
415     //   genericAnalyze,
416     genericDestruct,
417     genericPrint},
418     POC_CLRF,
419     "CLRF",
420     NULL, // from branch
421     NULL, // to branch
422     NULL, // label
423     NULL, // operand
424     NULL, // flow block
425     NULL, // C source 
426     1,    // num ops
427     0,0,  // dest, bit instruction
428     0,0,  // branch, skip
429     0,    // literal operand
430     POC_NOP,
431     PCC_NONE, // inCond
432     PCC_REGISTER  // outCond
433 };
434
435 pCodeInstruction pciCLRW = {
436   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
437     //   genericAnalyze,
438     genericDestruct,
439     genericPrint},
440     POC_CLRW,
441     "CLRW",
442     NULL, // from branch
443     NULL, // to branch
444     NULL, // label
445     NULL, // operand
446     NULL, // flow block
447     NULL, // C source 
448     0,    // num ops
449     0,0,  // dest, bit instruction
450     0,0,  // branch, skip
451     0,    // literal operand
452     POC_NOP,
453     PCC_NONE, // inCond
454     PCC_W  // outCond
455 };
456
457 pCodeInstruction pciCLRWDT = {
458   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
459     //   genericAnalyze,
460     genericDestruct,
461     genericPrint},
462     POC_CLRWDT,
463     "CLRWDT",
464     NULL, // from branch
465     NULL, // to branch
466     NULL, // label
467     NULL, // operand
468     NULL, // flow block
469     NULL, // C source 
470     0,    // num ops
471     0,0,  // dest, bit instruction
472     0,0,  // branch, skip
473     0,    // literal operand
474     POC_NOP,
475     PCC_NONE, // inCond
476     PCC_NONE  // outCond
477 };
478
479 pCodeInstruction pciDECF = {
480   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
481     //   genericAnalyze,
482     genericDestruct,
483     genericPrint},
484     POC_DECF,
485     "DECF",
486     NULL, // from branch
487     NULL, // to branch
488     NULL, // label
489     NULL, // operand
490     NULL, // flow block
491     NULL, // C source 
492     2,    // num ops
493     1,0,  // dest, bit instruction
494     0,0,  // branch, skip
495     0,    // literal operand
496     POC_NOP,
497     PCC_REGISTER,   // inCond
498     PCC_REGISTER    // outCond
499 };
500
501 pCodeInstruction pciDECFW = {
502   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
503     //   genericAnalyze,
504     genericDestruct,
505     genericPrint},
506     POC_DECFW,
507     "DECF",
508     NULL, // from branch
509     NULL, // to branch
510     NULL, // label
511     NULL, // operand
512     NULL, // flow block
513     NULL, // C source 
514     2,    // num ops
515     0,0,  // dest, bit instruction
516     0,0,  // branch, skip
517     0,    // literal operand
518     POC_NOP,
519     PCC_REGISTER,   // inCond
520     PCC_W    // outCond
521 };
522
523 pCodeInstruction pciDECFSZ = {
524   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
525     //   AnalyzeSKIP,
526     genericDestruct,
527     genericPrint},
528     POC_DECFSZ,
529     "DECFSZ",
530     NULL, // from branch
531     NULL, // to branch
532     NULL, // label
533     NULL, // operand
534     NULL, // flow block
535     NULL, // C source 
536     2,    // num ops
537     1,0,  // dest, bit instruction
538     1,1,  // branch, skip
539     0,    // literal operand
540     POC_NOP,
541     PCC_REGISTER,   // inCond
542     PCC_REGISTER    // outCond
543 };
544
545 pCodeInstruction pciDECFSZW = {
546   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
547     //   AnalyzeSKIP,
548     genericDestruct,
549     genericPrint},
550     POC_DECFSZW,
551     "DECFSZ",
552     NULL, // from branch
553     NULL, // to branch
554     NULL, // label
555     NULL, // operand
556     NULL, // flow block
557     NULL, // C source 
558     2,    // num ops
559     0,0,  // dest, bit instruction
560     1,1,  // branch, skip
561     0,    // literal operand
562     POC_NOP,
563     PCC_REGISTER,   // inCond
564     PCC_W           // outCond
565 };
566
567 pCodeInstruction pciGOTO = {
568   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
569     //   AnalyzeGOTO,
570     genericDestruct,
571     genericPrint},
572     POC_GOTO,
573     "GOTO",
574     NULL, // from branch
575     NULL, // to branch
576     NULL, // label
577     NULL, // operand
578     NULL, // flow block
579     NULL, // C source 
580     1,    // num ops
581     0,0,  // dest, bit instruction
582     1,0,  // branch, skip
583     0,    // literal operand
584     POC_NOP,
585     PCC_NONE,   // inCond
586     PCC_NONE    // outCond
587 };
588
589 pCodeInstruction pciINCF = {
590   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
591     //   genericAnalyze,
592     genericDestruct,
593     genericPrint},
594     POC_INCF,
595     "INCF",
596     NULL, // from branch
597     NULL, // to branch
598     NULL, // label
599     NULL, // operand
600     NULL, // flow block
601     NULL, // C source 
602     2,    // num ops
603     1,0,  // dest, bit instruction
604     0,0,  // branch, skip
605     0,    // literal operand
606     POC_NOP,
607     PCC_REGISTER,   // inCond
608     PCC_REGISTER    // outCond
609 };
610
611 pCodeInstruction pciINCFW = {
612   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
613     //   genericAnalyze,
614     genericDestruct,
615     genericPrint},
616     POC_INCFW,
617     "INCF",
618     NULL, // from branch
619     NULL, // to branch
620     NULL, // label
621     NULL, // operand
622     NULL, // flow block
623     NULL, // C source 
624     2,    // num ops
625     0,0,  // dest, bit instruction
626     0,0,  // branch, skip
627     0,    // literal operand
628     POC_NOP,
629     PCC_REGISTER,   // inCond
630     PCC_W    // outCond
631 };
632
633 pCodeInstruction pciINCFSZ = {
634   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
635     //   AnalyzeSKIP,
636     genericDestruct,
637     genericPrint},
638     POC_INCFSZ,
639     "INCFSZ",
640     NULL, // from branch
641     NULL, // to branch
642     NULL, // label
643     NULL, // operand
644     NULL, // flow block
645     NULL, // C source 
646     2,    // num ops
647     1,0,  // dest, bit instruction
648     1,1,  // branch, skip
649     0,    // literal operand
650     POC_NOP,
651     PCC_REGISTER,   // inCond
652     PCC_REGISTER    // outCond
653 };
654
655 pCodeInstruction pciINCFSZW = {
656   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
657     //   AnalyzeSKIP,
658     genericDestruct,
659     genericPrint},
660     POC_INCFSZW,
661     "INCFSZ",
662     NULL, // from branch
663     NULL, // to branch
664     NULL, // label
665     NULL, // operand
666     NULL, // flow block
667     NULL, // C source 
668     2,    // num ops
669     0,0,  // dest, bit instruction
670     1,1,  // branch, skip
671     0,    // literal operand
672     POC_NOP,
673     PCC_REGISTER,   // inCond
674     PCC_W           // outCond
675 };
676
677 pCodeInstruction pciIORWF = {
678   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
679     //   genericAnalyze,
680     genericDestruct,
681     genericPrint},
682     POC_IORWF,
683     "IORWF",
684     NULL, // from branch
685     NULL, // to branch
686     NULL, // label
687     NULL, // operand
688     NULL, // flow block
689     NULL, // C source 
690     2,    // num ops
691     1,0,  // dest, bit instruction
692     0,0,  // branch, skip
693     0,    // literal operand
694     POC_NOP,
695     (PCC_W | PCC_REGISTER),   // inCond
696     (PCC_REGISTER | PCC_Z) // outCond
697 };
698
699 pCodeInstruction pciIORFW = {
700   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
701     //   genericAnalyze,
702     genericDestruct,
703     genericPrint},
704     POC_IORFW,
705     "IORWF",
706     NULL, // from branch
707     NULL, // to branch
708     NULL, // label
709     NULL, // operand
710     NULL, // flow block
711     NULL, // C source 
712     2,    // num ops
713     0,0,  // dest, bit instruction
714     0,0,  // branch, skip
715     0,    // literal operand
716     POC_NOP,
717     (PCC_W | PCC_REGISTER),   // inCond
718     (PCC_W | PCC_Z) // outCond
719 };
720
721 pCodeInstruction pciIORLW = {
722   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
723     //   genericAnalyze,
724     genericDestruct,
725     genericPrint},
726     POC_IORLW,
727     "IORLW",
728     NULL, // from branch
729     NULL, // to branch
730     NULL, // label
731     NULL, // operand
732     NULL, // flow block
733     NULL, // C source 
734     1,    // num ops
735     0,0,  // dest, bit instruction
736     0,0,  // branch, skip
737     1,    // literal operand
738     POC_NOP,
739     (PCC_W | PCC_LITERAL),   // inCond
740     (PCC_W | PCC_Z) // outCond
741 };
742
743 pCodeInstruction pciMOVF = {
744   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
745     //   genericAnalyze,
746     genericDestruct,
747     genericPrint},
748     POC_MOVF,
749     "MOVF",
750     NULL, // from branch
751     NULL, // to branch
752     NULL, // label
753     NULL, // operand
754     NULL, // flow block
755     NULL, // C source 
756     2,    // num ops
757     1,0,  // dest, bit instruction
758     0,0,  // branch, skip
759     0,    // literal operand
760     POC_NOP,
761     PCC_REGISTER,   // inCond
762     PCC_Z // outCond
763 };
764
765 pCodeInstruction pciMOVFW = {
766   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
767     //   genericAnalyze,
768     genericDestruct,
769     genericPrint},
770     POC_MOVFW,
771     "MOVF",
772     NULL, // from branch
773     NULL, // to branch
774     NULL, // label
775     NULL, // operand
776     NULL, // flow block
777     NULL, // C source 
778     2,    // num ops
779     0,0,  // dest, bit instruction
780     0,0,  // branch, skip
781     0,    // literal operand
782     POC_NOP,
783     PCC_REGISTER,   // inCond
784     (PCC_W | PCC_Z) // outCond
785 };
786
787 pCodeInstruction pciMOVWF = {
788   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
789    //   genericAnalyze,
790    genericDestruct,
791    genericPrint},
792   POC_MOVWF,
793   "MOVWF",
794   NULL, // from branch
795   NULL, // to branch
796   NULL, // label
797   NULL, // operand
798   NULL, // flow block
799   NULL, // C source 
800   1,    // num ops
801   0,0,  // dest, bit instruction
802   0,0,  // branch, skip
803   0,    // literal operand
804   POC_NOP,
805   PCC_W,   // inCond
806   PCC_REGISTER // outCond
807 };
808
809 pCodeInstruction pciMOVLW = {
810   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
811    genericDestruct,
812    genericPrint},
813   POC_MOVLW,
814   "MOVLW",
815   NULL, // from branch
816   NULL, // to branch
817   NULL, // label
818   NULL, // operand
819   NULL, // flow block
820   NULL, // C source 
821   1,    // num ops
822   0,0,  // dest, bit instruction
823   0,0,  // branch, skip
824   1,    // literal operand
825   POC_NOP,
826   (PCC_NONE | PCC_LITERAL),   // inCond
827   PCC_W // outCond
828 };
829
830 pCodeInstruction pciNOP = {
831   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
832     genericDestruct,
833     genericPrint},
834     POC_NOP,
835     "NOP",
836     NULL, // from branch
837     NULL, // to branch
838     NULL, // label
839     NULL, // operand
840     NULL, // flow block
841     NULL, // C source 
842     0,    // num ops
843     0,0,  // dest, bit instruction
844     0,0,  // branch, skip
845     0,    // literal operand
846     POC_NOP,
847     PCC_NONE,   // inCond
848     PCC_NONE // outCond
849 };
850
851 pCodeInstruction pciRETFIE = {
852   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
853     //   AnalyzeRETURN,
854     genericDestruct,
855     genericPrint},
856     POC_RETFIE,
857     "RETFIE",
858     NULL, // from branch
859     NULL, // to branch
860     NULL, // label
861     NULL, // operand
862     NULL, // flow block
863     NULL, // C source 
864     0,    // num ops
865     0,0,  // dest, bit instruction
866     1,0,  // branch, skip
867     0,    // literal operand
868     POC_NOP,
869     PCC_NONE,   // inCond
870     PCC_NONE // outCond (not true... affects the GIE bit too)
871 };
872
873 pCodeInstruction pciRETLW = {
874   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
875     //   AnalyzeRETURN,
876     genericDestruct,
877     genericPrint},
878     POC_RETLW,
879     "RETLW",
880     NULL, // from branch
881     NULL, // to branch
882     NULL, // label
883     NULL, // operand
884     NULL, // flow block
885     NULL, // C source 
886     1,    // num ops
887     0,0,  // dest, bit instruction
888     1,0,  // branch, skip
889     1,    // literal operand
890     POC_NOP,
891     PCC_LITERAL,   // inCond
892     PCC_W // outCond
893 };
894
895 pCodeInstruction pciRETURN = {
896   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
897     //   AnalyzeRETURN,
898     genericDestruct,
899     genericPrint},
900     POC_RETURN,
901     "RETURN",
902     NULL, // from branch
903     NULL, // to branch
904     NULL, // label
905     NULL, // operand
906     NULL, // flow block
907     NULL, // C source 
908     0,    // num ops
909     0,0,  // dest, bit instruction
910     1,0,  // branch, skip
911     0,    // literal operand
912     POC_NOP,
913     PCC_NONE,   // inCond
914     PCC_NONE // outCond
915 };
916
917 pCodeInstruction pciRLF = {
918   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
919     //   genericAnalyze,
920     genericDestruct,
921     genericPrint},
922     POC_RLF,
923     "RLF",
924     NULL, // from branch
925     NULL, // to branch
926     NULL, // label
927     NULL, // operand
928     NULL, // flow block
929     NULL, // C source 
930     2,    // num ops
931     1,0,  // dest, bit instruction
932     0,0,  // branch, skip
933     0,    // literal operand
934     POC_NOP,
935     (PCC_C | PCC_REGISTER),   // inCond
936     (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
937 };
938
939 pCodeInstruction pciRLFW = {
940   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
941     //   genericAnalyze,
942     genericDestruct,
943     genericPrint},
944     POC_RLFW,
945     "RLF",
946     NULL, // from branch
947     NULL, // to branch
948     NULL, // label
949     NULL, // operand
950     NULL, // flow block
951     NULL, // C source 
952     2,    // num ops
953     0,0,  // dest, bit instruction
954     0,0,  // branch, skip
955     0,    // literal operand
956     POC_NOP,
957     (PCC_C | PCC_REGISTER),   // inCond
958     (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
959 };
960
961 pCodeInstruction pciRRF = {
962   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
963     //   genericAnalyze,
964     genericDestruct,
965     genericPrint},
966     POC_RRF,
967     "RRF",
968     NULL, // from branch
969     NULL, // to branch
970     NULL, // label
971     NULL, // operand
972     NULL, // flow block
973     NULL, // C source 
974     2,    // num ops
975     1,0,  // dest, bit instruction
976     0,0,  // branch, skip
977     0,    // literal operand
978     POC_NOP,
979     (PCC_C | PCC_REGISTER),   // inCond
980     (PCC_REGISTER | PCC_Z | PCC_C | PCC_DC) // outCond
981 };
982
983 pCodeInstruction pciRRFW = {
984   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
985     //   genericAnalyze,
986     genericDestruct,
987     genericPrint},
988     POC_RRFW,
989     "RRF",
990     NULL, // from branch
991     NULL, // to branch
992     NULL, // label
993     NULL, // operand
994     NULL, // flow block
995     NULL, // C source 
996     2,    // num ops
997     0,0,  // dest, bit instruction
998     0,0,  // branch, skip
999     0,    // literal operand
1000     POC_NOP,
1001     (PCC_C | PCC_REGISTER),   // inCond
1002     (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1003 };
1004
1005 pCodeInstruction pciSUBWF = {
1006   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
1007     //   genericAnalyze,
1008     genericDestruct,
1009     genericPrint},
1010     POC_SUBWF,
1011     "SUBWF",
1012     NULL, // from branch
1013     NULL, // to branch
1014     NULL, // label
1015     NULL, // operand
1016     NULL, // flow block
1017     NULL, // C source 
1018     2,    // num ops
1019     1,0,  // dest, bit instruction
1020     0,0,  // branch, skip
1021     0,    // literal operand
1022     POC_NOP,
1023     (PCC_W | PCC_REGISTER),   // inCond
1024     (PCC_REGISTER | PCC_Z) // outCond
1025 };
1026
1027 pCodeInstruction pciSUBFW = {
1028   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
1029     //   genericAnalyze,
1030     genericDestruct,
1031     genericPrint},
1032     POC_SUBFW,
1033     "SUBWF",
1034     NULL, // from branch
1035     NULL, // to branch
1036     NULL, // label
1037     NULL, // operand
1038     NULL, // flow block
1039     NULL, // C source 
1040     2,    // num ops
1041     0,0,  // dest, bit instruction
1042     0,0,  // branch, skip
1043     0,    // literal operand
1044     POC_NOP,
1045     (PCC_W | PCC_REGISTER),   // inCond
1046     (PCC_W | PCC_Z) // outCond
1047 };
1048
1049 pCodeInstruction pciSUBLW = {
1050   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
1051     //   genericAnalyze,
1052     genericDestruct,
1053     genericPrint},
1054     POC_SUBLW,
1055     "SUBLW",
1056     NULL, // from branch
1057     NULL, // to branch
1058     NULL, // label
1059     NULL, // operand
1060     NULL, // flow block
1061     NULL, // C source 
1062     1,    // num ops
1063     0,0,  // dest, bit instruction
1064     0,0,  // branch, skip
1065     1,    // literal operand
1066     POC_NOP,
1067     (PCC_W | PCC_LITERAL),   // inCond
1068     (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1069 };
1070
1071 pCodeInstruction pciSWAPF = {
1072   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
1073     //   genericAnalyze,
1074     genericDestruct,
1075     genericPrint},
1076     POC_SWAPF,
1077     "SWAPF",
1078     NULL, // from branch
1079     NULL, // to branch
1080     NULL, // label
1081     NULL, // operand
1082     NULL, // flow block
1083     NULL, // C source 
1084     2,    // num ops
1085     1,0,  // dest, bit instruction
1086     0,0,  // branch, skip
1087     0,    // literal operand
1088     POC_NOP,
1089     (PCC_REGISTER),   // inCond
1090     (PCC_REGISTER) // outCond
1091 };
1092
1093 pCodeInstruction pciSWAPFW = {
1094   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
1095     //   genericAnalyze,
1096     genericDestruct,
1097     genericPrint},
1098     POC_SWAPFW,
1099     "SWAPF",
1100     NULL, // from branch
1101     NULL, // to branch
1102     NULL, // label
1103     NULL, // operand
1104     NULL, // flow block
1105     NULL, // C source 
1106     2,    // num ops
1107     0,0,  // dest, bit instruction
1108     0,0,  // branch, skip
1109     0,    // literal operand
1110     POC_NOP,
1111     (PCC_REGISTER),   // inCond
1112     (PCC_W) // outCond
1113 };
1114
1115 pCodeInstruction pciTRIS = {
1116   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
1117     //   genericAnalyze,
1118     genericDestruct,
1119     genericPrint},
1120     POC_TRIS,
1121     "TRIS",
1122     NULL, // from branch
1123     NULL, // to branch
1124     NULL, // label
1125     NULL, // operand
1126     NULL, // flow block
1127     NULL, // C source 
1128     1,    // num ops
1129     0,0,  // dest, bit instruction
1130     0,0,  // branch, skip
1131     0,    // literal operand
1132     POC_NOP,
1133     PCC_NONE,   // inCond
1134     PCC_REGISTER // outCond
1135 };
1136
1137 pCodeInstruction pciXORWF = {
1138   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
1139     //   genericAnalyze,
1140     genericDestruct,
1141     genericPrint},
1142     POC_XORWF,
1143     "XORWF",
1144     NULL, // from branch
1145     NULL, // to branch
1146     NULL, // label
1147     NULL, // operand
1148     NULL, // flow block
1149     NULL, // C source 
1150     2,    // num ops
1151     1,0,  // dest, bit instruction
1152     0,0,  // branch, skip
1153     0,    // literal operand
1154     POC_NOP,
1155     (PCC_W | PCC_REGISTER),   // inCond
1156     (PCC_REGISTER | PCC_Z) // outCond
1157 };
1158
1159 pCodeInstruction pciXORFW = {
1160   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
1161     //   genericAnalyze,
1162     genericDestruct,
1163     genericPrint},
1164     POC_XORFW,
1165     "XORWF",
1166     NULL, // from branch
1167     NULL, // to branch
1168     NULL, // label
1169     NULL, // operand
1170     NULL, // flow block
1171     NULL, // C source 
1172     2,    // num ops
1173     0,0,  // dest, bit instruction
1174     0,0,  // branch, skip
1175     0,    // literal operand
1176     POC_NOP,
1177     (PCC_W | PCC_REGISTER),   // inCond
1178     (PCC_W | PCC_Z) // outCond
1179 };
1180
1181 pCodeInstruction pciXORLW = {
1182   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
1183     //   genericAnalyze,
1184     genericDestruct,
1185     genericPrint},
1186     POC_XORLW,
1187     "XORLW",
1188     NULL, // from branch
1189     NULL, // to branch
1190     NULL, // label
1191     NULL, // operand
1192     NULL, // flow block
1193     NULL, // C source 
1194     1,    // num ops
1195     0,0,  // dest, bit instruction
1196     0,0,  // branch, skip
1197     1,    // literal operand
1198     POC_NOP,
1199     (PCC_W | PCC_LITERAL),   // inCond
1200     (PCC_W | PCC_Z | PCC_C | PCC_DC) // outCond
1201 };
1202
1203
1204 pCodeInstruction pciBANKSEL = {
1205   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
1206     //   genericAnalyze,
1207     genericDestruct,
1208     genericPrint},
1209     POC_BANKSEL,
1210     "BANKSEL",
1211     NULL, // from branch
1212     NULL, // to branch
1213     NULL, // label
1214     NULL, // operand
1215     NULL, // flow block
1216     NULL, // C source 
1217     1,    // num ops
1218     0,0,  // dest, bit instruction
1219     0,0,  // branch, skip
1220     0,    // literal operand
1221     POC_NOP,
1222     PCC_NONE, // inCond
1223     PCC_REGISTER  // outCond
1224 };
1225
1226 pCodeInstruction pciPAGESEL = {
1227   {PC_OPCODE, NULL, NULL, 0, 0, NULL, 
1228     //   genericAnalyze,
1229     genericDestruct,
1230     genericPrint},
1231     POC_PAGESEL,
1232     "PAGESEL",
1233     NULL, // from branch
1234     NULL, // to branch
1235     NULL, // label
1236     NULL, // operand
1237     NULL, // flow block
1238     NULL, // C source 
1239     1,    // num ops
1240     0,0,  // dest, bit instruction
1241     0,0,  // branch, skip
1242     0,    // literal operand
1243     POC_NOP,
1244     PCC_NONE, // inCond
1245     PCC_REGISTER  // outCond
1246 };
1247
1248 pCodeInstruction *pic14Mnemonics[MAX_PIC14MNEMONICS];
1249
1250
1251 /*-----------------------------------------------------------------*/
1252 /* return a unique ID number to assist pCodes debuging             */
1253 /*-----------------------------------------------------------------*/
1254 unsigned PCodeID(void) {
1255   static unsigned int pcodeId = 1; /* unique ID number to be assigned to all pCodes */
1256   /*
1257   static unsigned int stop;
1258   if (pcodeId == 5801)
1259   stop++;
1260   if ((pcodeId >= 855)&&(pcodeId <= 856))
1261   stop++;
1262   */
1263   return pcodeId++;
1264 }
1265
1266 #ifdef HAVE_VSNPRINTF
1267 // Alas, vsnprintf is not ANSI standard, and does not exist
1268 // on Solaris (and probably other non-Gnu flavored Unixes).
1269
1270 /*-----------------------------------------------------------------*/
1271 /* SAFE_snprintf - like snprintf except the string pointer is      */
1272 /*                 after the string has been printed to. This is   */
1273 /*                 useful for printing to string as though if it   */
1274 /*                 were a stream.                                  */
1275 /*-----------------------------------------------------------------*/
1276 void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
1277 {
1278   va_list val;
1279   int len;
1280   
1281   if(!str || !*str)
1282     return;
1283   
1284   va_start(val, format);
1285   
1286   vsnprintf(*str, *size, format, val);
1287   
1288   va_end (val);
1289   
1290   len = strlen(*str);
1291   if((size_t)len > *size) {
1292     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1293     fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size);
1294   }
1295   
1296   *str += len;
1297   *size -= len;
1298   
1299 }
1300
1301 #else  //  HAVE_VSNPRINTF
1302
1303 // This version is *not* safe, despite the name.
1304
1305 void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
1306 {
1307   va_list val;
1308   int len;
1309   static char buffer[1024]; /* grossly conservative, but still not inherently safe */
1310   
1311   if(!str || !*str)
1312     return;
1313   
1314   va_start(val, format);
1315   
1316   vsprintf(buffer, format, val);
1317   va_end (val);
1318   
1319   len = strlen(buffer);
1320   if(len > *size) {
1321     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
1322     fprintf(stderr,"len = %d is > str size %d\n",len,*size);
1323   }
1324   
1325   strcpy(*str, buffer);
1326   *str += len;
1327   *size -= len;
1328   
1329 }
1330
1331 #endif    //  HAVE_VSNPRINTF
1332
1333
1334 extern  void initStack(int base_address, int size);
1335 extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
1336 extern regs *allocInternalRegister(int rIdx, char * name, short po_type, int alias);
1337 extern void init_pic(char *);
1338
1339 void  pCodeInitRegisters(void)
1340 {
1341   static int initialized=0;
1342   int shareBankAddress,stkSize;
1343   
1344   if(initialized)
1345     return;
1346   initialized = 1;
1347   
1348   shareBankAddress = 0x7f; /* FIXME - some PIC ICs like 16C7X which do not have a shared bank need a different approach. */
1349   stkSize = 8; // Set pseudo stack size to 8
1350   initStack(shareBankAddress, stkSize); // Putting the pseudo stack in shared memory so all modules use the same register when passing fn parameters
1351   init_pic(port->processor);
1352   
1353   pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1354   pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1355   pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1356   pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1357   pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x80);
1358   pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1359   
1360   pc_status.rIdx = IDX_STATUS;
1361   pc_fsr.rIdx = IDX_FSR;
1362   pc_indf.rIdx = IDX_INDF;
1363   pc_intcon.rIdx = IDX_INTCON;
1364   pc_pcl.rIdx = IDX_PCL;
1365   pc_pclath.rIdx = IDX_PCLATH;
1366   
1367   pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0x180); /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1368   pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0); /* Interrupt storage for status register. */
1369   pc_psave.r = allocInternalRegister(IDX_PSAVE,"PSAVE", PO_GPR_REGISTER, 0); /* Interrupt storage for pclath register. */
1370   
1371   pc_wsave.rIdx = pc_wsave.r->rIdx;
1372   pc_ssave.rIdx = pc_ssave.r->rIdx;
1373   pc_psave.rIdx = pc_psave.r->rIdx;
1374   
1375   pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1376   pc_wsave.r->address = shareBankAddress-stkSize;
1377   pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1378   pc_ssave.r->address = shareBankAddress-stkSize-1;
1379   pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1380   pc_psave.r->address = shareBankAddress-stkSize-2;
1381   
1382   /* probably should put this in a separate initialization routine */
1383   pb_dead_pcodes = newpBlock();
1384   
1385 }
1386
1387 /*-----------------------------------------------------------------*/
1388 /*  mnem2key - convert a pic mnemonic into a hash key              */
1389 /*   (BTW - this spreads the mnemonics quite well)                 */
1390 /*                                                                 */
1391 /*-----------------------------------------------------------------*/
1392
1393 int mnem2key(char const *mnem)
1394 {
1395   int key = 0;
1396   
1397   if(!mnem)
1398     return 0;
1399   
1400   while(*mnem) {
1401     
1402     key += toupper(*mnem++) +1;
1403     
1404   }
1405   
1406   return (key & 0x1f);
1407   
1408 }
1409
1410 void pic14initMnemonics(void)
1411 {
1412   int i = 0;
1413   int key;
1414   //  char *str;
1415   pCodeInstruction *pci;
1416   
1417   if(mnemonics_initialized)
1418     return;
1419   
1420   //FIXME - probably should NULL out the array before making the assignments
1421   //since we check the array contents below this initialization.
1422   
1423   pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1424   pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1425   pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1426   pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1427   pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1428   pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1429   pic14Mnemonics[POC_BCF] = &pciBCF;
1430   pic14Mnemonics[POC_BSF] = &pciBSF;
1431   pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1432   pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1433   pic14Mnemonics[POC_CALL] = &pciCALL;
1434   pic14Mnemonics[POC_COMF] = &pciCOMF;
1435   pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1436   pic14Mnemonics[POC_CLRF] = &pciCLRF;
1437   pic14Mnemonics[POC_CLRW] = &pciCLRW;
1438   pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1439   pic14Mnemonics[POC_DECF] = &pciDECF;
1440   pic14Mnemonics[POC_DECFW] = &pciDECFW;
1441   pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1442   pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1443   pic14Mnemonics[POC_GOTO] = &pciGOTO;
1444   pic14Mnemonics[POC_INCF] = &pciINCF;
1445   pic14Mnemonics[POC_INCFW] = &pciINCFW;
1446   pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1447   pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1448   pic14Mnemonics[POC_IORLW] = &pciIORLW;
1449   pic14Mnemonics[POC_IORWF] = &pciIORWF;
1450   pic14Mnemonics[POC_IORFW] = &pciIORFW;
1451   pic14Mnemonics[POC_MOVF] = &pciMOVF;
1452   pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1453   pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1454   pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1455   pic14Mnemonics[POC_NOP] = &pciNOP;
1456   pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1457   pic14Mnemonics[POC_RETLW] = &pciRETLW;
1458   pic14Mnemonics[POC_RETURN] = &pciRETURN;
1459   pic14Mnemonics[POC_RLF] = &pciRLF;
1460   pic14Mnemonics[POC_RLFW] = &pciRLFW;
1461   pic14Mnemonics[POC_RRF] = &pciRRF;
1462   pic14Mnemonics[POC_RRFW] = &pciRRFW;
1463   pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1464   pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1465   pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1466   pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1467   pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1468   pic14Mnemonics[POC_TRIS] = &pciTRIS;
1469   pic14Mnemonics[POC_XORLW] = &pciXORLW;
1470   pic14Mnemonics[POC_XORWF] = &pciXORWF;
1471   pic14Mnemonics[POC_XORFW] = &pciXORFW;
1472   pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1473   pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1474   
1475   for(i=0; i<MAX_PIC14MNEMONICS; i++)
1476     if(pic14Mnemonics[i])
1477       hTabAddItem(&pic14MnemonicsHash, mnem2key(pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1478     pci = hTabFirstItem(pic14MnemonicsHash, &key);
1479     
1480     while(pci) {
1481       DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1482       pci = hTabNextItem(pic14MnemonicsHash, &key);
1483     }
1484     
1485     mnemonics_initialized = 1;
1486 }
1487
1488 int getpCodePeepCommand(char *cmd);
1489
1490 int getpCode(char *mnem,unsigned dest)
1491 {
1492   
1493   pCodeInstruction *pci;
1494   int key = mnem2key(mnem);
1495   
1496   if(!mnemonics_initialized)
1497     pic14initMnemonics();
1498   
1499   pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1500   
1501   while(pci) {
1502     
1503     if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1504       if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1505         return(pci->op);
1506     }
1507     
1508     pci = hTabNextItemWK (pic14MnemonicsHash);
1509     
1510   }
1511   
1512   return -1;
1513 }
1514
1515 /*-----------------------------------------------------------------*
1516 * pic14initpCodePeepCommands
1517 *
1518 *-----------------------------------------------------------------*/
1519 void pic14initpCodePeepCommands(void)
1520 {
1521   
1522   int key, i;
1523   peepCommand *pcmd;
1524   
1525   i = 0;
1526   do {
1527     hTabAddItem(&pic14pCodePeepCommandsHash, 
1528       mnem2key(peepCommands[i].cmd), &peepCommands[i]);
1529     i++;
1530   } while (peepCommands[i].cmd);
1531   
1532   pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1533   
1534   while(pcmd) {
1535     //fprintf(stderr, "peep command %s  key %d\n",pcmd->cmd,pcmd->id);
1536     pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1537   }
1538   
1539 }
1540
1541 /*-----------------------------------------------------------------
1542 *
1543 *
1544 *-----------------------------------------------------------------*/
1545
1546 int getpCodePeepCommand(char *cmd)
1547 {
1548   
1549   peepCommand *pcmd;
1550   int key = mnem2key(cmd);
1551   
1552   
1553   pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1554   
1555   while(pcmd) {
1556     // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1557     if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1558       return pcmd->id;
1559     }
1560     
1561     pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1562     
1563   }
1564   
1565   return -1;
1566 }
1567
1568 char getpBlock_dbName(pBlock *pb)
1569 {
1570   if(!pb)
1571     return 0;
1572   
1573   if(pb->cmemmap)
1574     return pb->cmemmap->dbName;
1575   
1576   return pb->dbName;
1577 }
1578 void pBlockConvert2ISR(pBlock *pb)
1579 {
1580   if(!pb)
1581     return;
1582   
1583   if(pb->cmemmap)
1584     pb->cmemmap = NULL;
1585   
1586   pb->dbName = 'I';
1587 }
1588
1589 /*-----------------------------------------------------------------*/
1590 /* movepBlock2Head - given the dbname of a pBlock, move all        */
1591 /*                   instances to the front of the doubly linked   */
1592 /*                   list of pBlocks                               */
1593 /*-----------------------------------------------------------------*/
1594
1595 void movepBlock2Head(char dbName)
1596 {
1597   pBlock *pb;
1598
1599   if (!the_pFile)
1600     return;
1601
1602   pb = the_pFile->pbHead;
1603
1604   while(pb) {
1605     
1606     if(getpBlock_dbName(pb) == dbName) {
1607       pBlock *pbn = pb->next;
1608       pb->next = the_pFile->pbHead;
1609       the_pFile->pbHead->prev = pb;
1610       the_pFile->pbHead = pb;
1611       
1612       if(pb->prev)
1613         pb->prev->next = pbn;
1614       
1615       // If the pBlock that we just moved was the last
1616       // one in the link of all of the pBlocks, then we
1617       // need to point the tail to the block just before
1618       // the one we moved.
1619       // Note: if pb->next is NULL, then pb must have 
1620       // been the last pBlock in the chain.
1621       
1622       if(pbn)
1623         pbn->prev = pb->prev;
1624       else
1625         the_pFile->pbTail = pb->prev;
1626       
1627       pb = pbn;
1628       
1629     } else
1630       pb = pb->next;
1631     
1632   }
1633   
1634 }
1635
1636 void copypCode(FILE *of, char dbName)
1637 {
1638   pBlock *pb;
1639   
1640   if(!of || !the_pFile)
1641     return;
1642   
1643   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1644     if(getpBlock_dbName(pb) == dbName) {
1645       pBlockStats(of,pb);
1646       printpBlock(of,pb);
1647       fprintf (of, "\n");
1648     }
1649   }
1650   
1651 }
1652 void pcode_test(void)
1653 {
1654   
1655   DFPRINTF((stderr,"pcode is alive!\n"));
1656   
1657   //initMnemonics();
1658   
1659   if(the_pFile) {
1660     
1661     pBlock *pb;
1662     FILE *pFile;
1663     char buffer[100];
1664     
1665     /* create the file name */
1666     strcpy(buffer,dstFileName);
1667     strcat(buffer,".p");
1668     
1669     if( !(pFile = fopen(buffer, "w" ))) {
1670       werror(E_FILE_OPEN_ERR,buffer);
1671       exit(1);
1672     }
1673     
1674     fprintf(pFile,"pcode dump\n\n");
1675     
1676     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1677       fprintf(pFile,"\n\tNew pBlock\n\n");
1678       if(pb->cmemmap)
1679         fprintf(pFile,"%s",pb->cmemmap->sname);
1680       else
1681         fprintf(pFile,"internal pblock");
1682       
1683       fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1684       printpBlock(pFile,pb);
1685     }
1686   }
1687 }
1688 /*-----------------------------------------------------------------*/
1689 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg-  */
1690 /*      ister, RegCond will return the bit being referenced.       */
1691 /*                                                                 */
1692 /* fixme - why not just OR in the pcop bit field                   */
1693 /*-----------------------------------------------------------------*/
1694
1695 static int RegCond(pCodeOp *pcop)
1696 {
1697   
1698   if(!pcop)
1699     return 0;
1700   
1701   if (pcop->type == PO_GPR_BIT) {
1702     char *name = pcop->name;
1703     if (!name) 
1704       name = PCOR(pcop)->r->name;
1705     //      if (strcmp(name, pc_status.pcop.name) != 0) { <<< This breaks the peep 2 optimisation
1706     switch(PCORB(pcop)->bit) {
1707     case PIC_C_BIT:
1708       return PCC_C;
1709     case PIC_DC_BIT:
1710       return PCC_DC;
1711     case PIC_Z_BIT:
1712       return PCC_Z;
1713     }
1714     //    }
1715   }
1716   
1717   return 0;
1718 }
1719
1720 /*-----------------------------------------------------------------*/
1721 /* newpCode - create and return a newly initialized pCode          */
1722 /*                                                                 */
1723 /*  fixme - rename this                                            */
1724 /*                                                                 */
1725 /* The purpose of this routine is to create a new Instruction      */
1726 /* pCode. This is called by gen.c while the assembly code is being */
1727 /* generated.                                                      */
1728 /*                                                                 */
1729 /* Inouts:                                                         */
1730 /*  PIC_OPCODE op - the assembly instruction we wish to create.    */
1731 /*                  (note that the op is analogous to but not the  */
1732 /*                  same thing as the opcode of the instruction.)  */
1733 /*  pCdoeOp *pcop - pointer to the operand of the instruction.     */
1734 /*                                                                 */
1735 /* Outputs:                                                        */
1736 /*  a pointer to the new malloc'd pCode is returned.               */
1737 /*                                                                 */
1738 /*                                                                 */
1739 /*                                                                 */
1740 /*-----------------------------------------------------------------*/
1741 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1742 {
1743   pCodeInstruction *pci ;
1744   
1745   if(!mnemonics_initialized)
1746     pic14initMnemonics();
1747
1748   pci = Safe_calloc(1, sizeof(pCodeInstruction));
1749   
1750   if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1751     memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1752     pci->pc.id = PCodeID();
1753     pci->pcop = pcop;
1754     
1755     if(pci->inCond & PCC_EXAMINE_PCOP)
1756       pci->inCond  |= RegCond(pcop);
1757     
1758     if(pci->outCond & PCC_EXAMINE_PCOP)
1759       pci->outCond  |= RegCond(pcop);
1760     
1761     pci->pc.prev = pci->pc.next = NULL;
1762     return (pCode *)pci;
1763   }
1764   
1765   fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1766   exit(1);
1767   
1768   return NULL;
1769 }       
1770
1771 /*-----------------------------------------------------------------*/
1772 /* newpCodeWild - create a "wild" as in wild card pCode            */
1773 /*                                                                 */
1774 /* Wild pcodes are used during the peep hole optimizer to serve    */
1775 /* as place holders for any instruction. When a snippet of code is */
1776 /* compared to a peep hole rule, the wild card opcode will match   */
1777 /* any instruction. However, the optional operand and label are    */
1778 /* additional qualifiers that must also be matched before the      */
1779 /* line (of assembly code) is declared matched. Note that the      */
1780 /* operand may be wild too.                                        */
1781 /*                                                                 */
1782 /*   Note, a wild instruction is specified just like a wild var:   */
1783 /*      %4     ; A wild instruction,                               */
1784 /*  See the peeph.def file for additional examples                 */
1785 /*                                                                 */
1786 /*-----------------------------------------------------------------*/
1787
1788 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1789 {
1790   
1791   pCodeWild *pcw;
1792
1793   pcw = Safe_calloc(1,sizeof(pCodeWild));
1794   
1795   pcw->pci.pc.type = PC_WILD;
1796   pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1797   pcw->id = PCodeID();
1798   pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1799   pcw->pci.pc.pb = NULL;
1800   
1801   //  pcw->pci.pc.analyze = genericAnalyze;
1802   pcw->pci.pc.destruct = genericDestruct;
1803   pcw->pci.pc.print = genericPrint;
1804   
1805   pcw->id = pCodeID;              // this is the 'n' in %n
1806   pcw->operand = optional_operand;
1807   pcw->label   = optional_label;
1808   
1809   pcw->mustBeBitSkipInst = 0;
1810   pcw->mustNotBeBitSkipInst = 0;
1811   pcw->invertBitSkipInst = 0;
1812   
1813   return ( (pCode *)pcw);
1814   
1815 }
1816
1817 /*-----------------------------------------------------------------*/
1818 /* newPcodeInlineP - create a new pCode from a char string           */
1819 /*-----------------------------------------------------------------*/
1820
1821
1822 pCode *newpCodeInlineP(char *cP)
1823 {
1824   
1825   pCodeComment *pcc ;
1826
1827   pcc = Safe_calloc(1,sizeof(pCodeComment));
1828   
1829   pcc->pc.type = PC_INLINE;
1830   pcc->pc.prev = pcc->pc.next = NULL;
1831   pcc->pc.id = PCodeID();
1832   //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1833   pcc->pc.pb = NULL;
1834   
1835   //  pcc->pc.analyze = genericAnalyze;
1836   pcc->pc.destruct = genericDestruct;
1837   pcc->pc.print = genericPrint;
1838   
1839   if(cP)
1840     pcc->comment = Safe_strdup(cP);
1841   else
1842     pcc->comment = NULL;
1843   
1844   return ( (pCode *)pcc);
1845   
1846 }
1847
1848 /*-----------------------------------------------------------------*/
1849 /* newPcodeCharP - create a new pCode from a char string           */
1850 /*-----------------------------------------------------------------*/
1851
1852 pCode *newpCodeCharP(char *cP)
1853 {
1854   
1855   pCodeComment *pcc ;
1856
1857   pcc = Safe_calloc(1,sizeof(pCodeComment));
1858   
1859   pcc->pc.type = PC_COMMENT;
1860   pcc->pc.prev = pcc->pc.next = NULL;
1861   pcc->pc.id = PCodeID();
1862   //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1863   pcc->pc.pb = NULL;
1864   
1865   //  pcc->pc.analyze = genericAnalyze;
1866   pcc->pc.destruct = genericDestruct;
1867   pcc->pc.print = genericPrint;
1868   
1869   if(cP)
1870     pcc->comment = Safe_strdup(cP);
1871   else
1872     pcc->comment = NULL;
1873   
1874   return ( (pCode *)pcc);
1875   
1876 }
1877
1878 /*-----------------------------------------------------------------*/
1879 /* newpCodeFunction -                                              */
1880 /*-----------------------------------------------------------------*/
1881
1882
1883 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1884 {
1885   pCodeFunction *pcf;
1886   
1887   pcf = Safe_calloc(1,sizeof(pCodeFunction));
1888   //_ALLOC(pcf,sizeof(pCodeFunction));
1889   
1890   pcf->pc.type = PC_FUNCTION;
1891   pcf->pc.prev = pcf->pc.next = NULL;
1892   pcf->pc.id = PCodeID();
1893   //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1894   pcf->pc.pb = NULL;
1895   
1896   //  pcf->pc.analyze = genericAnalyze;
1897   pcf->pc.destruct = genericDestruct;
1898   pcf->pc.print = pCodePrintFunction;
1899   
1900   pcf->ncalled = 0;
1901   
1902   if(mod) {
1903     //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1904     pcf->modname = Safe_calloc(1,strlen(mod)+1);
1905     strcpy(pcf->modname,mod);
1906   } else
1907     pcf->modname = NULL;
1908   
1909   if(f) {
1910     //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1911     pcf->fname = Safe_calloc(1,strlen(f)+1);
1912     strcpy(pcf->fname,f);
1913   } else
1914     pcf->fname = NULL;
1915   
1916   pcf->isPublic = (unsigned)isPublic;
1917   
1918   return ( (pCode *)pcf);
1919   
1920 }
1921
1922 /*-----------------------------------------------------------------*/
1923 /* newpCodeFlow                                                    */
1924 /*-----------------------------------------------------------------*/
1925 void destructpCodeFlow(pCode *pc)
1926 {
1927   if(!pc || !isPCFL(pc))
1928     return;
1929   
1930     /*
1931     if(PCFL(pc)->from)
1932     if(PCFL(pc)->to)
1933   */
1934   unlinkpCode(pc);
1935   
1936   deleteSet(&PCFL(pc)->registers);
1937   deleteSet(&PCFL(pc)->from);
1938   deleteSet(&PCFL(pc)->to);
1939   free(pc);
1940   
1941 }
1942
1943 pCode *newpCodeFlow(void )
1944 {
1945   pCodeFlow *pcflow;
1946   
1947   //_ALLOC(pcflow,sizeof(pCodeFlow));
1948   pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1949   
1950   pcflow->pc.type = PC_FLOW;
1951   pcflow->pc.prev = pcflow->pc.next = NULL;
1952   pcflow->pc.pb = NULL;
1953   
1954   //  pcflow->pc.analyze = genericAnalyze;
1955   pcflow->pc.destruct = destructpCodeFlow;
1956   pcflow->pc.print = genericPrint;
1957   
1958   pcflow->pc.seq = GpcFlowSeq++;
1959   
1960   pcflow->from = pcflow->to = NULL;
1961   
1962   pcflow->inCond = PCC_NONE;
1963   pcflow->outCond = PCC_NONE;
1964   
1965   pcflow->firstBank = 'U'; /* Undetermined */
1966   pcflow->lastBank = 'U'; /* Undetermined */
1967   
1968   pcflow->FromConflicts = 0;
1969   pcflow->ToConflicts = 0;
1970   
1971   pcflow->end = NULL;
1972   
1973   pcflow->registers = newSet();
1974   
1975   return ( (pCode *)pcflow);
1976   
1977 }
1978
1979 /*-----------------------------------------------------------------*/
1980 /*-----------------------------------------------------------------*/
1981 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
1982 {
1983   pCodeFlowLink *pcflowLink;
1984   
1985   pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
1986   
1987   pcflowLink->pcflow = pcflow;
1988   pcflowLink->bank_conflict = 0;
1989   
1990   return pcflowLink;
1991 }
1992
1993 /*-----------------------------------------------------------------*/
1994 /* newpCodeCSource - create a new pCode Source Symbol              */
1995 /*-----------------------------------------------------------------*/
1996
1997 pCode *newpCodeCSource(int ln, char *f, char *l)
1998 {
1999   
2000   pCodeCSource *pccs;
2001
2002   pccs = Safe_calloc(1,sizeof(pCodeCSource));
2003   
2004   pccs->pc.type = PC_CSOURCE;
2005   pccs->pc.prev = pccs->pc.next = NULL;
2006   pccs->pc.id = PCodeID();
2007   pccs->pc.pb = NULL;
2008   
2009   pccs->pc.destruct = genericDestruct;
2010   pccs->pc.print = genericPrint;
2011   
2012   pccs->line_number = ln;
2013   if(l)
2014     pccs->line = Safe_strdup(l);
2015   else
2016     pccs->line = NULL;
2017   
2018   if(f)
2019     pccs->file_name = Safe_strdup(f);
2020   else
2021     pccs->file_name = NULL;
2022   
2023   return ( (pCode *)pccs);
2024   
2025 }
2026 /*-----------------------------------------------------------------*/
2027 /* pCodeLabelDestruct - free memory used by a label.               */
2028 /*-----------------------------------------------------------------*/
2029 static void pCodeLabelDestruct(pCode *pc)
2030 {
2031   
2032   if(!pc)
2033     return;
2034   
2035   if((pc->type == PC_LABEL) && PCL(pc)->label)
2036     free(PCL(pc)->label);
2037   
2038   free(pc);
2039   
2040 }
2041
2042 pCode *newpCodeLabel(char *name, int key)
2043 {
2044   
2045   char *s = buffer;
2046   pCodeLabel *pcl;
2047
2048   pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2049   
2050   pcl->pc.type = PC_LABEL;
2051   pcl->pc.prev = pcl->pc.next = NULL;
2052   pcl->pc.id = PCodeID();
2053   //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2054   pcl->pc.pb = NULL;
2055   
2056   //  pcl->pc.analyze = genericAnalyze;
2057   pcl->pc.destruct = pCodeLabelDestruct;
2058   pcl->pc.print = pCodePrintLabel;
2059   
2060   pcl->key = key;
2061   
2062   pcl->label = NULL;
2063   if(key>0) {
2064     sprintf(s,"_%05d_DS_",key);
2065   } else
2066     s = name;
2067   
2068   if(s)
2069     pcl->label = Safe_strdup(s);
2070   
2071   //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2072   return ( (pCode *)pcl);
2073   
2074 }
2075
2076
2077 /*-----------------------------------------------------------------*/
2078 /* newpBlock - create and return a pointer to a new pBlock         */
2079 /*-----------------------------------------------------------------*/
2080 pBlock *newpBlock(void)
2081 {
2082   
2083   pBlock *PpB;
2084   
2085   PpB = Safe_calloc(1,sizeof(pBlock) );
2086   PpB->next = PpB->prev = NULL;
2087   
2088   PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2089   PpB->tregisters = NULL;
2090   PpB->visited = 0;
2091   PpB->FlowTree = NULL;
2092   
2093   return PpB;
2094   
2095 }
2096
2097 /*-----------------------------------------------------------------*/
2098 /* newpCodeChain - create a new chain of pCodes                    */
2099 /*-----------------------------------------------------------------*
2100 *
2101 *  This function will create a new pBlock and the pointer to the
2102 *  pCode that is passed in will be the first pCode in the block.
2103 *-----------------------------------------------------------------*/
2104
2105
2106 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2107 {
2108   
2109   pBlock *pB  = newpBlock();
2110   
2111   pB->pcHead  = pB->pcTail = pc;
2112   pB->cmemmap = cm;
2113   pB->dbName  = c;
2114   
2115   return pB;
2116 }
2117
2118 /*-----------------------------------------------------------------*/
2119 /* newpCodeOpLabel - Create a new label given the key              */
2120 /*  Note, a negative key means that the label is part of wild card */
2121 /*  (and hence a wild card label) used in the pCodePeep            */
2122 /*   optimizations).                                               */
2123 /*-----------------------------------------------------------------*/
2124
2125 pCodeOp *newpCodeOpLabel(char *name, int key)
2126 {
2127   char *s=NULL;
2128   static int label_key=-1;
2129   
2130   pCodeOp *pcop;
2131   
2132   pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2133   pcop->type = PO_LABEL;
2134   
2135   pcop->name = NULL;
2136   
2137   if(key>0)
2138     sprintf(s=buffer,"_%05d_DS_",key);
2139   else 
2140     s = name, key = label_key--;
2141   
2142   PCOLAB(pcop)->offset = 0;
2143   if(s)
2144     pcop->name = Safe_strdup(s);
2145   
2146   ((pCodeOpLabel *)pcop)->key = key;
2147   
2148   //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2149   return pcop;
2150 }
2151
2152 /*-----------------------------------------------------------------*/
2153 /*-----------------------------------------------------------------*/
2154 pCodeOp *newpCodeOpLit(int lit)
2155 {
2156   char *s = buffer;
2157   pCodeOp *pcop;
2158   
2159   
2160   pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2161   pcop->type = PO_LITERAL;
2162   
2163   pcop->name = NULL;
2164   if(lit>=0) {
2165     sprintf(s,"0x%02x",lit);
2166     if(s)
2167       pcop->name = Safe_strdup(s);
2168   }
2169   
2170   ((pCodeOpLit *)pcop)->lit = lit;
2171   
2172   return pcop;
2173 }
2174
2175 /*-----------------------------------------------------------------*/
2176 /*-----------------------------------------------------------------*/
2177 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2178 {
2179   pCodeOp *pcop;
2180   
2181   pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2182   pcop->type = PO_IMMEDIATE;
2183   if(name) {
2184     regs *r = NULL;
2185     pcop->name = Safe_strdup(name);
2186     
2187     if(!is_func) 
2188       r = dirregWithName(name);
2189     
2190     PCOI(pcop)->r = r;
2191     if(r) {
2192       //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2193       PCOI(pcop)->rIdx = r->rIdx;
2194     } else {
2195       //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2196       PCOI(pcop)->rIdx = -1;
2197     }
2198     //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2199   } else {
2200     pcop->name = NULL;
2201   }
2202   
2203   PCOI(pcop)->index = index;
2204   PCOI(pcop)->offset = offset;
2205   PCOI(pcop)->_const = code_space;
2206   PCOI(pcop)->_function = is_func;
2207   
2208   return pcop;
2209 }
2210
2211 /*-----------------------------------------------------------------*/
2212 /*-----------------------------------------------------------------*/
2213 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2214 {
2215   char *s = buffer;
2216   pCodeOp *pcop;
2217   
2218   
2219   if(!pcwb || !subtype) {
2220     fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2221     exit(1);
2222   }
2223   
2224   pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2225   pcop->type = PO_WILD;
2226   sprintf(s,"%%%d",id);
2227   pcop->name = Safe_strdup(s);
2228   
2229   PCOW(pcop)->id = id;
2230   PCOW(pcop)->pcwb = pcwb;
2231   PCOW(pcop)->subtype = subtype;
2232   PCOW(pcop)->matched = NULL;
2233   
2234   return pcop;
2235 }
2236 /*-----------------------------------------------------------------*/
2237 /* Find a symbol with matching name                                */
2238 /*-----------------------------------------------------------------*/
2239 static symbol *symFindWithName(memmap * map, const char *name)
2240 {
2241   symbol *sym;
2242   
2243   for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2244     if (sym->rname && (strcmp(sym->rname,name)==0))
2245       return sym;
2246   }
2247   return 0;
2248 }
2249
2250 /*-----------------------------------------------------------------*/
2251 /*-----------------------------------------------------------------*/
2252 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2253 {
2254   pCodeOp *pcop;
2255   struct regs *r = 0;
2256   
2257   pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2258   pcop->type = PO_GPR_BIT;
2259   
2260   PCORB(pcop)->bit = ibit;
2261   PCORB(pcop)->inBitSpace = inBitSpace;
2262   
2263   if (name) r = regFindWithName(name);
2264   if (!r) {
2265     // Register has not been allocated - check for symbol information
2266     symbol *sym;
2267     sym = symFindWithName(bit, name);
2268     if (!sym) sym = symFindWithName(sfrbit, name);
2269     if (!sym) sym = symFindWithName(sfr, name);
2270     if (sym) {
2271       r = allocNewDirReg(sym->etype,name);
2272     }
2273   }
2274   if (r) {
2275     pcop->name = NULL;
2276     PCOR(pcop)->r = r;
2277     PCOR(pcop)->rIdx = r->rIdx;
2278   } else {
2279     pcop->name = Safe_strdup(name);   
2280     PCOR(pcop)->r = NULL;
2281     PCOR(pcop)->rIdx = 0;
2282   }
2283   return pcop;
2284 }
2285
2286 /*-----------------------------------------------------------------*
2287 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2288 *
2289 * If rIdx >=0 then a specific register from the set of registers
2290 * will be selected. If rIdx <0, then a new register will be searched
2291 * for.
2292 *-----------------------------------------------------------------*/
2293
2294 pCodeOp *newpCodeOpReg(int rIdx)
2295 {
2296   pCodeOp *pcop;
2297   
2298   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2299   
2300   pcop->name = NULL;
2301   
2302   if(rIdx >= 0) {
2303     PCOR(pcop)->rIdx = rIdx;
2304     PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2305   } else {
2306     PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2307     
2308     if(PCOR(pcop)->r)
2309       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2310   }
2311   
2312   if(PCOR(pcop)->r)
2313     pcop->type = PCOR(pcop)->r->pc_type;
2314   
2315   return pcop;
2316 }
2317
2318 pCodeOp *newpCodeOpRegFromStr(char *name)
2319 {
2320   pCodeOp *pcop;
2321   
2322   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2323   PCOR(pcop)->r = allocRegByName(name, 1);
2324   PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2325   pcop->type = PCOR(pcop)->r->pc_type;
2326   pcop->name = PCOR(pcop)->r->name;
2327   
2328   return pcop;
2329 }
2330
2331 pCodeOp *newpCodeOpStr(char *name)
2332 {
2333   pCodeOp *pcop;
2334   
2335   pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2336   pcop->type = PO_STR;
2337   pcop->name = Safe_strdup(name);   
2338   
2339   PCOS(pcop)->isPublic = 0;
2340   
2341   return pcop;
2342 }
2343
2344
2345 /*-----------------------------------------------------------------*/
2346 /*-----------------------------------------------------------------*/
2347
2348 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2349 {
2350   pCodeOp *pcop;
2351   
2352   switch(type) {
2353   case PO_BIT:
2354   case PO_GPR_BIT:
2355     pcop = newpCodeOpBit(name, -1,0);
2356     break;
2357     
2358   case PO_LITERAL:
2359     pcop = newpCodeOpLit(-1);
2360     break;
2361     
2362   case PO_LABEL:
2363     pcop = newpCodeOpLabel(NULL,-1);
2364     break;
2365     
2366   case PO_GPR_TEMP:
2367     pcop = newpCodeOpReg(-1);
2368     break;
2369     
2370   case PO_GPR_POINTER:
2371   case PO_GPR_REGISTER:
2372     if(name)
2373       pcop = newpCodeOpRegFromStr(name);
2374     else
2375       pcop = newpCodeOpReg(-1);
2376     break;
2377     
2378   case PO_STR:
2379     pcop = newpCodeOpStr(name);
2380     break;
2381     
2382   default:
2383     pcop = Safe_calloc(1,sizeof(pCodeOp) );
2384     pcop->type = type;
2385     if(name)
2386       pcop->name = Safe_strdup(name);   
2387     else
2388       pcop->name = NULL;
2389   }
2390   
2391   return pcop;
2392 }
2393
2394 /*-----------------------------------------------------------------*/
2395 /*-----------------------------------------------------------------*/
2396 void pCodeConstString(char *name, char *value)
2397 {
2398   pBlock *pb;
2399   
2400   //  fprintf(stderr, " %s  %s  %s\n",__FUNCTION__,name,value);
2401   
2402   if(!name || !value)
2403     return;
2404   
2405   pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2406   
2407   addpBlock(pb);
2408   
2409   sprintf(buffer,"; %s = %s",name,value);
2410   
2411   addpCode2pBlock(pb,newpCodeCharP(buffer));
2412   addpCode2pBlock(pb,newpCodeLabel(name,-1));
2413   
2414   do {
2415     addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2416   }while (*value++);
2417   
2418   
2419 }
2420
2421 /*-----------------------------------------------------------------*/
2422 /*-----------------------------------------------------------------*/
2423 void pCodeReadCodeTable(void)
2424 {
2425   pBlock *pb;
2426   
2427   fprintf(stderr, " %s\n",__FUNCTION__);
2428   
2429   pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2430   
2431   addpBlock(pb);
2432   
2433   addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2434   addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2435   addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2436   addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2437   
2438   addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2439   addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2440   addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2441   addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2442   
2443   
2444 }
2445
2446 /*-----------------------------------------------------------------*/
2447 /* addpCode2pBlock - place the pCode into the pBlock linked list   */
2448 /*-----------------------------------------------------------------*/
2449 void addpCode2pBlock(pBlock *pb, pCode *pc)
2450 {
2451   
2452   if(!pc)
2453     return;
2454   
2455   if(!pb->pcHead) {
2456   /* If this is the first pcode to be added to a block that
2457   * was initialized with a NULL pcode, then go ahead and
2458     * make this pcode the head and tail */
2459     pb->pcHead  = pb->pcTail = pc;
2460   } else {
2461     //    if(pb->pcTail)
2462     pb->pcTail->next = pc;
2463     
2464     pc->prev = pb->pcTail;
2465     pc->pb = pb;
2466     
2467     pb->pcTail = pc;
2468   }
2469 }
2470
2471 /*-----------------------------------------------------------------*/
2472 /* addpBlock - place a pBlock into the pFile                       */
2473 /*-----------------------------------------------------------------*/
2474 void addpBlock(pBlock *pb)
2475 {
2476   // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2477   
2478   if(!the_pFile) {
2479     /* First time called, we'll pass through here. */
2480     //_ALLOC(the_pFile,sizeof(pFile));
2481     the_pFile = Safe_calloc(1,sizeof(pFile));
2482     the_pFile->pbHead = the_pFile->pbTail = pb;
2483     the_pFile->functions = NULL;
2484     return;
2485   }
2486   
2487   the_pFile->pbTail->next = pb;
2488   pb->prev = the_pFile->pbTail;
2489   pb->next = NULL;
2490   the_pFile->pbTail = pb;
2491 }
2492
2493 /*-----------------------------------------------------------------*/
2494 /* removepBlock - remove a pBlock from the pFile                   */
2495 /*-----------------------------------------------------------------*/
2496 void removepBlock(pBlock *pb)
2497 {
2498   pBlock *pbs;
2499   
2500   if(!the_pFile)
2501     return;
2502   
2503   
2504   //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2505   
2506   for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2507     if(pbs == pb) {
2508       
2509       if(pbs == the_pFile->pbHead)
2510         the_pFile->pbHead = pbs->next;
2511       
2512       if (pbs == the_pFile->pbTail) 
2513         the_pFile->pbTail = pbs->prev;
2514       
2515       if(pbs->next)
2516         pbs->next->prev = pbs->prev;
2517       
2518       if(pbs->prev)
2519         pbs->prev->next = pbs->next;
2520       
2521       return;
2522       
2523     }
2524   }
2525   
2526   fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2527   
2528 }
2529
2530 /*-----------------------------------------------------------------*/
2531 /* printpCode - write the contents of a pCode to a file            */
2532 /*-----------------------------------------------------------------*/
2533 void printpCode(FILE *of, pCode *pc)
2534 {
2535   
2536   if(!pc || !of)
2537     return;
2538   
2539   if(pc->print) {
2540     pc->print(of,pc);
2541     return;
2542   }
2543   
2544   fprintf(of,"warning - unable to print pCode\n");
2545 }
2546
2547 /*-----------------------------------------------------------------*/
2548 /* printpBlock - write the contents of a pBlock to a file          */
2549 /*-----------------------------------------------------------------*/
2550 void printpBlock(FILE *of, pBlock *pb)
2551 {
2552   pCode *pc;
2553   
2554   if(!pb)
2555     return;
2556   
2557   if(!of)
2558     of = stderr;
2559   
2560   for(pc = pb->pcHead; pc; pc = pc->next)
2561     printpCode(of,pc);
2562   
2563 }
2564
2565 /*-----------------------------------------------------------------*/
2566 /*                                                                 */
2567 /*       pCode processing                                          */
2568 /*                                                                 */
2569 /*                                                                 */
2570 /*                                                                 */
2571 /*-----------------------------------------------------------------*/
2572
2573 void unlinkpCode(pCode *pc)
2574 {
2575   
2576   
2577   if(pc) {
2578 #ifdef PCODE_DEBUG
2579     fprintf(stderr,"Unlinking: ");
2580     printpCode(stderr, pc);
2581 #endif
2582     if(pc->prev) 
2583       pc->prev->next = pc->next;
2584     if(pc->next)
2585       pc->next->prev = pc->prev;
2586     
2587     pc->prev = pc->next = NULL;
2588   }
2589 }
2590
2591 /*-----------------------------------------------------------------*/
2592 /*-----------------------------------------------------------------*/
2593
2594 static void genericDestruct(pCode *pc)
2595 {
2596   
2597   unlinkpCode(pc);
2598   
2599   if(isPCI(pc)) {
2600   /* For instructions, tell the register (if there's one used)
2601     * that it's no longer needed */
2602     regs *reg = getRegFromInstruction(pc);
2603     if(reg)
2604       deleteSetItem (&(reg->reglives.usedpCodes),pc);
2605   }
2606   
2607   /* Instead of deleting the memory used by this pCode, mark
2608   * the object as bad so that if there's a pointer to this pCode
2609   * dangling around somewhere then (hopefully) when the type is
2610   * checked we'll catch it.
2611   */
2612   
2613   pc->type = PC_BAD;
2614   
2615   addpCode2pBlock(pb_dead_pcodes, pc);
2616   
2617   //free(pc);
2618   
2619 }
2620
2621
2622 /*-----------------------------------------------------------------*/
2623 /*  Copies the pCodeInstruction flow pointer from source pCode     */
2624 /*-----------------------------------------------------------------*/
2625 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2626   pCode *p;
2627   pCodeFlow *pcflow = 0;
2628   for (p=pcs; p; p=p->prev) {
2629     if (isPCI(p)) {
2630       pcflow = PCI(p)->pcflow;
2631       break;
2632     }
2633     if (isPCF(p)) {
2634       pcflow = (pCodeFlow*)p;
2635       break;
2636     }
2637   }
2638   PCI(pcd)->pcflow = pcflow;
2639 }
2640
2641 /*-----------------------------------------------------------------*/
2642 /*  pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2643 /*                     into the pCode chain containing pc1         */
2644 /*-----------------------------------------------------------------*/
2645 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2646 {
2647   
2648   if(!pc1 || !pc2)
2649     return;
2650   
2651   pc2->next = pc1->next;
2652   if(pc1->next)
2653     pc1->next->prev = pc2;
2654   
2655   pc2->pb = pc1->pb;
2656   pc2->prev = pc1;
2657   pc1->next = pc2;
2658   
2659   /* If this is an instrution type propogate the flow */
2660   if (isPCI(pc2))
2661     CopyFlow(PCI(pc2),pc1);
2662 }
2663
2664 /*------------------------------------------------------------------*/
2665 /*  pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2666 /*                      into the pCode chain containing pc1         */
2667 /*------------------------------------------------------------------*/
2668 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2669 {
2670   
2671   if(!pc1 || !pc2)
2672     return;
2673   
2674   pc2->prev = pc1->prev;
2675   if(pc1->prev)
2676     pc1->prev->next = pc2;
2677   
2678   pc2->pb = pc1->pb;
2679   pc2->next = pc1;
2680   pc1->prev = pc2;
2681   
2682   /* If this is an instrution type propogate the flow */
2683   if (isPCI(pc2))
2684     CopyFlow(PCI(pc2),pc1);
2685 }
2686
2687 /*-----------------------------------------------------------------*/
2688 /* pCodeOpCopy - copy a pcode operator                             */
2689 /*-----------------------------------------------------------------*/
2690 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2691 {
2692   pCodeOp *pcopnew=NULL;
2693   
2694   if(!pcop)
2695     return NULL;
2696   
2697   switch(pcop->type) { 
2698   case PO_CRY:
2699   case PO_BIT:
2700     //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2701     pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2702     PCORB(pcopnew)->bit = PCORB(pcop)->bit;
2703     PCORB(pcopnew)->inBitSpace = PCORB(pcop)->inBitSpace;
2704     
2705     break;
2706     
2707   case PO_WILD:
2708     /* Here we expand the wild card into the appropriate type: */
2709     /* By recursively calling pCodeOpCopy */
2710     //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2711     if(PCOW(pcop)->matched)
2712       pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2713     else {
2714       // Probably a label
2715       pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2716       pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2717       //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2718     }
2719     
2720     return pcopnew;
2721     break;
2722     
2723   case PO_LABEL:
2724     //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2725     pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2726     PCOLAB(pcopnew)->key =  PCOLAB(pcop)->key;
2727     break;
2728     
2729   case PO_IMMEDIATE:
2730     pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2731     PCOI(pcopnew)->index = PCOI(pcop)->index;
2732     PCOI(pcopnew)->offset = PCOI(pcop)->offset;
2733     PCOI(pcopnew)->_const = PCOI(pcop)->_const;
2734     PCOI(pcopnew)->_function = PCOI(pcop)->_function;
2735     break;
2736     
2737   case PO_LITERAL:
2738     //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2739     pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2740     PCOL(pcopnew)->lit = PCOL(pcop)->lit;
2741     break;
2742     
2743   case PO_GPR_BIT:
2744     
2745     pcopnew = newpCodeOpBit(pcop->name, PCORB(pcop)->bit,PCORB(pcop)->inBitSpace);
2746     PCOR(pcopnew)->r = PCOR(pcop)->r;
2747     PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2748     DFPRINTF((stderr," pCodeOpCopy Bit -register index\n"));
2749     return pcopnew;
2750     break;
2751     
2752   case PO_GPR_POINTER:
2753   case PO_GPR_REGISTER:
2754   case PO_GPR_TEMP:
2755   case PO_FSR:
2756   case PO_INDF:
2757     //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2758     pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2759     PCOR(pcopnew)->r = PCOR(pcop)->r;
2760     PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2761     PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2762     DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2763     break;
2764     
2765   case PO_DIR:
2766     //fprintf(stderr,"pCodeOpCopy PO_DIR\n");
2767     pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2768     PCOR(pcopnew)->r = PCOR(pcop)->r;
2769     PCOR(pcopnew)->rIdx = PCOR(pcop)->rIdx;
2770     PCOR(pcopnew)->instance = PCOR(pcop)->instance;
2771     break;
2772   case PO_STATUS:
2773     DFPRINTF((stderr,"pCodeOpCopy PO_STATUS\n"));
2774   case PO_SFR_REGISTER:
2775   case PO_STR:
2776   case PO_NONE:
2777   case PO_W:
2778   case PO_INTCON:
2779   case PO_PCL:
2780   case PO_PCLATH:
2781     
2782     //DFPRINTF((stderr,"pCodeOpCopy register type %d\n", pcop->type));
2783     pcopnew = Safe_calloc(1,sizeof(pCodeOp) );
2784     
2785   }
2786   
2787   pcopnew->type = pcop->type;
2788   if(pcop->name)
2789     pcopnew->name = Safe_strdup(pcop->name);
2790   else
2791     pcopnew->name = NULL;
2792   
2793   return pcopnew;
2794 }
2795
2796 /*-----------------------------------------------------------------*/
2797 /* popCopyReg - copy a pcode operator                              */
2798 /*-----------------------------------------------------------------*/
2799 pCodeOp *popCopyReg(pCodeOpReg *pc)
2800 {
2801   pCodeOpReg *pcor;
2802   
2803   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2804   pcor->pcop.type = pc->pcop.type;
2805   if(pc->pcop.name) {
2806     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2807       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2808   } else
2809     pcor->pcop.name = NULL;
2810   
2811   pcor->r = pc->r;
2812   pcor->rIdx = pc->rIdx;
2813   pcor->r->wasUsed=1;
2814   
2815   //DEBUGpic14_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2816   
2817   return PCOP(pcor);
2818 }
2819
2820 /*-----------------------------------------------------------------*/
2821 /* pCodeInstructionCopy - copy a pCodeInstructionCopy              */
2822 /*-----------------------------------------------------------------*/
2823 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2824 {
2825   pCodeInstruction *new_pci;
2826   
2827   if(invert)
2828     new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2829   else
2830     new_pci = PCI(newpCode(pci->op,pci->pcop));
2831   
2832   new_pci->pc.pb = pci->pc.pb;
2833   new_pci->from = pci->from;
2834   new_pci->to   = pci->to;
2835   new_pci->label = pci->label;
2836   new_pci->pcflow = pci->pcflow;
2837   
2838   return PCODE(new_pci);
2839 }
2840
2841 /*-----------------------------------------------------------------*/
2842 /*-----------------------------------------------------------------*/
2843 void pCodeDeleteChain(pCode *f,pCode *t)
2844 {
2845   pCode *pc;
2846   
2847   while(f && f!=t) {
2848     DFPRINTF((stderr,"delete pCode:\n"));
2849     pc = f->next;
2850     //f->print(stderr,f);
2851     //f->delete(f);  this dumps core...
2852     f = pc;
2853   }
2854 }
2855
2856 /*-----------------------------------------------------------------*/
2857 /*-----------------------------------------------------------------*/
2858 void pBlockRegs(FILE *of, pBlock *pb)
2859 {
2860   
2861   regs  *r;
2862   
2863   r = setFirstItem(pb->tregisters);
2864   while (r) {
2865     r = setNextItem(pb->tregisters);
2866   }
2867 }
2868
2869
2870 /*-----------------------------------------------------------------*/
2871 /*-----------------------------------------------------------------*/
2872 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2873 {
2874   regs *r;
2875   static char b[50];
2876   char *s;
2877   int use_buffer = 1;    // copy the string to the passed buffer pointer
2878   
2879   if(!buffer) {
2880     buffer = b;
2881     size = sizeof(b);
2882     use_buffer = 0;     // Don't bother copying the string to the buffer.
2883   } 
2884   
2885   if(pcop) {
2886     switch(pcop->type) {
2887     case PO_INDF:
2888     case PO_FSR:
2889       if(use_buffer) {
2890         SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2891         return buffer;
2892       }
2893       //return PCOR(pcop)->r->name;
2894       return pcop->name;
2895       break;
2896     case PO_GPR_TEMP:
2897       if (PCOR(pcop)->r->type == REG_STK)
2898         r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
2899       else
2900         r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
2901       
2902       if(use_buffer) {
2903         SAFE_snprintf(&buffer,&size,"%s",r->name);
2904         return buffer;
2905       }
2906       
2907       return r->name;
2908       
2909       
2910     case PO_IMMEDIATE:
2911       s = buffer;
2912       
2913       if(PCOI(pcop)->_const) {
2914         
2915         if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
2916           switch(PCOI(pcop)->offset) {
2917           case 0:
2918             SAFE_snprintf(&s,&size,"low %s",pcop->name);
2919             break;
2920           case 1:
2921             SAFE_snprintf(&s,&size,"high %s",pcop->name);
2922             break;
2923           default:
2924             SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
2925                           pcop->name,
2926                           PCOI(pcop)->index,
2927                           8 * PCOI(pcop)->offset );
2928           }
2929         } else
2930           SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
2931       } else {
2932         
2933         if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
2934           SAFE_snprintf(&s,&size,"(%s + %d)",
2935                         pcop->name,
2936                         PCOI(pcop)->index );
2937         } else {
2938           switch(PCOI(pcop)->offset) {
2939           case 0:
2940             SAFE_snprintf(&s,&size,"%s",pcop->name);
2941             break;
2942           case 1:
2943             SAFE_snprintf(&s,&size,"high %s",pcop->name);
2944             break;
2945           default:
2946             SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
2947           }
2948         }
2949       }
2950       
2951       return buffer;
2952       
2953     case PO_DIR:
2954       s = buffer;
2955       //size = sizeof(buffer);
2956       if( PCOR(pcop)->instance) {
2957         SAFE_snprintf(&s,&size,"(%s + %d)",
2958                       pcop->name,
2959                       PCOR(pcop)->instance );
2960         //fprintf(stderr,"PO_DIR %s\n",buffer);
2961       } else
2962         SAFE_snprintf(&s,&size,"%s",pcop->name);
2963       return buffer;
2964             
2965     case PO_LABEL:
2966       s = buffer;
2967       if  (pcop->name) {
2968         if(PCOLAB(pcop)->offset == 1)
2969           SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
2970         else
2971           SAFE_snprintf(&s,&size,"%s",pcop->name);
2972       }
2973       return buffer;
2974
2975     case PO_GPR_BIT:
2976       if(PCOR(pcop)->r) {
2977         if(use_buffer) {
2978           SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
2979           return buffer;
2980         }
2981         return PCOR(pcop)->r->name;
2982       }
2983
2984       /* fall through to the default case */
2985     default:
2986       if(pcop->name) {
2987         if(use_buffer) {
2988           SAFE_snprintf(&buffer,&size,"%s",pcop->name);
2989           return buffer;
2990         }
2991         return pcop->name;
2992       }
2993     }
2994   }
2995
2996   printf("PIC port internal warning: (%s:%d) %s not found\n",
2997          __FUNCTION__,
2998          __LINE__,
2999          pCodeOpType(pcop));
3000
3001   return "NO operand";
3002   
3003 }
3004
3005 /*-----------------------------------------------------------------*/
3006 /*-----------------------------------------------------------------*/
3007 static char *get_op_from_instruction( pCodeInstruction *pcc)
3008 {
3009
3010   if(pcc)
3011     return get_op(pcc->pcop,NULL,0);
3012
3013   return ("ERROR Null: get_op_from_instruction");
3014
3015 }
3016
3017 /*-----------------------------------------------------------------*/
3018 /*-----------------------------------------------------------------*/
3019 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3020 {
3021   fprintf(of,"pcodeopprint- not implemented\n");
3022 }
3023
3024 /*-----------------------------------------------------------------*/
3025 /*-----------------------------------------------------------------*/
3026 char *pCode2str(char *str, size_t size, pCode *pc)
3027 {
3028   char *s = str;
3029   
3030   switch(pc->type) {
3031     
3032   case PC_OPCODE:
3033     
3034     SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3035     
3036     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3037       
3038       if(PCI(pc)->isBitInst) {
3039   if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3040     char *name = PCI(pc)->pcop->name;
3041     if (!name) 
3042       name = PCOR(PCI(pc)->pcop)->r->name;
3043     if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3044       SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3045     else
3046       SAFE_snprintf(&s,&size,"%s,%d", name, 
3047         (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3048   } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3049     SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3050   }else
3051     SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3052   //PCI(pc)->pcop->t.bit );
3053       } else {
3054         
3055   if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3056     if( PCI(pc)->num_ops == 2)
3057       SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3058     else
3059       SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3060           
3061   }else {
3062     SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3063           
3064     if( PCI(pc)->num_ops == 2)
3065       SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3066   }
3067       }
3068       
3069     }
3070     break;
3071     
3072   case PC_COMMENT:
3073     /* assuming that comment ends with a \n */
3074     SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3075     break;
3076     
3077   case PC_INLINE:
3078     /* assuming that inline code ends with a \n */
3079     SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3080     break;
3081     
3082   case PC_LABEL:
3083     SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3084     break;
3085   case PC_FUNCTION:
3086     SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3087     break;
3088   case PC_WILD:
3089     SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3090     break;
3091   case PC_FLOW:
3092     SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3093     break;
3094   case PC_CSOURCE:
3095     SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3096     break;
3097     
3098   case PC_BAD:
3099     SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3100   }
3101   
3102   return str;
3103   
3104 }
3105
3106 /*-----------------------------------------------------------------*/
3107 /* genericPrint - the contents of a pCode to a file                */
3108 /*-----------------------------------------------------------------*/
3109 static void genericPrint(FILE *of, pCode *pc)
3110 {
3111   
3112   if(!pc || !of)
3113     return;
3114   
3115   switch(pc->type) {
3116   case PC_COMMENT:
3117     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3118     break;
3119     
3120   case PC_INLINE:
3121     fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3122     break;
3123     
3124   case PC_OPCODE:
3125     // If the opcode has a label, print that first
3126     {
3127       pBranch *pbl = PCI(pc)->label;
3128       while(pbl && pbl->pc) {
3129         if(pbl->pc->type == PC_LABEL)
3130           pCodePrintLabel(of, pbl->pc);
3131         pbl = pbl->next;
3132       }
3133     }
3134     
3135     if(PCI(pc)->cline) 
3136       genericPrint(of,PCODE(PCI(pc)->cline));
3137     
3138     {
3139       char str[256];
3140       
3141       pCode2str(str, 256, pc);
3142       
3143       fprintf(of,"%s",str);
3144       
3145       /* Debug */
3146       if(debug_verbose) {
3147         fprintf(of, "\t;id=%u,key=%03x",pc->id,pc->seq);
3148         if(PCI(pc)->pcflow)
3149           fprintf(of,",flow seq=%03x",PCI(pc)->pcflow->pc.seq);
3150       }
3151     }
3152 #if 0
3153     {
3154       pBranch *dpb = pc->to;   // debug
3155       while(dpb) {
3156         switch ( dpb->pc->type) {
3157         case PC_OPCODE:
3158           fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3159           break;
3160         case PC_LABEL:
3161           fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3162           break;
3163         case PC_FUNCTION:
3164           fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3165           break;
3166         case PC_FLOW:
3167           fprintf(of, "\t;flow");
3168           break;
3169         case PC_COMMENT:
3170         case PC_WILD:
3171           break;
3172         }
3173         dpb = dpb->next;
3174       }
3175     }
3176 #endif
3177     fprintf(of,"\n");
3178     break;
3179     
3180   case PC_WILD:
3181     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3182     if(PCW(pc)->pci.label)
3183       pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3184     
3185     if(PCW(pc)->operand) {
3186       fprintf(of,";\toperand  ");
3187       pCodeOpPrint(of,PCW(pc)->operand );
3188     }
3189     break;
3190     
3191   case PC_FLOW:
3192     if(debug_verbose) {
3193       fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3194       if(PCFL(pc)->ancestor)
3195         fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3196       fprintf(of,"\n");
3197       
3198     }
3199     break;
3200     
3201   case PC_CSOURCE:
3202     fprintf(of,";#CSRC\t%s %d\n;  %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3203     break;
3204   case PC_LABEL:
3205   default:
3206     fprintf(of,"unknown pCode type %d\n",pc->type);
3207   }
3208   
3209 }
3210
3211 /*-----------------------------------------------------------------*/
3212 /* pCodePrintFunction - prints function begin/end                  */
3213 /*-----------------------------------------------------------------*/
3214
3215 static void pCodePrintFunction(FILE *of, pCode *pc)
3216 {
3217   
3218   if(!pc || !of)
3219     return;
3220   
3221   if( ((pCodeFunction *)pc)->modname) 
3222     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3223   
3224   if(PCF(pc)->fname) {
3225     pBranch *exits = PCF(pc)->to;
3226     int i=0;
3227     fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3228     while(exits) {
3229       i++;
3230       exits = exits->next;
3231     }
3232     //if(i) i--;
3233     fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3234     
3235   }else {
3236     if((PCF(pc)->from && 
3237       PCF(pc)->from->pc->type == PC_FUNCTION &&
3238       PCF(PCF(pc)->from->pc)->fname) )
3239       fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3240     else
3241       fprintf(of,"; exit point [can't find entry point]\n");
3242   }
3243 }
3244 /*-----------------------------------------------------------------*/
3245 /* pCodePrintLabel - prints label                                  */
3246 /*-----------------------------------------------------------------*/
3247
3248 static void pCodePrintLabel(FILE *of, pCode *pc)
3249 {
3250   
3251   if(!pc || !of)
3252     return;
3253   
3254   if(PCL(pc)->label) 
3255     fprintf(of,"%s\n",PCL(pc)->label);
3256   else if (PCL(pc)->key >=0) 
3257     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3258   else
3259     fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3260   
3261 }
3262 /*-----------------------------------------------------------------*/
3263 /* unlinkpCodeFromBranch - Search for a label in a pBranch and     */
3264 /*                         remove it if it is found.               */
3265 /*-----------------------------------------------------------------*/
3266 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3267 {
3268   pBranch *b, *bprev;
3269   
3270   
3271   bprev = NULL;
3272   
3273   if(pcl->type == PC_OPCODE)
3274     b = PCI(pcl)->label;
3275   else {
3276     fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3277     exit(1);
3278     
3279   }
3280   
3281   //fprintf (stderr, "%s \n",__FUNCTION__);
3282   //pcl->print(stderr,pcl);
3283   //pc->print(stderr,pc);
3284   while(b) {
3285     if(b->pc == pc) {
3286       //fprintf (stderr, "found label\n");
3287       
3288       /* Found a label */
3289       if(bprev) {
3290         bprev->next = b->next;  /* Not first pCode in chain */
3291         free(b);
3292       } else {
3293         pc->destruct(pc);
3294         PCI(pcl)->label = b->next;   /* First pCode in chain */
3295         free(b);
3296       }
3297       return;  /* A label can't occur more than once */
3298     }
3299     bprev = b;
3300     b = b->next;
3301   }
3302   
3303 }
3304
3305 /*-----------------------------------------------------------------*/
3306 /*-----------------------------------------------------------------*/
3307 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3308 {
3309   pBranch *b;
3310   
3311   if(!h)
3312     return n;
3313   
3314   if(h == n)
3315     return n;
3316   
3317   b = h;
3318   while(b->next)
3319     b = b->next;
3320   
3321   b->next = n;
3322   
3323   return h;
3324   
3325 }  
3326 /*-----------------------------------------------------------------*/
3327 /* pBranchLink - given two pcodes, this function will link them    */
3328 /*               together through their pBranches                  */
3329 /*-----------------------------------------------------------------*/
3330 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3331 {
3332   pBranch *b;
3333   
3334   // Declare a new branch object for the 'from' pCode.
3335   
3336   //_ALLOC(b,sizeof(pBranch));
3337   b = Safe_calloc(1,sizeof(pBranch));
3338   b->pc = PCODE(t);             // The link to the 'to' pCode.
3339   b->next = NULL;
3340   
3341   f->to = pBranchAppend(f->to,b);
3342   
3343   // Now do the same for the 'to' pCode.
3344   
3345   //_ALLOC(b,sizeof(pBranch));
3346   b = Safe_calloc(1,sizeof(pBranch));
3347   b->pc = PCODE(f);
3348   b->next = NULL;
3349   
3350   t->from = pBranchAppend(t->from,b);
3351   
3352 }
3353
3354 #if 0
3355 /*-----------------------------------------------------------------*/
3356 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3357 /*               a pCode                                           */
3358 /*-----------------------------------------------------------------*/
3359 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3360 {
3361   while(pb) {
3362     
3363     if(pb->pc == pc)
3364       return pb;
3365     
3366     pb = pb->next;
3367   }
3368   
3369   return NULL;
3370 }
3371
3372 /*-----------------------------------------------------------------*/
3373 /* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
3374 /*-----------------------------------------------------------------*/
3375 static void pCodeUnlink(pCode *pc)
3376 {
3377   pBranch *pb1,*pb2;
3378   pCode *pc1;
3379   
3380   if(!pc->prev || !pc->next) {
3381     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3382     exit(1);
3383   }
3384   
3385   /* first remove the pCode from the chain */
3386   pc->prev->next = pc->next;
3387   pc->next->prev = pc->prev;
3388   
3389   /* Now for the hard part... */
3390   
3391   /* Remove the branches */
3392   
3393   pb1 = pc->from;
3394   while(pb1) {
3395   pc1 = pb1->pc;    /* Get the pCode that branches to the
3396   * one we're unlinking */
3397   
3398   /* search for the link back to this pCode (the one we're
3399   * unlinking) */
3400   if(pb2 = pBranchFind(pc1->to,pc)) {
3401     pb2->pc = pc->to->pc;  // make the replacement
3402     
3403                  /* if the pCode we're unlinking contains multiple 'to'
3404                  * branches (e.g. this a skip instruction) then we need
3405     * to copy these extra branches to the chain. */
3406     if(pc->to->next)
3407       pBranchAppend(pb2, pc->to->next);
3408   }
3409
3410   pb1 = pb1->next;
3411   }
3412   
3413   
3414 }
3415 #endif
3416 /*-----------------------------------------------------------------*/
3417 /*-----------------------------------------------------------------*/
3418 #if 0
3419 static void genericAnalyze(pCode *pc)
3420 {
3421   switch(pc->type) {
3422   case PC_WILD:
3423   case PC_COMMENT:
3424     return;
3425   case PC_LABEL:
3426   case PC_FUNCTION:
3427   case PC_OPCODE:
3428     {
3429       // Go through the pCodes that are in pCode chain and link
3430       // them together through the pBranches. Note, the pCodes
3431       // are linked together as a contiguous stream like the 
3432       // assembly source code lines. The linking here mimics this
3433       // except that comments are not linked in.
3434       // 
3435       pCode *npc = pc->next;
3436       while(npc) {
3437         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3438           pBranchLink(pc,npc);
3439           return;
3440         } else
3441           npc = npc->next;
3442       }
3443       /* reached the end of the pcode chain without finding
3444       * an instruction we could link to. */
3445     }
3446     break;
3447   case PC_FLOW:
3448     fprintf(stderr,"analyze PC_FLOW\n");
3449     
3450     return;
3451   case PC_BAD:
3452     fprintf(stderr,";A bad pCode is being used\n");
3453     
3454   }
3455 }
3456 #endif
3457
3458 /*-----------------------------------------------------------------*/
3459 /*-----------------------------------------------------------------*/
3460 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3461 {
3462   pBranch *pbr;
3463   
3464   if(pc->type == PC_LABEL) {
3465     if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
3466       return TRUE;
3467   }
3468   if(pc->type == PC_OPCODE) {
3469     pbr = PCI(pc)->label;
3470     while(pbr) {
3471       if(pbr->pc->type == PC_LABEL) {
3472         if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
3473           return TRUE;
3474       }
3475       pbr = pbr->next;
3476     }
3477   }
3478   
3479   return FALSE;
3480 }
3481
3482 /*-----------------------------------------------------------------*/
3483 /*-----------------------------------------------------------------*/
3484 int checkLabel(pCode *pc)
3485 {
3486   pBranch *pbr;
3487   
3488   if(pc && isPCI(pc)) {
3489     pbr = PCI(pc)->label;
3490     while(pbr) {
3491       if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3492         return TRUE;
3493       
3494       pbr = pbr->next;
3495     }
3496   }
3497   
3498   return FALSE;
3499 }
3500
3501 /*-----------------------------------------------------------------*/
3502 /* findLabelinpBlock - Search the pCode for a particular label     */
3503 /*-----------------------------------------------------------------*/
3504 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3505 {
3506   pCode  *pc;
3507   
3508   if(!pb)
3509     return NULL;
3510   
3511   for(pc = pb->pcHead; pc; pc = pc->next) 
3512     if(compareLabel(pc,pcop_label))
3513       return pc;
3514     
3515     return NULL;
3516 }
3517
3518 /*-----------------------------------------------------------------*/
3519 /* findLabel - Search the pCode for a particular label             */
3520 /*-----------------------------------------------------------------*/
3521 pCode * findLabel(pCodeOpLabel *pcop_label)
3522 {
3523   pBlock *pb;
3524   pCode  *pc;
3525   
3526   if(!the_pFile)
3527     return NULL;
3528   
3529   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3530     if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3531       return pc;
3532   }
3533   
3534   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
3535   return NULL;
3536 }
3537
3538 /*-----------------------------------------------------------------*/
3539 /* findNextpCode - given a pCode, find the next of type 'pct'      */
3540 /*                 in the linked list                              */
3541 /*-----------------------------------------------------------------*/
3542 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3543 {
3544   
3545   while(pc) {
3546     if(pc->type == pct)
3547       return pc;
3548     
3549     pc = pc->next;
3550   }
3551   
3552   return NULL;
3553 }
3554
3555 /*-----------------------------------------------------------------*/
3556 /* findPrevpCode - given a pCode, find the previous of type 'pct'  */
3557 /*                 in the linked list                              */
3558 /*-----------------------------------------------------------------*/
3559 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3560 {
3561   
3562   while(pc) {
3563     if(pc->type == pct)
3564       return pc;
3565     
3566     pc = pc->prev;
3567   }
3568   
3569   return NULL;
3570 }
3571 /*-----------------------------------------------------------------*/
3572 /* findNextInstruction - given a pCode, find the next instruction  */
3573 /*                       in the linked list                        */
3574 /*-----------------------------------------------------------------*/
3575 pCode * findNextInstruction(pCode *pci)
3576 {
3577   pCode *pc = pci;
3578   
3579   while(pc) {
3580     if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
3581       return pc;
3582     
3583 #ifdef PCODE_DEBUG
3584     fprintf(stderr,"findNextInstruction:  ");
3585     printpCode(stderr, pc);
3586 #endif
3587     pc = pc->next;
3588   }
3589   
3590   //fprintf(stderr,"Couldn't find instruction\n");
3591   return NULL;
3592 }
3593
3594 /*-----------------------------------------------------------------*/
3595 /* findNextInstruction - given a pCode, find the next instruction  */
3596 /*                       in the linked list                        */
3597 /*-----------------------------------------------------------------*/
3598 pCode * findPrevInstruction(pCode *pci)
3599 {
3600   return findPrevpCode(pci, PC_OPCODE);
3601 }
3602
3603 /*-----------------------------------------------------------------*/
3604 /* findFunctionEnd - given a pCode find the end of the function    */
3605 /*                   that contains it                              */
3606 /*-----------------------------------------------------------------*/
3607 pCode * findFunctionEnd(pCode *pc)
3608 {
3609   
3610   while(pc) {
3611     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
3612       return pc;
3613     
3614     pc = pc->next;
3615   }
3616   
3617   fprintf(stderr,"Couldn't find function end\n");
3618   return NULL;
3619 }
3620
3621 #if 0
3622 /*-----------------------------------------------------------------*/
3623 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
3624 /*                instruction with which it is associated.         */
3625 /*-----------------------------------------------------------------*/
3626 static void AnalyzeLabel(pCode *pc)
3627 {
3628   
3629   pCodeUnlink(pc);
3630   
3631 }
3632 #endif
3633
3634 #if 0
3635 static void AnalyzeGOTO(pCode *pc)
3636 {
3637   
3638   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3639   
3640 }
3641
3642 static void AnalyzeSKIP(pCode *pc)
3643 {
3644   
3645   pBranchLink(pc,findNextInstruction(pc->next));
3646   pBranchLink(pc,findNextInstruction(pc->next->next));
3647   
3648 }
3649
3650 static void AnalyzeRETURN(pCode *pc)
3651 {
3652   
3653   //  branch_link(pc,findFunctionEnd(pc->next));
3654   
3655 }
3656
3657 #endif
3658
3659 /*-----------------------------------------------------------------*/
3660 /*-----------------------------------------------------------------*/
3661 regs * getRegFromInstruction(pCode *pc)
3662 {
3663   
3664   if(!pc                   || 
3665     !isPCI(pc)            ||
3666     !PCI(pc)->pcop        ||
3667     PCI(pc)->num_ops == 0 )
3668     return NULL;
3669   
3670   switch(PCI(pc)->pcop->type) {
3671   case PO_INDF:
3672   case PO_FSR:
3673     return PCOR(PCI(pc)->pcop)->r;
3674     
3675     //    return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
3676     
3677   case PO_BIT:
3678   case PO_GPR_TEMP:
3679     //fprintf(stderr, "getRegFromInstruction - bit or temp\n");
3680     return PCOR(PCI(pc)->pcop)->r;
3681     
3682   case PO_IMMEDIATE:
3683     if(PCOI(PCI(pc)->pcop)->r)
3684       return (PCOI(PCI(pc)->pcop)->r);
3685     
3686     //fprintf(stderr, "getRegFromInstruction - immediate\n");
3687     return dirregWithName(PCI(pc)->pcop->name);
3688     //return NULL; // PCOR(PCI(pc)->pcop)->r;
3689     
3690   case PO_GPR_BIT:
3691     return PCOR(PCI(pc)->pcop)->r;
3692     
3693   case PO_GPR_REGISTER:
3694   case PO_DIR:
3695     //fprintf(stderr, "getRegFromInstruction - dir\n");
3696     return PCOR(PCI(pc)->pcop)->r;
3697   case PO_LITERAL:
3698     //fprintf(stderr, "getRegFromInstruction - literal\n");
3699     break;
3700     
3701   default:
3702     //fprintf(stderr, "getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
3703     //genericPrint(stderr, pc);
3704     break;
3705   }
3706   
3707   return NULL;
3708   
3709 }
3710
3711 /*-----------------------------------------------------------------*/
3712 /*-----------------------------------------------------------------*/
3713
3714 void AnalyzepBlock(pBlock *pb)
3715 {
3716   pCode *pc;
3717   
3718   if(!pb)
3719     return;
3720   
3721     /* Find all of the registers used in this pBlock 
3722     * by looking at each instruction and examining it's
3723     * operands
3724   */
3725   for(pc = pb->pcHead; pc; pc = pc->next) {
3726     
3727     /* Is this an instruction with operands? */
3728     if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3729       
3730       if((PCI(pc)->pcop->type == PO_GPR_TEMP) 
3731         || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3732         
3733         /* Loop through all of the registers declared so far in
3734         this block and see if we find this one there */
3735         
3736         regs *r = setFirstItem(pb->tregisters);
3737         
3738         while(r) {
3739           if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3740             PCOR(PCI(pc)->pcop)->r = r;
3741             break;
3742           }
3743           r = setNextItem(pb->tregisters);
3744         }
3745         
3746         if(!r) {
3747           /* register wasn't found */
3748           //r = Safe_calloc(1, sizeof(regs));
3749           //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3750           //addSet(&pb->tregisters, r);
3751           addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3752           //PCOR(PCI(pc)->pcop)->r = r;
3753           //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3754           }/* else 
3755            fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3756         */
3757       }
3758       if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3759         if(PCOR(PCI(pc)->pcop)->r) {
3760           pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3761           DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3762         } else {
3763           if(PCI(pc)->pcop->name)
3764             fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3765           else
3766             fprintf(stderr,"ERROR: NULL register\n");
3767         }
3768       }
3769     }
3770     
3771     
3772   }
3773 }
3774
3775 /*-----------------------------------------------------------------*/
3776 /* */
3777 /*-----------------------------------------------------------------*/
3778 void InsertpFlow(pCode *pc, pCode **pflow)
3779 {
3780   if(*pflow)
3781     PCFL(*pflow)->end = pc;
3782   
3783   if(!pc || !pc->next)
3784     return;
3785   
3786   *pflow = newpCodeFlow();
3787   pCodeInsertAfter(pc, *pflow);
3788 }
3789
3790 /*-----------------------------------------------------------------*/
3791 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
3792 /*                         the flow blocks.                        */
3793 /*
3794 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3795 * point the instruction flow changes. 
3796 */
3797 /*-----------------------------------------------------------------*/
3798 void BuildFlow(pBlock *pb)
3799 {
3800   pCode *pc;
3801   pCode *last_pci=NULL;
3802   pCode *pflow=NULL;
3803   int seq = 0;
3804   
3805   if(!pb)
3806     return;
3807   
3808   //fprintf (stderr,"build flow start seq %d  ",GpcFlowSeq);
3809   /* Insert a pCodeFlow object at the beginning of a pBlock */
3810   
3811   InsertpFlow(pb->pcHead, &pflow);
3812   
3813   //pflow = newpCodeFlow();    /* Create a new Flow object */
3814   //pflow->next = pb->pcHead;  /* Make the current head the next object */
3815   //pb->pcHead->prev = pflow;  /* let the current head point back to the flow object */
3816   //pb->pcHead = pflow;        /* Make the Flow object the head */
3817   //pflow->pb = pb;
3818   
3819   for( pc = findNextInstruction(pb->pcHead);
3820   pc != NULL;
3821   pc=findNextInstruction(pc)) { 
3822     
3823     pc->seq = seq++;
3824     PCI(pc)->pcflow = PCFL(pflow);
3825     
3826     //fprintf(stderr," build: ");
3827     //pflow->print(stderr,pflow);
3828     
3829     if( PCI(pc)->isSkip) {
3830       
3831     /* The two instructions immediately following this one 
3832       * mark the beginning of a new flow segment */
3833       
3834       while(pc && PCI(pc)->isSkip) {
3835         
3836         PCI(pc)->pcflow = PCFL(pflow);
3837         pc->seq = seq-1;
3838         seq = 1;
3839         
3840         InsertpFlow(pc, &pflow);
3841         pc=findNextInstruction(pc->next);
3842       }
3843       
3844       seq = 0;
3845       
3846       if(!pc)
3847         break;
3848       
3849       PCI(pc)->pcflow = PCFL(pflow);
3850       pc->seq = 0;
3851       InsertpFlow(pc, &pflow);
3852       
3853     } else if ( PCI(pc)->isBranch && !checkLabel(findNextInstruction(pc->next)))  {
3854       
3855       InsertpFlow(pc, &pflow);
3856       seq = 0;
3857       
3858     } else if (checkLabel(pc)) { 
3859       
3860     /* This instruction marks the beginning of a
3861       * new flow segment */
3862       
3863       pc->seq = 0;
3864       seq = 1;
3865       
3866       /* If the previous pCode is not a flow object, then 
3867       * insert a new flow object. (This check prevents 
3868       * two consecutive flow objects from being insert in
3869       * the case where a skip instruction preceeds an
3870       * instruction containing a label.) */
3871       
3872       if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
3873         InsertpFlow(findPrevInstruction(pc->prev), &pflow);
3874       
3875       PCI(pc)->pcflow = PCFL(pflow);
3876       
3877     }
3878     last_pci = pc;
3879     pc = pc->next;
3880   }
3881   
3882   //fprintf (stderr,",end seq %d",GpcFlowSeq);
3883   if(pflow)
3884     PCFL(pflow)->end = pb->pcTail;
3885 }
3886
3887 /*-------------------------------------------------------------------*/
3888 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
3889 /*                           the flow blocks.                        */
3890 /*
3891 * unBuildFlow removes pCodeFlow objects from a pCode chain
3892 */
3893 /*-----------------------------------------------------------------*/
3894 void unBuildFlow(pBlock *pb)
3895 {
3896   pCode *pc,*pcnext;
3897   
3898   if(!pb)
3899     return;
3900   
3901   pc = pb->pcHead;
3902   
3903   while(pc) {
3904     pcnext = pc->next;
3905     
3906     if(isPCI(pc)) {
3907       
3908       pc->seq = 0;
3909       if(PCI(pc)->pcflow) {
3910         //free(PCI(pc)->pcflow);
3911         PCI(pc)->pcflow = NULL;
3912       }
3913       
3914     } else if(isPCFL(pc) )
3915       pc->destruct(pc);
3916     
3917     pc = pcnext;
3918   }
3919   
3920   
3921 }
3922
3923 /*-----------------------------------------------------------------*/
3924 /*-----------------------------------------------------------------*/
3925 void dumpCond(int cond)
3926 {
3927   
3928   static char *pcc_str[] = {
3929     //"PCC_NONE",
3930     "PCC_REGISTER",
3931       "PCC_C",
3932       "PCC_Z",
3933       "PCC_DC",
3934       "PCC_W",
3935       "PCC_EXAMINE_PCOP",
3936       "PCC_REG_BANK0",
3937       "PCC_REG_BANK1",
3938       "PCC_REG_BANK2",
3939       "PCC_REG_BANK3"
3940   };
3941   
3942   int ncond = sizeof(pcc_str) / sizeof(char *);
3943   int i,j;
3944   
3945   fprintf(stderr, "0x%04X\n",cond);
3946   
3947   for(i=0,j=1; i<ncond; i++, j<<=1)
3948     if(cond & j)
3949       fprintf(stderr, "  %s\n",pcc_str[i]);
3950     
3951 }
3952
3953 /*-----------------------------------------------------------------*/
3954 /*-----------------------------------------------------------------*/
3955 void FlowStats(pCodeFlow *pcflow)
3956 {
3957   
3958   pCode *pc;
3959   
3960   if(!isPCFL(pcflow))
3961     return;
3962   
3963   fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
3964   
3965   pc = findNextpCode(PCODE(pcflow), PC_OPCODE); 
3966   
3967   if(!pc) {
3968     fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
3969     return;
3970   }
3971   
3972   
3973   fprintf(stderr, "  FlowStats inCond: ");
3974   dumpCond(pcflow->inCond);
3975   fprintf(stderr, "  FlowStats outCond: ");
3976   dumpCond(pcflow->outCond);
3977   
3978 }
3979
3980 /*-----------------------------------------------------------------*
3981 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
3982 *    if it affects the banking bits. 
3983
3984 * return: -1 == Banking bits are unaffected by this pCode.
3985 *
3986 * return: > 0 == Banking bits are affected.
3987 *
3988 *  If the banking bits are affected, then the returned value describes
3989 * which bits are affected and how they're affected. The lower half
3990 * of the integer maps to the bits that are affected, the upper half
3991 * to whether they're set or cleared.
3992 *
3993 *-----------------------------------------------------------------*/
3994 /*
3995 #define SET_BANK_BIT (1 << 16)
3996 #define CLR_BANK_BIT 0
3997
3998 static int isBankInstruction(pCode *pc)
3999 {
4000   regs *reg;
4001   int bank = -1;
4002   
4003   if(!isPCI(pc))
4004     return -1;
4005   
4006   if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4007     
4008     // Check to see if the register banks are changing
4009     if(PCI(pc)->isModReg) {
4010       
4011       pCodeOp *pcop = PCI(pc)->pcop;
4012       switch(PCI(pc)->op) {
4013         
4014       case POC_BSF:
4015         if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4016           //fprintf(stderr, "  isBankInstruction - Set RP0\n");
4017           return  SET_BANK_BIT | PIC_RP0_BIT;
4018         }
4019         
4020         if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4021           //fprintf(stderr, "  isBankInstruction - Set RP1\n");
4022           return  CLR_BANK_BIT | PIC_RP0_BIT;
4023         }
4024         break;
4025         
4026       case POC_BCF:
4027         if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4028           //fprintf(stderr, "  isBankInstruction - Clr RP0\n");
4029           return  CLR_BANK_BIT | PIC_RP1_BIT;
4030         }
4031         if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4032           //fprintf(stderr, "  isBankInstruction - Clr RP1\n");
4033           return  CLR_BANK_BIT | PIC_RP1_BIT;
4034         }
4035         break;
4036       default:
4037         //fprintf(stderr, "  isBankInstruction - Status register is getting Modified by:\n");
4038         //genericPrint(stderr, pc);
4039         ;
4040       }
4041     }
4042     
4043   }
4044   
4045   return bank;
4046 }
4047 */
4048
4049 /*-----------------------------------------------------------------*/
4050 /*-----------------------------------------------------------------*/
4051 /*
4052 static void FillFlow(pCodeFlow *pcflow)
4053 {
4054   pCode *pc;
4055   int cur_bank;
4056   
4057   if(!isPCFL(pcflow))
4058     return;
4059   
4060   //  fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4061   
4062   pc = findNextpCode(PCODE(pcflow), PC_OPCODE); 
4063   
4064   if(!pc) {
4065     //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4066     return;
4067   }
4068   
4069   cur_bank = -1;
4070
4071   do {
4072     isBankInstruction(pc);
4073     pc = pc->next;
4074   } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4075   / *
4076   if(!pc ) {
4077     fprintf(stderr, "  FillFlow - Bad end of flow\n");
4078   } else {
4079     fprintf(stderr, "  FillFlow - Ending flow with\n  ");
4080     pc->print(stderr,pc);
4081   }
4082
4083   fprintf(stderr, "  FillFlow inCond: ");
4084   dumpCond(pcflow->inCond);
4085   fprintf(stderr, "  FillFlow outCond: ");
4086   dumpCond(pcflow->outCond);
4087   * /
4088 }
4089 */
4090
4091 /*-----------------------------------------------------------------*/
4092 /*-----------------------------------------------------------------*/
4093 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4094 {
4095   pCodeFlowLink *fromLink, *toLink;
4096   
4097   if(!from || !to || !to->pcflow || !from->pcflow)
4098     return;
4099   
4100   fromLink = newpCodeFlowLink(from->pcflow);
4101   toLink   = newpCodeFlowLink(to->pcflow);
4102   
4103   addSetIfnotP(&(from->pcflow->to), toLink);   //to->pcflow);
4104   addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4105   
4106 }
4107
4108 /*-----------------------------------------------------------------*
4109 * void LinkFlow(pBlock *pb)
4110 *
4111 * In BuildFlow, the PIC code has been partitioned into contiguous
4112 * non-branching segments. In LinkFlow, we determine the execution
4113 * order of these segments. For example, if one of the segments ends
4114 * with a skip, then we know that there are two possible flow segments
4115 * to which control may be passed.
4116 *-----------------------------------------------------------------*/
4117 void LinkFlow(pBlock *pb)
4118 {
4119   pCode *pc=NULL;
4120   pCode *pcflow;
4121   pCode *pct;
4122   
4123   //fprintf(stderr,"linkflow \n");
4124   
4125   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4126   pcflow != NULL;
4127   pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4128     
4129     if(!isPCFL(pcflow))
4130       fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4131     
4132     //fprintf(stderr," link: ");
4133     //pcflow->print(stderr,pcflow);
4134     
4135     //FillFlow(PCFL(pcflow));
4136     
4137     pc = PCFL(pcflow)->end;
4138     
4139     //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4140     if(isPCI_SKIP(pc)) {
4141       //fprintf(stderr, "ends with skip\n");
4142       //pc->print(stderr,pc);
4143       pct=findNextInstruction(pc->next);
4144       LinkFlow_pCode(PCI(pc),PCI(pct));
4145       pct=findNextInstruction(pct->next);
4146       LinkFlow_pCode(PCI(pc),PCI(pct));
4147       continue;
4148     }
4149     
4150     if(isPCI_BRANCH(pc)) {
4151       pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4152       
4153       //fprintf(stderr, "ends with branch\n  ");
4154       //pc->print(stderr,pc);
4155       
4156       if(!(pcol && isPCOLAB(pcol))) {
4157         if((PCI(pc)->op != POC_RETLW) && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
4158           pc->print(stderr,pc);
4159           fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4160         }
4161         continue;
4162       }
4163       
4164       if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4165         LinkFlow_pCode(PCI(pc),PCI(pct));
4166       else
4167         fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4168         __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4169       //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4170       
4171       continue;
4172     }
4173     
4174     if(isPCI(pc)) {
4175       //fprintf(stderr, "ends with non-branching instruction:\n");
4176       //pc->print(stderr,pc);
4177       
4178       LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4179       
4180       continue;
4181     }
4182     
4183     if(pc) {
4184       //fprintf(stderr, "ends with unknown\n");
4185       //pc->print(stderr,pc);
4186       continue;
4187     }
4188     
4189     //fprintf(stderr, "ends with nothing: ERROR\n");
4190     
4191   }
4192 }
4193 /*-----------------------------------------------------------------*/
4194 /*-----------------------------------------------------------------*/
4195
4196 /*-----------------------------------------------------------------*/
4197 /*-----------------------------------------------------------------*/
4198 int isPCinFlow(pCode *pc, pCode *pcflow)
4199 {
4200   
4201   if(!pc || !pcflow)
4202     return 0;
4203   
4204   if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4205     return 0;
4206   
4207   if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4208     return 1;
4209   
4210   return 0;
4211 }
4212
4213 /*-----------------------------------------------------------------*/
4214 /*-----------------------------------------------------------------*/
4215 /*
4216 static void BanksUsedFlow2(pCode *pcflow)
4217 {
4218   pCode *pc=NULL;
4219   
4220   int bank = -1;
4221   bool RegUsed = 0;
4222   
4223   regs *reg;
4224   
4225   if(!isPCFL(pcflow)) {
4226     fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4227     return;
4228   }
4229   
4230   pc = findNextInstruction(pcflow->next);
4231   
4232       PCFL(pcflow)->lastBank = -1;
4233       
4234       while(isPCinFlow(pc,pcflow)) {
4235         
4236         int bank_selected = isBankInstruction(pc);
4237         
4238         //if(PCI(pc)->pcflow) 
4239         //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4240         
4241         if(bank_selected > 0) {
4242           //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4243           
4244           // This instruction is modifying banking bits before accessing registers
4245           if(!RegUsed)
4246             PCFL(pcflow)->firstBank = -1;
4247           
4248           if(PCFL(pcflow)->lastBank == -1)
4249             PCFL(pcflow)->lastBank = 0;
4250           
4251           bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4252           if(bank_selected & SET_BANK_BIT)
4253             PCFL(pcflow)->lastBank |= bank;
4254           
4255           
4256         } else { 
4257           reg = getRegFromInstruction(pc);
4258           
4259           if(reg && !isREGinBank(reg, bank)) {
4260             int allbanks = REGallBanks(reg);
4261             if(bank == -1)
4262               PCFL(pcflow)->firstBank = allbanks;
4263             
4264             PCFL(pcflow)->lastBank = allbanks;
4265             
4266             bank = allbanks;
4267           }
4268           RegUsed = 1;
4269         }
4270         
4271         pc = findNextInstruction(pc->next);
4272       }
4273       
4274       //  fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4275       //    pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4276 }
4277 */
4278 /*-----------------------------------------------------------------*/
4279 /*-----------------------------------------------------------------*/
4280 /*
4281 static void BanksUsedFlow(pBlock *pb)
4282 {
4283 pCode *pcflow;
4284
4285
4286   //pb->pcHead->print(stderr, pb->pcHead);
4287   
4288   pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4289   //pcflow->print(stderr,pcflow);
4290
4291   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4292     pcflow != NULL;
4293     pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4294     
4295     BanksUsedFlow2(pcflow);
4296   }
4297
4298 }
4299 */
4300
4301 /*-----------------------------------------------------------------*/
4302 /*-----------------------------------------------------------------*/
4303 static void pCodeInstructionInsertAfter(pCodeInstruction *pci, pCodeInstruction *new_pci)
4304 {
4305   
4306   pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4307   
4308   /* Move the label, if there is one */
4309   
4310   if(pci->label) {
4311     new_pci->label = pci->label;
4312     pci->label = NULL;
4313   }
4314   
4315   /* Move the C code comment, if there is one */
4316   
4317   if(pci->cline) {
4318     new_pci->cline = pci->cline;
4319     pci->cline = NULL;
4320   }
4321   
4322   /* The new instruction has the same pcflow block */
4323   new_pci->pcflow = pci->pcflow;
4324   
4325 }
4326
4327 /*-----------------------------------------------------------------*/
4328 /*-----------------------------------------------------------------*/
4329 static void insertBankSwitch(pCodeInstruction *pci, int Set_Clear, int RP_BankBit)
4330 {
4331   pCode *new_pc;
4332   
4333   new_pc = newpCode((Set_Clear?POC_BSF:POC_BCF),popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit));
4334   
4335   pCodeInstructionInsertAfter(pci, PCI(new_pc));
4336 }
4337
4338 /*-----------------------------------------------------------------*/
4339 /*-----------------------------------------------------------------*/
4340 static void insertBankSel(pCodeInstruction  *pci, const char *name)
4341 {
4342   pCode *new_pc;
4343   
4344   pCodeOp *pcop = popCopyReg(PCOR(pci->pcop));
4345   pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4346   if (pcop->name == 0)
4347     pcop->name = strdup(name);
4348   new_pc = newpCode(POC_BANKSEL, pcop);
4349   
4350   pCodeInstructionInsertAfter(pci, PCI(new_pc));
4351 }
4352
4353 /*-----------------------------------------------------------------*/
4354 /* If the register is a fixed known addess then we can assign the  */
4355 /* bank selection bits. Otherwise the linker is going to assign    */
4356 /* the register location and thus has to set bank selection bits   */
4357 /* through the banksel directive.                                  */
4358 /* One critical assumption here is that within this C module all   */ 
4359 /* the locally allocated registers are in the same udata sector.   */
4360 /* Therefore banksel is only called for external registers or the  */
4361 /* first time a local register is encountered.                     */
4362 /*-----------------------------------------------------------------*/
4363 static int LastRegIdx; /* If the previous register is the same one again then no need to change bank. */
4364 static int BankSelect(pCodeInstruction *pci, int cur_bank, regs *reg)
4365 {
4366   int bank;
4367   int a = reg->alias>>7;
4368   if ((a&3) == 3) {
4369     return cur_bank; // This register is available in all banks
4370   } else if ((a&1)&&((cur_bank==0)||(cur_bank==1))) {
4371     return cur_bank; // This register is available in banks 0 & 1
4372   } else if (a&2) {
4373     if (reg->address&0x80) {
4374       if ((cur_bank==1)||(cur_bank==3)) {
4375         return cur_bank; // This register is available in banks 1 & 3
4376       }
4377     } else {
4378       if ((cur_bank==0)||(cur_bank==1)) {
4379         return cur_bank; // This register is available in banks 0 & 2
4380       }
4381     }
4382   }
4383   
4384   if (LastRegIdx == reg->rIdx) // If this is the same register as last time then it is in same bank
4385     return cur_bank;
4386   LastRegIdx = reg->rIdx;
4387   
4388   if (reg->isFixed) {
4389     bank = REG_BANK(reg);
4390   } else if (reg->isExtern) {
4391     bank = 'E'; // Unfixed extern registers are allocated by the linker therefore its bank is unknown
4392   } else {
4393     bank = 'L'; // Unfixed local registers are allocated by the linker therefore its bank is unknown
4394   }
4395   if ((cur_bank == 'L')&&(bank == 'L')) { // If current bank and new bank are both allocated locally by the linker, then assume it is in same bank.
4396     return 'L'; // Local registers are presumed to be in same linker assigned bank
4397   } else if ((bank == 'L')&&(cur_bank != 'L')) { // Reg is now local and linker to assign bank
4398     insertBankSel(pci, reg->name); // Let linker choose the bank selection
4399   } else if (bank == 'E') { // Reg is now extern and linker to assign bank
4400     insertBankSel(pci, reg->name); // Let linker choose the bank selection
4401   } else if ((cur_bank == -1)||(cur_bank == 'L')||(cur_bank == 'E')) { // Current bank unknown and new register bank is known then can set bank bits
4402     insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4403     insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4404   } else { // Current bank and new register banks known - can set bank bits
4405     switch((cur_bank^bank) & 3) {
4406     case 0:
4407       break;
4408     case 1:
4409       insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4410       break;
4411     case 2:
4412       insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4413       break;
4414     case 3:
4415       insertBankSwitch(pci, bank&1, PIC_RP0_BIT);
4416       insertBankSwitch(pci, bank&2, PIC_RP1_BIT);
4417       break;
4418     }
4419   }
4420   
4421   return bank;
4422 }
4423
4424 /*-----------------------------------------------------------------*/
4425 /* Check for bank selection pcodes instructions and modify         */
4426 /* cur_bank to match.                                              */
4427 /*-----------------------------------------------------------------*/
4428 static int IsBankChange(pCode *pc, regs *reg, int *cur_bank) {
4429   
4430   if (isSTATUS_REG(reg)) {
4431     
4432     if (PCI(pc)->op == POC_BCF) {
4433       int old_bank = *cur_bank;
4434       if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4435         /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4436         if (*cur_bank & ~(0x3))
4437           *cur_bank = 0;
4438         else
4439           *cur_bank = *cur_bank&0x2;
4440         LastRegIdx = reg->rIdx;
4441       } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4442         /* If current bank is unknown or linker assigned then set to 0 else just change the bit */
4443         if (*cur_bank & ~(0x3))
4444           *cur_bank = 0;
4445         else
4446           *cur_bank = *cur_bank&0x1;
4447         LastRegIdx = reg->rIdx;
4448       }
4449       return old_bank != *cur_bank;
4450     }
4451     
4452     if (PCI(pc)->op == POC_BSF) {
4453       int old_bank = *cur_bank;
4454       if (PCORB(PCI(pc)->pcop)->bit == PIC_RP0_BIT) {
4455         /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4456         if (*cur_bank & ~(0x3))
4457           *cur_bank = 0x1;
4458         else
4459           *cur_bank = (*cur_bank&0x2) | 0x1;
4460         LastRegIdx = reg->rIdx;
4461       } else if (PCORB(PCI(pc)->pcop)->bit == PIC_RP1_BIT) {
4462         /* If current bank is unknown or linker assigned then set to bit else just change the bit */
4463         if (*cur_bank & ~(0x3))
4464           *cur_bank = 0x2;
4465         else
4466           *cur_bank = (*cur_bank&0x1) | 0x2;
4467         LastRegIdx = reg->rIdx;
4468       }
4469       return old_bank != *cur_bank;
4470     }
4471     
4472   } else if (PCI(pc)->op == POC_BANKSEL) {
4473     int old_bank = *cur_bank;
4474     *cur_bank = (PCOR(PCI(pc)->pcop)->r->isExtern) ? 'E' : 'L';
4475     LastRegIdx = reg->rIdx;
4476     return old_bank != *cur_bank;
4477   }
4478   
4479   return 0;
4480 }
4481
4482 /*-----------------------------------------------------------------*/
4483 /* Set bank selection if necessary                                 */
4484 /*-----------------------------------------------------------------*/
4485 static int DoBankSelect(pCode *pc, int cur_bank) {
4486   pCode *pcprev;
4487   regs *reg;
4488   
4489   if(!isPCI(pc))
4490     return cur_bank;
4491   
4492   if (isCALL(pc)) {
4493     pCode *pcf = findFunction(get_op_from_instruction(PCI(pc)));
4494     if (pcf && isPCF(pcf)) {
4495       pCode *pcfr;
4496       int rbank = 'U'; // Undetermined
4497       FixRegisterBanking(pcf->pb,cur_bank); // Ensure this block has had its banks selection done
4498       // Check all the returns to work out what bank is selected
4499       for (pcfr=pcf->pb->pcHead; pcfr; pcfr=pcfr->next) {
4500         if (isPCI(pcfr)) {
4501           if ((PCI(pcfr)->op==POC_RETURN) || (PCI(pcfr)->op==POC_RETLW)) {
4502             if (rbank == 'U')
4503               rbank = PCFL(pcfr)->lastBank;
4504             else
4505               if (rbank != PCFL(pcfr)->lastBank)
4506                 return -1; // Unknown bank - multiple returns with different banks
4507           }
4508         }
4509       }
4510       if (rbank == 'U')
4511         return -1; // Unknown bank
4512       return rbank;
4513     } else if (isPCOS(PCI(pc)->pcop) && PCOS(PCI(pc)->pcop)->isPublic) {
4514       /* Extern functions may use registers in different bank - must call banksel */
4515       return -1; /* Unknown bank */
4516     }
4517   }
4518   
4519   if ((isPCI(pc)) && (PCI(pc)->op == POC_BANKSEL)) {
4520     return -1; /* New bank unknown - linkers choice. */
4521   }
4522   
4523   reg = getRegFromInstruction(pc);
4524   if (reg) {
4525     
4526     if (IsBankChange(pc,reg,&cur_bank))
4527       return cur_bank;
4528     
4529     if (!isPCI_LIT(pc)) {
4530       
4531     /* Examine the instruction before this one to make sure it is
4532       * not a skip type instruction */
4533       pcprev = findPrevpCode(pc->prev, PC_OPCODE);
4534       
4535       if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
4536         cur_bank = BankSelect(PCI(pc),cur_bank,reg);
4537       } else {
4538         cur_bank = BankSelect(PCI(pcprev),cur_bank,reg);
4539       }
4540       if (!PCI(pc)->pcflow)
4541         fprintf(stderr,"PCI ID=%d missing flow pointer ???\n",pc->id);
4542       else
4543         PCI(pc)->pcflow->lastBank = cur_bank; /* Maintain pCodeFlow lastBank state */
4544     }
4545   }
4546   return cur_bank;
4547 }
4548
4549 /*-----------------------------------------------------------------*/
4550 /*-----------------------------------------------------------------*/
4551 /*
4552 static void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank)
4553 {
4554   pCode *pc=NULL;
4555   pCode *pcprev=NULL;
4556
4557   if(!pcfl)
4558   return;
4559
4560   pc = findNextInstruction(pcfl->pc.next);
4561   
4562   while(isPCinFlow(pc,PCODE(pcfl))) {
4563
4564     cur_bank = DoBankSelect(pc,cur_bank);
4565     pcprev = pc;
4566     pc = findNextInstruction(pc->next);
4567     
4568   }
4569
4570   if(pcprev && cur_bank) {
4571     // Set bank state to unknown at the end of each flow block
4572     cur_bank = -1;
4573   }
4574
4575 }
4576 */
4577 /*-----------------------------------------------------------------*/
4578 /*int compareBankFlow - compare the banking requirements between   */
4579 /*  flow objects. */
4580 /*-----------------------------------------------------------------*/
4581 /*
4582 int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
4583 {
4584   
4585   if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
4586     return 0;
4587   
4588   if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
4589     return 0;
4590   
4591   if(pcflow->firstBank == -1)
4592     return 0;
4593   
4594   
4595       if(pcflowLink->pcflow->firstBank == -1) {
4596         pCodeFlowLink *pctl = setFirstItem( toORfrom ? 
4597           pcflowLink->pcflow->to : 
4598         pcflowLink->pcflow->from);
4599         return compareBankFlow(pcflow, pctl, toORfrom);
4600       }
4601       
4602       if(toORfrom) {
4603         if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
4604           return 0;
4605         
4606         pcflowLink->bank_conflict++;
4607         pcflowLink->pcflow->FromConflicts++;
4608         pcflow->ToConflicts++;
4609       } else {
4610         
4611         if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
4612           return 0;
4613         
4614         pcflowLink->bank_conflict++;
4615         pcflowLink->pcflow->ToConflicts++;
4616         pcflow->FromConflicts++;
4617         
4618       }
4619       / *
4620         fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
4621         pcflowLink->pcflow->pc.seq,
4622         pcflowLink->pcflow->FromConflicts,
4623         pcflowLink->pcflow->ToConflicts);
4624       * /
4625         return 1;
4626       
4627 }
4628 */
4629 /*-----------------------------------------------------------------*/
4630 /*-----------------------------------------------------------------*/
4631 /*
4632 void FixBankFlow(pBlock *pb)
4633 {
4634   pCode *pc=NULL;
4635   pCode *pcflow;
4636   pCodeFlowLink *pcfl;
4637   
4638   pCode *pcflow_max_To=NULL;
4639   pCode *pcflow_max_From=NULL;
4640   int max_ToConflicts=0;
4641   int max_FromConflicts=0;
4642   
4643   //fprintf(stderr,"Fix Bank flow \n");
4644   pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4645   
4646   
4647   / *
4648   First loop through all of the flow objects in this pcode block
4649   and fix the ones that have banking conflicts between the 
4650   entry and exit.
4651   * /
4652
4653   //fprintf(stderr, "FixBankFlow - Phase 1\n");
4654   
4655   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4656     pcflow != NULL;
4657     pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4658
4659     if(!isPCFL(pcflow)) {
4660       fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4661       continue;
4662     }
4663     
4664     if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank  &&
4665       PCFL(pcflow)->firstBank >= 0 &&
4666       PCFL(pcflow)->lastBank >= 0 ) {
4667       
4668       int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ?
4669         PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank;
4670       
4671       FixRegisterBankingInFlow(PCFL(pcflow),cur_bank);
4672       BanksUsedFlow2(pcflow);
4673       
4674     }
4675   }
4676   
4677   //fprintf(stderr, "FixBankFlow - Phase 2\n");
4678   
4679   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4680     pcflow != NULL;
4681     pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4682
4683       int nFlows;
4684       int nConflicts;
4685
4686       if(!isPCFL(pcflow)) {
4687         fprintf(stderr, "FixBankFlow - pcflow is not a flow object ");
4688         continue;
4689       }
4690
4691     PCFL(pcflow)->FromConflicts = 0;
4692     PCFL(pcflow)->ToConflicts = 0;
4693
4694     nFlows = 0;
4695     nConflicts = 0;
4696
4697     //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq);
4698     pcfl = setFirstItem(PCFL(pcflow)->from);
4699     while (pcfl) {
4700
4701       pc = PCODE(pcfl->pcflow);
4702
4703       if(!isPCFL(pc)) {
4704         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4705         pc->print(stderr,pc);
4706       }
4707
4708       nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0);
4709       nFlows++;
4710
4711       pcfl=setNextItem(PCFL(pcflow)->from);
4712     }
4713
4714     if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) {
4715       //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4716
4717       FixRegisterBankingInFlow(PCFL(pcflow),-1);
4718       BanksUsedFlow2(pcflow);
4719
4720       continue;  / * Don't need to check the flow from here - it's already been fixed * /
4721
4722     }
4723
4724     nFlows = 0;
4725     nConflicts = 0;
4726
4727     pcfl = setFirstItem(PCFL(pcflow)->to);
4728     while (pcfl) {
4729
4730       pc = PCODE(pcfl->pcflow);
4731       if(!isPCFL(pc)) {
4732         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4733         pc->print(stderr,pc);
4734       }
4735
4736       nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1);
4737       nFlows++;
4738
4739       pcfl=setNextItem(PCFL(pcflow)->to);
4740     }
4741
4742     if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) {
4743       //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts);
4744
4745       FixRegisterBankingInFlow(PCFL(pcflow),-1);
4746       BanksUsedFlow2(pcflow);
4747     }
4748   }
4749
4750   / *
4751   Loop through the flow objects again and find the ones with the 
4752   maximum conflicts
4753   * /
4754
4755   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4756   pcflow != NULL;
4757   pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4758
4759     if(PCFL(pcflow)->ToConflicts > max_ToConflicts)
4760       pcflow_max_To = pcflow;
4761
4762     if(PCFL(pcflow)->FromConflicts > max_FromConflicts)
4763       pcflow_max_From = pcflow;
4764   }
4765   / *
4766   if(pcflow_max_To)
4767     fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n",
4768   PCFL(pcflow_max_To)->pc.seq,
4769   PCFL(pcflow_max_To)->ToConflicts);
4770
4771   if(pcflow_max_From)
4772     fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n",
4773   PCFL(pcflow_max_From)->pc.seq,
4774   PCFL(pcflow_max_From)->FromConflicts);
4775   * /
4776 }
4777 */
4778
4779 /*-----------------------------------------------------------------*/
4780 /*-----------------------------------------------------------------*/
4781 void DumpFlow(pBlock *pb)
4782 {
4783   pCode *pc=NULL;
4784   pCode *pcflow;
4785   pCodeFlowLink *pcfl;
4786   
4787   
4788   fprintf(stderr,"Dump flow \n");
4789   pb->pcHead->print(stderr, pb->pcHead);
4790   
4791   pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4792   pcflow->print(stderr,pcflow);
4793   
4794   for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4795   pcflow != NULL;
4796   pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4797     
4798     if(!isPCFL(pcflow)) {
4799       fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
4800       continue;
4801     }
4802     fprintf(stderr,"dumping: ");
4803     pcflow->print(stderr,pcflow);
4804     FlowStats(PCFL(pcflow));
4805     
4806     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4807       
4808       pc = PCODE(pcfl->pcflow);
4809       
4810       fprintf(stderr, "    from seq %d:\n",pc->seq);
4811       if(!isPCFL(pc)) {
4812         fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
4813         pc->print(stderr,pc);
4814       }
4815       
4816     }
4817     
4818     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
4819       
4820       pc = PCODE(pcfl->pcflow);
4821       
4822       fprintf(stderr, "    to seq %d:\n",pc->seq);
4823       if(!isPCFL(pc)) {
4824         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
4825         pc->print(stderr,pc);
4826       }
4827       
4828     }
4829     
4830   }
4831   
4832 }
4833
4834 /*-----------------------------------------------------------------*/
4835 /*-----------------------------------------------------------------*/
4836 int OptimizepBlock(pBlock *pb)
4837 {
4838   pCode *pc, *pcprev;
4839   int matches =0;
4840   
4841   if(!pb || !peepOptimizing)
4842     return 0;
4843   
4844   DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4845   /*
4846   for(pc = pb->pcHead; pc; pc = pc->next)
4847   matches += pCodePeepMatchRule(pc);
4848   */
4849   
4850   pc = findNextInstruction(pb->pcHead);
4851   if(!pc)
4852     return 0;
4853   
4854   pcprev = pc->prev;
4855   do {
4856     
4857     
4858     if(pCodePeepMatchRule(pc)) {
4859       
4860       matches++;
4861       
4862       if(pcprev)
4863         pc = findNextInstruction(pcprev->next);
4864       else 
4865         pc = findNextInstruction(pb->pcHead);
4866     } else
4867       pc = findNextInstruction(pc->next);
4868   } while(pc);
4869   
4870   if(matches)
4871     DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4872   return matches;
4873   
4874 }
4875
4876 /*-----------------------------------------------------------------*/
4877 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
4878 /*-----------------------------------------------------------------*/
4879 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4880 {
4881   pCode *pc;
4882   
4883   for(pc = pcs; pc; pc = pc->next) {
4884     
4885     if((pc->type == PC_OPCODE) && 
4886       (PCI(pc)->pcop) && 
4887       (PCI(pc)->pcop->type == PO_LABEL) &&
4888       (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4889       return pc;
4890   }
4891   
4892   
4893   return NULL;
4894 }
4895
4896 /*-----------------------------------------------------------------*/
4897 /*-----------------------------------------------------------------*/
4898 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4899 {
4900   
4901   char *s=NULL;
4902   
4903   if(isPCI(pc) && 
4904     (PCI(pc)->pcop) && 
4905     (PCI(pc)->pcop->type == PO_LABEL)) {
4906     
4907     pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4908     
4909     //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4910     if(pcol->pcop.name)
4911       free(pcol->pcop.name);
4912     
4913       /* If the key is negative, then we (probably) have a label to
4914     * a function and the name is already defined */
4915     
4916     if(pcl->key>0)
4917       sprintf(s=buffer,"_%05d_DS_",pcl->key);
4918     else 
4919       s = pcl->label;
4920     
4921     //sprintf(buffer,"_%05d_DS_",pcl->key);
4922     if(!s) {
4923       fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4924     }
4925     pcol->pcop.name = Safe_strdup(s);
4926     pcol->key = pcl->key;
4927     //pc->print(stderr,pc);
4928     
4929   }
4930   
4931   
4932 }
4933
4934 /*-----------------------------------------------------------------*/
4935 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
4936 /*                            pCode chain if they're not used.     */
4937 /*-----------------------------------------------------------------*/
4938 void pBlockRemoveUnusedLabels(pBlock *pb)
4939 {
4940   pCode *pc; pCodeLabel *pcl;
4941   
4942   if(!pb)
4943     return;
4944   
4945   for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4946     
4947     pBranch *pbr = PCI(pc)->label;
4948     if(pbr && pbr->next) {
4949       pCode *pcd = pb->pcHead;
4950       
4951       //fprintf(stderr, "multiple labels\n");
4952       //pc->print(stderr,pc);
4953       
4954       pbr = pbr->next;
4955       while(pbr) {
4956         
4957         while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4958           //fprintf(stderr,"Used by:\n");
4959           //pcd->print(stderr,pcd);
4960           
4961           exchangeLabels(PCL(pbr->pc),pcd);
4962           
4963           pcd = pcd->next;
4964         }
4965         pbr = pbr->next;
4966       }
4967     }
4968   }
4969   
4970   for(pc = pb->pcHead; pc; pc = pc->next) {
4971     
4972     if(isPCL(pc)) // Label pcode
4973       pcl = PCL(pc);
4974     else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
4975       pcl = PCL(PCI(pc)->label->pc);
4976     else continue;
4977     
4978     //fprintf(stderr," found  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4979     
4980     /* This pCode is a label, so search the pBlock to see if anyone
4981     * refers to it */
4982     
4983     if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4984       //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4985       /* Couldn't find an instruction that refers to this label
4986       * So, unlink the pCode label from it's pCode chain
4987       * and destroy the label */
4988       //fprintf(stderr," removed  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4989       
4990       DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4991       if(pc->type == PC_LABEL) {
4992         unlinkpCode(pc);
4993         pCodeLabelDestruct(pc);
4994       } else {
4995         unlinkpCodeFromBranch(pc, PCODE(pcl));
4996         /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4997         free(pc->label);
4998       }*/
4999       }
5000       
5001     }
5002   }
5003   
5004 }
5005
5006
5007 /*-----------------------------------------------------------------*/
5008 /* pBlockMergeLabels - remove the pCode labels from the pCode      */
5009 /*                     chain and put them into pBranches that are  */
5010 /*                     associated with the appropriate pCode       */
5011 /*                     instructions.                               */
5012 /*-----------------------------------------------------------------*/
5013 void pBlockMergeLabels(pBlock *pb)
5014 {
5015   pBranch *pbr;
5016   pCode *pc, *pcnext=NULL;
5017   
5018   if(!pb)
5019     return;
5020   
5021   /* First, Try to remove any unused labels */
5022   //pBlockRemoveUnusedLabels(pb);
5023   
5024   /* Now loop through the pBlock and merge the labels with the opcodes */
5025   
5026   pc = pb->pcHead;
5027   //  for(pc = pb->pcHead; pc; pc = pc->next) {
5028   
5029   while(pc) {
5030     pCode *pcn = pc->next;
5031     
5032     if(pc->type == PC_LABEL) {
5033       
5034       //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5035       //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5036       if((pcnext = findNextInstruction(pc) )) {
5037         
5038         // Unlink the pCode label from it's pCode chain
5039         unlinkpCode(pc);
5040         
5041         //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5042         // And link it into the instruction's pBranch labels. (Note, since
5043         // it's possible to have multiple labels associated with one instruction
5044         // we must provide a means to accomodate the additional labels. Thus
5045         // the labels are placed into the singly-linked list "label" as 
5046         // opposed to being a single member of the pCodeInstruction.)
5047         
5048         //_ALLOC(pbr,sizeof(pBranch));
5049         pbr = Safe_calloc(1,sizeof(pBranch));
5050         pbr->pc = pc;
5051         pbr->next = NULL;
5052         
5053         PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
5054         
5055       } else {
5056         fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5057       }
5058     } else if(pc->type == PC_CSOURCE) {
5059       
5060       /* merge the source line symbolic info into the next instruction */
5061       if((pcnext = findNextInstruction(pc) )) {
5062         
5063         // Unlink the pCode label from it's pCode chain
5064         unlinkpCode(pc);
5065         PCI(pcnext)->cline = PCCS(pc);
5066         //fprintf(stderr, "merging CSRC\n");
5067         //genericPrint(stderr,pcnext);
5068       }
5069       
5070     }
5071     pc = pcn;
5072   }
5073   pBlockRemoveUnusedLabels(pb);
5074   
5075 }
5076
5077 /*-----------------------------------------------------------------*/
5078 /*-----------------------------------------------------------------*/
5079 int OptimizepCode(char dbName)
5080 {
5081 #define MAX_PASSES 4
5082   
5083   int matches = 0;
5084   int passes = 0;
5085   pBlock *pb;
5086   
5087   if(!the_pFile)
5088     return 0;
5089   
5090   DFPRINTF((stderr," Optimizing pCode\n"));
5091   
5092   do {
5093     matches = 0;
5094     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5095       if('*' == dbName || getpBlock_dbName(pb) == dbName)
5096         matches += OptimizepBlock(pb);
5097     }
5098   }
5099   while(matches && ++passes < MAX_PASSES);
5100   
5101   return matches;
5102 }
5103
5104 /*-----------------------------------------------------------------*/
5105 /* popCopyGPR2Bit - copy a pcode operator                          */
5106 /*-----------------------------------------------------------------*/
5107
5108 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5109 {
5110   pCodeOp *pcop;
5111   
5112   pcop = newpCodeOpBit(pc->name, bitval, 0);
5113   
5114   if( !( (pcop->type == PO_LABEL) ||
5115     (pcop->type == PO_LITERAL) ||
5116     (pcop->type == PO_STR) ))
5117     PCOR(pcop)->r = PCOR(pc)->r;  /* This is dangerous... */
5118   
5119   return pcop;
5120 }
5121
5122
5123 /*-----------------------------------------------------------------*/
5124 /*-----------------------------------------------------------------*/
5125 static void FixRegisterBanking(pBlock *pb,int cur_bank)
5126 {
5127   pCode *pc;
5128   int firstBank = 'U';
5129   
5130   if(!pb)
5131     return;
5132   
5133   for (pc=pb->pcHead; pc; pc=pc->next) {
5134     if (isPCFL(pc)) {
5135       firstBank = PCFL(pc)->firstBank;
5136       break;
5137     }
5138   }
5139   if (firstBank != 'U') {
5140     /* This block has already been done */
5141     if (firstBank != cur_bank) {
5142       /* This block has started with a different bank - must adjust it */ 
5143       if ((firstBank != -1)&&(firstBank != 'E')) { /* The first bank start off unknown or extern then need not worry as banksel will be called */
5144         while (pc) {
5145           if (isPCI(pc)) {
5146             regs *reg = getRegFromInstruction(pc);
5147             if (reg) {
5148               DoBankSelect(pc,cur_bank);
5149             }
5150           }
5151           pc = pc->next;
5152         }
5153       }
5154     }
5155     return;
5156   }
5157   
5158   /* loop through all of the pCodes within this pblock setting the bank selection, ignoring any branching */
5159   LastRegIdx = -1;
5160   cur_bank = -1;
5161   for (pc=pb->pcHead; pc; pc=pc->next) {
5162     if (isPCFL(pc)) {
5163       PCFL(pc)->firstBank = cur_bank;
5164       continue;
5165     }
5166     cur_bank = DoBankSelect(pc,cur_bank);
5167   }
5168   
5169   /* Trace through branches and set the bank selection as required. */
5170   LastRegIdx = -1;
5171   cur_bank = -1;
5172   for (pc=pb->pcHead; pc; pc=pc->next) {
5173     if (isPCFL(pc)) {
5174       PCFL(pc)->firstBank = cur_bank;
5175       continue;
5176     }
5177     if (isPCI(pc)) {
5178       if (PCI(pc)->op == POC_GOTO) {
5179         int lastRegIdx = LastRegIdx;
5180         pCode *pcb = pc;
5181         /* Trace through branch */
5182         pCode *pcl = findLabel(PCOLAB(PCI(pcb)->pcop));
5183         while (pcl) {
5184           if (isPCI(pcl)) {
5185             regs *reg = getRegFromInstruction(pcl);
5186             if (reg) {
5187               int bankUnknown = -1;
5188               if (IsBankChange(pcl,reg,&bankUnknown)) /* Look for any bank change */
5189                 break;
5190               if (cur_bank != DoBankSelect(pcl,cur_bank)) /* Set bank selection if necessary */
5191                 break;
5192             }
5193           }
5194           pcl = pcl->next;
5195         }
5196         LastRegIdx = lastRegIdx;
5197       } else {
5198         /* Keep track out current bank */
5199         regs *reg = getRegFromInstruction(pc);
5200         if (reg)
5201           IsBankChange(pc,reg,&cur_bank);
5202       }
5203     }
5204   }
5205 }
5206
5207
5208 /*-----------------------------------------------------------------*/
5209 /*-----------------------------------------------------------------*/
5210 void pBlockDestruct(pBlock *pb)
5211 {
5212   
5213   if(!pb)
5214     return;
5215   
5216   
5217   free(pb);
5218   
5219 }
5220
5221 /*-----------------------------------------------------------------*/
5222 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5223 /*                                  name dbName and combine them   */
5224 /*                                  into one block                 */
5225 /*-----------------------------------------------------------------*/
5226 void mergepBlocks(char dbName)
5227 {
5228   
5229   pBlock *pb, *pbmerged = NULL,*pbn;
5230   
5231   pb = the_pFile->pbHead;
5232   
5233   //fprintf(stderr," merging blocks named %c\n",dbName);
5234   while(pb) {
5235     
5236     pbn = pb->next;
5237     //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5238     if( getpBlock_dbName(pb) == dbName) {
5239       
5240       //fprintf(stderr," merged block %c\n",dbName);
5241       
5242       if(!pbmerged) {
5243         pbmerged = pb;
5244       } else {
5245         addpCode2pBlock(pbmerged, pb->pcHead);
5246         /* addpCode2pBlock doesn't handle the tail: */
5247         pbmerged->pcTail = pb->pcTail;
5248         
5249         pb->prev->next = pbn;
5250         if(pbn) 
5251           pbn->prev = pb->prev;
5252         
5253         
5254         pBlockDestruct(pb);
5255       }
5256       //printpBlock(stderr, pbmerged);
5257     } 
5258     pb = pbn;
5259   }
5260   
5261 }
5262
5263 /*-----------------------------------------------------------------*/
5264 /* AnalyzeFlow - Examine the flow of the code and optimize         */
5265 /*                                                                 */
5266 /* level 0 == minimal optimization                                 */
5267 /*   optimize registers that are used only by two instructions     */
5268 /* level 1 == maximal optimization                                 */
5269 /*   optimize by looking at pairs of instructions that use the     */
5270 /*   register.                                                     */
5271 /*-----------------------------------------------------------------*/
5272
5273 void AnalyzeFlow(int level)
5274 {
5275   static int times_called=0;
5276   
5277   pBlock *pb;
5278   
5279   if(!the_pFile)
5280     return;
5281   
5282   
5283   /* if this is not the first time this function has been called,
5284   then clean up old flow information */
5285   if(times_called++) {
5286     for(pb = the_pFile->pbHead; pb; pb = pb->next)
5287       unBuildFlow(pb);
5288     
5289     RegsUnMapLiveRanges();
5290     
5291   }
5292   
5293   GpcFlowSeq = 1;
5294   
5295   /* Phase 2 - Flow Analysis - Register Banking
5296   *
5297   * In this phase, the individual flow blocks are examined
5298   * and register banking is fixed.
5299   */
5300   
5301   //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5302   //FixRegisterBanking(pb);
5303   
5304   /* Phase 2 - Flow Analysis
5305   *
5306   * In this phase, the pCode is partition into pCodeFlow 
5307   * blocks. The flow blocks mark the points where a continuous
5308   * stream of instructions changes flow (e.g. because of
5309   * a call or goto or whatever).
5310   */
5311   
5312   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5313     BuildFlow(pb);
5314   
5315   
5316   /* Phase 2 - Flow Analysis - linking flow blocks
5317   *
5318   * In this phase, the individual flow blocks are examined
5319   * to determine their order of excution.
5320   */
5321   
5322   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5323     LinkFlow(pb);
5324   
5325   /* Phase 3 - Flow Analysis - Flow Tree
5326   *
5327   * In this phase, the individual flow blocks are examined
5328   * to determine their order of excution.
5329   */
5330   
5331   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5332     BuildFlowTree(pb);
5333   
5334   
5335   /* Phase x - Flow Analysis - Used Banks
5336   *
5337   * In this phase, the individual flow blocks are examined
5338   * to determine the Register Banks they use
5339   */
5340   
5341   //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
5342   //    FixBankFlow(pb);
5343   
5344   
5345   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5346     pCodeRegMapLiveRanges(pb);
5347   
5348   RemoveUnusedRegisters();
5349   
5350   //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
5351   pCodeRegOptimizeRegUsage(level);
5352   
5353   OptimizepCode('*');
5354   
5355   
5356   /*
5357   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5358   DumpFlow(pb);
5359   */
5360   /* debug stuff */
5361   /*
5362   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5363     pCode *pcflow;
5364     for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
5365     (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5366     pcflow = pcflow->next) {
5367     
5368     FillFlow(PCFL(pcflow));
5369     }
5370   }
5371   */
5372   /*
5373   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5374     pCode *pcflow;
5375     for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
5376     (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5377     pcflow = pcflow->next) {
5378   
5379     FlowStats(PCFL(pcflow));
5380     }
5381   }
5382   */
5383 }
5384
5385 /*-----------------------------------------------------------------*/
5386 /* AnalyzeBanking - Called after the memory addresses have been    */
5387 /*                  assigned to the registers.                     */
5388 /*                                                                 */
5389 /*-----------------------------------------------------------------*/
5390
5391 void AnalyzeBanking(void)
5392 {
5393   pBlock  *pb;
5394   
5395   if(!picIsInitialized()) {
5396     fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
5397     fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
5398     fprintf(stderr,"support/scripts/inc2h.pl\n");
5399     fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
5400     
5401     exit(1);
5402   }
5403   
5404   /* Phase x - Flow Analysis - Used Banks
5405   *
5406   * In this phase, the individual flow blocks are examined
5407   * to determine the Register Banks they use
5408   */
5409   
5410   AnalyzeFlow(0);
5411   AnalyzeFlow(1);
5412   
5413   //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
5414   //    BanksUsedFlow(pb);
5415   for(pb = the_pFile->pbHead; pb; pb = pb->next)
5416     FixRegisterBanking(pb,-1); // cur_bank is unknown
5417   
5418 }
5419
5420 /*-----------------------------------------------------------------*/
5421 /*-----------------------------------------------------------------*/
5422 DEFSETFUNC (resetrIdx)
5423 {
5424   if (!((regs *)item)->isFixed)
5425     ((regs *)item)->rIdx = 0;
5426   
5427   return 0;
5428 }
5429
5430 /*-----------------------------------------------------------------*/
5431 /* InitRegReuse - Initialises variables for code analyzer          */
5432 /*-----------------------------------------------------------------*/
5433
5434 void InitReuseReg(void)
5435 {
5436   /* Find end of statically allocated variables for start idx */
5437   unsigned maxIdx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5438   regs *r;
5439   for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5440     if (r->type != REG_SFR) {
5441       maxIdx += r->size; /* Increment for all statically allocated variables */
5442     }
5443   }
5444   peakIdx = maxIdx;
5445   applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5446 }
5447
5448 /*-----------------------------------------------------------------*/
5449 /*-----------------------------------------------------------------*/
5450 static unsigned register_reassign(pBlock *pb, unsigned idx)
5451 {
5452   pCode *pc;
5453   
5454   /* check recursion */
5455   pc = setFirstItem(pb->function_entries);
5456   if(!pc)
5457     return idx;
5458   
5459   pb->visited = 1;
5460   
5461   DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname));
5462   
5463   if (pb->tregisters) {
5464     regs *r;
5465     for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5466       if (r->type == REG_GPR) {
5467         if (!r->isFixed) {
5468           if (r->rIdx < (int)idx) {
5469             char s[20];
5470             r->rIdx = idx++;
5471             if (peakIdx < idx) peakIdx = idx;
5472             sprintf(s,"r0x%02X", r->rIdx);
5473             DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s));
5474             free(r->name);
5475             r->name = Safe_strdup(s);
5476           }
5477         }
5478       }
5479     }
5480   }
5481   for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5482     
5483     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5484       char *dest = get_op_from_instruction(PCI(pc));
5485       
5486       pCode *pcn = findFunction(dest);
5487       if(pcn) {
5488         register_reassign(pcn->pb,idx);
5489       }
5490     }
5491     
5492   }
5493   
5494   return idx;
5495 }
5496
5497 /*------------------------------------------------------------------*/
5498 /* ReuseReg were call tree permits                                  */
5499 /*                                                                  */
5500 /*  Re-allocate the GPR for optimum reuse for a given pblock        */ 
5501 /*  eg  if a function m() calls function f1() and f2(), where f1    */
5502 /*  allocates a local variable vf1 and f2 allocates a local         */
5503 /*  variable vf2. Then providing f1 and f2 do not call each other   */
5504 /*  they may share the same general purpose registers for vf1 and   */
5505 /*  vf2.                                                            */
5506 /*  This is done by first setting the the regs rIdx to start after  */
5507 /*  all the global variables, then walking through the call tree    */
5508 /*  renaming the registers to match their new idx and incrementng   */
5509 /*  it as it goes. If a function has already been called it will    */
5510 /*  only rename the registers if it has already used up those       */
5511 /*  registers ie rIdx of the function's registers is lower than the */
5512 /*  current rIdx. That way the register will not be reused while    */
5513 /*  still being used by an eariler function call.                   */
5514 /*                                                                  */
5515 /*  Note for this to work the fucntions need to be declared static. */
5516 /*                                                                  */
5517 /*------------------------------------------------------------------*/
5518 void ReuseReg(void)
5519 {
5520   pBlock  *pb;
5521   InitReuseReg();
5522   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5523     /* Non static functions can be called from other modules so their registers must reassign */
5524     if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
5525       register_reassign(pb,peakIdx);
5526   }
5527 }
5528
5529 /*-----------------------------------------------------------------*/
5530 /* buildCallTree - look at the flow and extract all of the calls   */
5531 /*                                                                 */
5532 /*-----------------------------------------------------------------*/
5533
5534 void buildCallTree(void    )
5535 {
5536   pBranch *pbr;
5537   pBlock  *pb;
5538   pCode   *pc;
5539   
5540   if(!the_pFile)
5541     return;
5542   
5543   /* Now build the call tree.
5544   First we examine all of the pCodes for functions.
5545   Keep in mind that the function boundaries coincide
5546   with pBlock boundaries. 
5547   
5548   The algorithm goes something like this:
5549   We have two nested loops. The outer loop iterates
5550   through all of the pBlocks/functions. The inner
5551   loop iterates through all of the pCodes for
5552   a given pBlock. When we begin iterating through
5553   a pBlock, the variable pc_fstart, pCode of the start
5554   of a function, is cleared. We then search for pCodes
5555   of type PC_FUNCTION. When one is encountered, we
5556   initialize pc_fstart to this and at the same time
5557   associate a new pBranch object that signifies a 
5558   branch entry. If a return is found, then this signifies
5559   a function exit point. We'll link the pCodes of these
5560   returns to the matching pc_fstart.
5561
5562   When we're done, a doubly linked list of pBranches
5563   will exist. The head of this list is stored in
5564   `the_pFile', which is the meta structure for all
5565   of the pCode. Look at the printCallTree function
5566   on how the pBranches are linked together.
5567
5568   */
5569   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5570     pCode *pc_fstart=NULL;
5571     for(pc = pb->pcHead; pc; pc = pc->next) {
5572       if(isPCF(pc)) {
5573         pCodeFunction *pcf = PCF(pc);
5574         if (pcf->fname) {
5575           
5576           if(STRCASECMP(pcf->fname, "_main") == 0) {
5577             //fprintf(stderr," found main \n");
5578             pb->cmemmap = NULL;  /* FIXME do we need to free ? */
5579             pb->dbName = 'M';
5580           }
5581           
5582           pbr = Safe_calloc(1,sizeof(pBranch));
5583           pbr->pc = pc_fstart = pc;
5584           pbr->next = NULL;
5585           
5586           the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5587           
5588           // Here's a better way of doing the same:
5589           addSet(&pb->function_entries, pc);
5590           
5591         } else {
5592           // Found an exit point in a function, e.g. return
5593           // (Note, there may be more than one return per function)
5594           if(pc_fstart)
5595             pBranchLink(PCF(pc_fstart), pcf);
5596           
5597           addSet(&pb->function_exits, pc);
5598         }
5599       } else if(isCALL(pc)) {
5600         addSet(&pb->function_calls,pc);
5601       }
5602     }
5603   }
5604 }
5605
5606 /*-----------------------------------------------------------------*/
5607 /* AnalyzepCode - parse the pCode that has been generated and form */
5608 /*                all of the logical connections.                  */
5609 /*                                                                 */
5610 /* Essentially what's done here is that the pCode flow is          */
5611 /* determined.                                                     */
5612 /*-----------------------------------------------------------------*/
5613
5614 void AnalyzepCode(char dbName)
5615 {
5616   pBlock *pb;
5617   int i,changes;
5618   
5619   if(!the_pFile)
5620     return;
5621   
5622   mergepBlocks('D');
5623   
5624   
5625   /* Phase 1 - Register allocation and peep hole optimization
5626   *
5627   * The first part of the analysis is to determine the registers
5628   * that are used in the pCode. Once that is done, the peep rules
5629   * are applied to the code. We continue to loop until no more
5630   * peep rule optimizations are found (or until we exceed the
5631   * MAX_PASSES threshold). 
5632   *
5633   * When done, the required registers will be determined.
5634   *
5635   */
5636   i = 0;
5637   do {
5638     
5639     DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5640     
5641     /* First, merge the labels with the instructions */
5642     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5643       if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5644         
5645         DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5646         pBlockMergeLabels(pb);
5647         AnalyzepBlock(pb);
5648       } else {
5649         DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
5650       }
5651     }
5652     
5653     changes = OptimizepCode(dbName);
5654     
5655   } while(changes && (i++ < MAX_PASSES));
5656   
5657   buildCallTree();
5658 }
5659
5660 /*-----------------------------------------------------------------*/
5661 /* ispCodeFunction - returns true if *pc is the pCode of a         */
5662 /*                   function                                      */
5663 /*-----------------------------------------------------------------*/
5664 bool ispCodeFunction(pCode *pc)
5665 {
5666   
5667   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5668     return 1;
5669   
5670   return 0;
5671 }
5672
5673 /*-----------------------------------------------------------------*/
5674 /* findFunction - Search for a function by name (given the name)   */
5675 /*                in the set of all functions that are in a pBlock */
5676 /* (note - I expect this to change because I'm planning to limit   */
5677 /*  pBlock's to just one function declaration                      */
5678 /*-----------------------------------------------------------------*/
5679 pCode *findFunction(char *fname)
5680 {
5681   pBlock *pb;
5682   pCode *pc;
5683   if(!fname)
5684     return NULL;
5685   
5686   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5687     
5688     pc = setFirstItem(pb->function_entries);
5689     while(pc) {
5690       
5691       if((pc->type == PC_FUNCTION) &&
5692         (PCF(pc)->fname) && 
5693         (strcmp(fname, PCF(pc)->fname)==0))
5694         return pc;
5695       
5696       pc = setNextItem(pb->function_entries);
5697       
5698     }
5699     
5700   }
5701   return NULL;
5702 }
5703
5704 void MarkUsedRegisters(set *regset)
5705 {
5706   
5707   regs *r1,*r2;
5708   
5709   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5710     r2 = pic14_regWithIdx(r1->rIdx);
5711     if (r2) {
5712       r2->isFree = 0;
5713       r2->wasUsed = 1;
5714     }
5715   }
5716 }
5717
5718 void pBlockStats(FILE *of, pBlock *pb)
5719 {
5720   
5721   pCode *pc;
5722   regs  *r;
5723   
5724   fprintf(of,";***\n;  pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5725   
5726   // for now just print the first element of each set
5727   pc = setFirstItem(pb->function_entries);
5728   if(pc) {
5729     fprintf(of,";entry:  ");
5730     pc->print(of,pc);
5731   }
5732   pc = setFirstItem(pb->function_exits);
5733   if(pc) {
5734     fprintf(of,";has an exit\n");
5735     //pc->print(of,pc);
5736   }
5737   
5738   pc = setFirstItem(pb->function_calls);
5739   if(pc) {
5740     fprintf(of,";functions called:\n");
5741     
5742     while(pc) {
5743       if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5744         fprintf(of,";   %s\n",get_op_from_instruction(PCI(pc)));
5745       }
5746       pc = setNextItem(pb->function_calls);
5747     }
5748   }
5749   
5750   r = setFirstItem(pb->tregisters);
5751   if(r) {
5752     int n = elementsInSet(pb->tregisters);
5753     
5754     fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5755     
5756     while (r) {
5757       fprintf(of,";   %s\n",r->name);
5758       r = setNextItem(pb->tregisters);
5759     }
5760   }
5761 }
5762
5763 /*-----------------------------------------------------------------*/
5764 /*-----------------------------------------------------------------*/
5765 #if 0
5766 static void sequencepCode(void)
5767 {
5768   pBlock *pb;
5769   pCode *pc;
5770   
5771   
5772   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5773     
5774     pb->seq = GpCodeSequenceNumber+1;
5775     
5776     for( pc = pb->pcHead; pc; pc = pc->next)
5777       pc->seq = ++GpCodeSequenceNumber;
5778   }
5779   
5780 }
5781 #endif
5782
5783 /*-----------------------------------------------------------------*/
5784 /*-----------------------------------------------------------------*/
5785 /*
5786 set *register_usage(pBlock *pb)
5787 {
5788   pCode *pc,*pcn;
5789   set *registers=NULL;
5790   set *registersInCallPath = NULL;
5791   
5792   / * check recursion * /
5793
5794   pc = setFirstItem(pb->function_entries);
5795   
5796   if(!pc)
5797     return registers;
5798   
5799   pb->visited = 1;
5800   
5801   if(pc->type != PC_FUNCTION)
5802     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5803
5804   pc = setFirstItem(pb->function_calls);
5805   for( ; pc; pc = setNextItem(pb->function_calls)) {
5806
5807     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5808       char *dest = get_op_from_instruction(PCI(pc));
5809
5810       pcn = findFunction(dest);
5811       if(pcn) 
5812         registersInCallPath = register_usage(pcn->pb);
5813     } else
5814       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5815
5816   }
5817
5818 #ifdef PCODE_DEBUG
5819   pBlockStats(stderr,pb);  // debug
5820 #endif
5821
5822   // Mark the registers in this block as used.
5823
5824   MarkUsedRegisters(pb->tregisters);
5825   if(registersInCallPath) {
5826     / * registers were used in the functions this pBlock has called * /
5827     / * so now, we need to see if these collide with the ones we are * /
5828     / * using here * /
5829
5830     regs *r1,*r2, *newreg;
5831
5832     DFPRINTF((stderr,"comparing registers\n"));
5833
5834     r1 = setFirstItem(registersInCallPath);
5835     while(r1) {
5836       if (r1->type != REG_STK) {
5837         r2 = setFirstItem(pb->tregisters);
5838
5839         while(r2 && (r2->type != REG_STK)) {
5840
5841           if(r2->rIdx == r1->rIdx) {
5842             newreg = pic14_findFreeReg(REG_GPR);
5843
5844
5845             if(!newreg) {
5846               DFPRINTF((stderr,"Bummer, no more registers.\n"));
5847               exit(1);
5848             }
5849
5850             DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5851               r1->rIdx, newreg->rIdx));
5852             r2->rIdx = newreg->rIdx;
5853             if(newreg->name)
5854               r2->name = Safe_strdup(newreg->name);
5855             else
5856               r2->name = NULL;
5857             newreg->isFree = 0;
5858             newreg->wasUsed = 1;
5859           }
5860           r2 = setNextItem(pb->tregisters);
5861         }
5862       }
5863
5864       r1 = setNextItem(registersInCallPath);
5865     }
5866
5867     / * Collisions have been resolved. Now free the registers in the call path * /
5868     r1 = setFirstItem(registersInCallPath);
5869     while(r1) {
5870       newreg = pic14_regWithIdx(r1->rIdx);
5871       if (newreg) newreg->isFree = 1;
5872         r1 = setNextItem(registersInCallPath);
5873     }
5874
5875   }// else
5876   //    MarkUsedRegisters(pb->registers);
5877
5878   registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5879 #ifdef PCODE_DEBUG
5880   if(registers) 
5881     DFPRINTF((stderr,"returning regs\n"));
5882   else
5883     DFPRINTF((stderr,"not returning regs\n"));
5884
5885   DFPRINTF((stderr,"pBlock after register optim.\n"));
5886   pBlockStats(stderr,pb);  // debug
5887 #endif
5888
5889   return registers;
5890 }
5891 */
5892
5893 /*-----------------------------------------------------------------*/
5894 /* printCallTree - writes the call tree to a file                  */
5895 /*                                                                 */
5896 /*-----------------------------------------------------------------*/
5897 void pct2(FILE *of,pBlock *pb,int indent)
5898 {
5899   pCode *pc,*pcn;
5900   int i;
5901   //  set *registersInCallPath = NULL;
5902   
5903   if(!of)
5904     return;
5905   
5906   if(indent > 10)
5907     return; //recursion ?
5908   
5909   pc = setFirstItem(pb->function_entries);
5910   
5911   if(!pc)
5912     return;
5913   
5914   pb->visited = 0;
5915   
5916   for(i=0;i<indent;i++)   // Indentation
5917     fputc(' ',of);
5918   
5919   if(pc->type == PC_FUNCTION)
5920     fprintf(of,"%s\n",PCF(pc)->fname);
5921   else
5922     return;  // ???
5923   
5924   
5925   pc = setFirstItem(pb->function_calls);
5926   for( ; pc; pc = setNextItem(pb->function_calls)) {
5927     
5928     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5929       char *dest = get_op_from_instruction(PCI(pc));
5930       
5931       pcn = findFunction(dest);
5932       if(pcn) 
5933         pct2(of,pcn->pb,indent+1);
5934     } else
5935       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5936     
5937   }
5938   
5939   
5940 }
5941
5942
5943 /*-----------------------------------------------------------------*/
5944 /* printCallTree - writes the call tree to a file                  */
5945 /*                                                                 */
5946 /*-----------------------------------------------------------------*/
5947
5948 void printCallTree(FILE *of)
5949 {
5950   pBranch *pbr;
5951   pBlock  *pb;
5952   pCode   *pc;
5953   
5954   if(!the_pFile)
5955     return;
5956   
5957   if(!of)
5958     of = stderr;
5959   
5960   fprintf(of, "\npBlock statistics\n");
5961   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
5962     pBlockStats(of,pb);
5963   
5964   
5965   
5966   fprintf(of,"Call Tree\n");
5967   pbr = the_pFile->functions;
5968   while(pbr) {
5969     if(pbr->pc) {
5970       pc = pbr->pc;
5971       if(!ispCodeFunction(pc))
5972         fprintf(of,"bug in call tree");
5973       
5974       
5975       fprintf(of,"Function: %s\n", PCF(pc)->fname);
5976       
5977       while(pc->next && !ispCodeFunction(pc->next)) {
5978         pc = pc->next;
5979         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5980           fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5981       }
5982     }
5983     
5984     pbr = pbr->next;
5985   }
5986   
5987   
5988   fprintf(of,"\n**************\n\na better call tree\n");
5989   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5990     if(pb->visited)
5991       pct2(of,pb,0);
5992   }
5993   
5994   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5995     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5996   }
5997 }
5998
5999
6000
6001 /*-----------------------------------------------------------------*/
6002 /*                                                                 */
6003 /*-----------------------------------------------------------------*/
6004
6005 void InlineFunction(pBlock *pb)
6006 {
6007   pCode *pc;
6008   pCode *pc_call;
6009   
6010   if(!pb)
6011     return;
6012   
6013   pc = setFirstItem(pb->function_calls);
6014   
6015   for( ; pc; pc = setNextItem(pb->function_calls)) {
6016     
6017     if(isCALL(pc)) {
6018       pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6019       pCode *pcp = pc->prev;
6020       pCode *pct;
6021       pCode *pce;
6022       
6023       pBranch *pbr;
6024       
6025       if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 1) && !PCF(pcn)->isPublic && (pcp && (isPCI_BITSKIP(pcp)||!isPCI_SKIP(pcp)))) { /* Bit skips can be inverted other skips can not */
6026         
6027         InlineFunction(pcn->pb);
6028         
6029         /*
6030         At this point, *pc points to a CALL mnemonic, and
6031         *pcn points to the function that is being called.
6032         
6033         To in-line this call, we need to remove the CALL
6034         and RETURN(s), and link the function pCode in with
6035         the CALLee pCode.
6036
6037         */
6038         
6039         pc_call = pc;
6040         
6041         /* Check if previous instruction was a bit skip */
6042         if (isPCI_BITSKIP(pcp)) {
6043           pCodeLabel *pcl;
6044           /* Invert skip instruction and add a goto */
6045           PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
6046           
6047           if(isPCL(pc_call->next)) { // Label pcode
6048             pcl = PCL(pc_call->next);
6049           } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
6050             pcl = PCL(PCI(pc_call->next)->label->pc);
6051           } else {
6052             pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
6053             PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
6054           }
6055           pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
6056         }
6057         
6058         /* remove callee pBlock from the pBlock linked list */
6059         removepBlock(pcn->pb);
6060         
6061         pce = pcn;
6062         while(pce) {
6063           pce->pb = pb;
6064           pce = pce->next;
6065         }
6066         
6067         /* Remove the Function pCode */
6068         pct = findNextInstruction(pcn->next);
6069         
6070         /* Link the function with the callee */
6071         if (pcp) pcp->next = pcn->next;
6072         pcn->next->prev = pcp;
6073         
6074         /* Convert the function name into a label */
6075         
6076         pbr = Safe_calloc(1,sizeof(pBranch));
6077         pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
6078         pbr->next = NULL;
6079         PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
6080         PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6081         
6082         /* turn all of the return's except the last into goto's */
6083         /* check case for 2 instruction pBlocks */
6084         pce = findNextInstruction(pcn->next);
6085         while(pce) {
6086           pCode *pce_next = findNextInstruction(pce->next);
6087           
6088           if(pce_next == NULL) {
6089             /* found the last return */
6090             pCode *pc_call_next =  findNextInstruction(pc_call->next);
6091             
6092             //fprintf(stderr,"found last return\n");
6093             //pce->print(stderr,pce);
6094             pce->prev->next = pc_call->next;
6095             pc_call->next->prev = pce->prev;
6096             PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
6097               PCI(pce)->label);
6098           }
6099           
6100           pce = pce_next;
6101         }
6102         
6103       }
6104     } else
6105       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6106     
6107   }
6108   
6109 }
6110
6111 /*-----------------------------------------------------------------*/
6112 /*                                                                 */
6113 /*-----------------------------------------------------------------*/
6114
6115 void InlinepCode(void)
6116 {
6117   
6118   pBlock  *pb;
6119   pCode   *pc;
6120   
6121   if(!the_pFile)
6122     return;
6123   
6124   if(!functionInlining)
6125     return;
6126   
6127     /* Loop through all of the function definitions and count the
6128   * number of times each one is called */
6129   //fprintf(stderr,"inlining %d\n",__LINE__);
6130   
6131   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6132     
6133     pc = setFirstItem(pb->function_calls);
6134     
6135     for( ; pc; pc = setNextItem(pb->function_calls)) {
6136       
6137       if(isCALL(pc)) {
6138         pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
6139         if(pcn && isPCF(pcn)) {
6140           PCF(pcn)->ncalled++;
6141         }
6142       } else
6143         fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6144       
6145     }
6146   }
6147   
6148   //fprintf(stderr,"inlining %d\n",__LINE__);
6149   
6150   /* Now, Loop through the function definitions again, but this
6151   * time inline those functions that have only been called once. */
6152   
6153   InlineFunction(the_pFile->pbHead);
6154   //fprintf(stderr,"inlining %d\n",__LINE__);
6155   
6156   for(pb = the_pFile->pbHead; pb; pb = pb->next)
6157     unBuildFlow(pb);
6158   
6159 }