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