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