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