]> git.gag.com Git - fw/sdcc/blob - src/pic16/pcode.c
2004-01-16 Vangelis Rokas <vrokas@otenet.gr>
[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         if(pic16_pcode_verbose) {
3612                 fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
3613                         __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
3614         }
3615
3616   return pcop;
3617 }
3618
3619 /*-----------------------------------------------------------------*/
3620 /*-----------------------------------------------------------------*/
3621
3622 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
3623 {
3624   pCodeOp *pcop;
3625
3626   switch(type) {
3627   case PO_BIT:
3628   case PO_GPR_BIT:
3629     pcop = pic16_newpCodeOpBit(name, -1,0);
3630     break;
3631
3632   case PO_LITERAL:
3633     pcop = pic16_newpCodeOpLit(-1);
3634     break;
3635
3636   case PO_LABEL:
3637     pcop = pic16_newpCodeOpLabel(NULL,-1);
3638     break;
3639   case PO_GPR_TEMP:
3640     pcop = pic16_newpCodeOpReg(-1);
3641     break;
3642
3643   case PO_GPR_REGISTER:
3644     if(name)
3645       pcop = pic16_newpCodeOpRegFromStr(name);
3646     else
3647       pcop = pic16_newpCodeOpReg(-1);
3648     break;
3649
3650   default:
3651     pcop = Safe_calloc(1,sizeof(pCodeOp) );
3652     pcop->type = type;
3653     if(name)
3654       pcop->name = Safe_strdup(name);   
3655     else
3656       pcop->name = NULL;
3657   }
3658
3659   return pcop;
3660 }
3661
3662 /*-----------------------------------------------------------------*/
3663 /*-----------------------------------------------------------------*/
3664 void pic16_pCodeConstString(char *name, char *value)
3665 {
3666   pBlock *pb;
3667
3668   //  fprintf(stderr, " %s  %s  %s\n",__FUNCTION__,name,value);
3669
3670   if(!name || !value)
3671     return;
3672
3673   pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3674
3675   pic16_addpBlock(pb);
3676
3677   sprintf(buffer,"; %s = %s",name,value);
3678   
3679   pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
3680   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
3681
3682   do {
3683     pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(*value)));
3684   }while (*value++);
3685
3686
3687 }
3688
3689 /*-----------------------------------------------------------------*/
3690 /*-----------------------------------------------------------------*/
3691 #if 0
3692 static void pCodeReadCodeTable(void)
3693 {
3694   pBlock *pb;
3695
3696   fprintf(stderr, " %s\n",__FUNCTION__);
3697
3698   pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
3699
3700   pic16_addpBlock(pb);
3701
3702   pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
3703   pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
3704   pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
3705   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
3706
3707   pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
3708   pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
3709   pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
3710   pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
3711
3712
3713 }
3714 #endif
3715 /*-----------------------------------------------------------------*/
3716 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list   */
3717 /*-----------------------------------------------------------------*/
3718 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
3719 {
3720
3721   if(!pc)
3722     return;
3723
3724   if(!pb->pcHead) {
3725     /* If this is the first pcode to be added to a block that
3726      * was initialized with a NULL pcode, then go ahead and
3727      * make this pcode the head and tail */
3728     pb->pcHead  = pb->pcTail = pc;
3729   } else {
3730     //    if(pb->pcTail)
3731     pb->pcTail->next = pc;
3732
3733     pc->prev = pb->pcTail;
3734     pc->pb = pb;
3735
3736     pb->pcTail = pc;
3737   }
3738 }
3739
3740 /*-----------------------------------------------------------------*/
3741 /* pic16_addpBlock - place a pBlock into the pFile                 */
3742 /*-----------------------------------------------------------------*/
3743 void pic16_addpBlock(pBlock *pb)
3744 {
3745   // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
3746
3747   if(!the_pFile) {
3748     /* First time called, we'll pass through here. */
3749     //_ALLOC(the_pFile,sizeof(pFile));
3750     the_pFile = Safe_calloc(1,sizeof(pFile));
3751     the_pFile->pbHead = the_pFile->pbTail = pb;
3752     the_pFile->functions = NULL;
3753     return;
3754   }
3755
3756   the_pFile->pbTail->next = pb;
3757   pb->prev = the_pFile->pbTail;
3758   pb->next = NULL;
3759   the_pFile->pbTail = pb;
3760 }
3761
3762 /*-----------------------------------------------------------------*/
3763 /* removepBlock - remove a pBlock from the pFile                   */
3764 /*-----------------------------------------------------------------*/
3765 static void removepBlock(pBlock *pb)
3766 {
3767   pBlock *pbs;
3768
3769   if(!the_pFile)
3770     return;
3771
3772
3773   //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
3774
3775   for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
3776     if(pbs == pb) {
3777
3778       if(pbs == the_pFile->pbHead)
3779         the_pFile->pbHead = pbs->next;
3780
3781       if (pbs == the_pFile->pbTail) 
3782         the_pFile->pbTail = pbs->prev;
3783
3784       if(pbs->next)
3785         pbs->next->prev = pbs->prev;
3786
3787       if(pbs->prev)
3788         pbs->prev->next = pbs->next;
3789
3790       return;
3791
3792     }
3793   }
3794
3795   fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
3796
3797 }
3798
3799 /*-----------------------------------------------------------------*/
3800 /* printpCode - write the contents of a pCode to a file            */
3801 /*-----------------------------------------------------------------*/
3802 static void printpCode(FILE *of, pCode *pc)
3803 {
3804
3805   if(!pc || !of)
3806     return;
3807
3808   if(pc->print) {
3809     pc->print(of,pc);
3810     return;
3811   }
3812
3813   fprintf(of,"warning - unable to print pCode\n");
3814 }
3815
3816 /*-----------------------------------------------------------------*/
3817 /* pic16_printpBlock - write the contents of a pBlock to a file    */
3818 /*-----------------------------------------------------------------*/
3819 void pic16_printpBlock(FILE *of, pBlock *pb)
3820 {
3821   pCode *pc;
3822
3823         if(!pb)return;
3824
3825         if(!of)of=stderr;
3826
3827 #if 0
3828         if(pb->dbName == 'A') {
3829           absSym *ab;
3830
3831                 PCF(pb->pcHead)->
3832                 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet))
3833                         if(strcmp(ab->name, 
3834 //              fprintf(of, "%s\tcode\t%d"
3835         }
3836 #endif
3837
3838         for(pc = pb->pcHead; pc; pc = pc->next) {
3839                 if(isPCF(pc) && PCF(pc)->fname) {
3840                         fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
3841                         if(pb->dbName == 'A') {
3842                           absSym *ab;
3843                                 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet))
3844                                         if(strcmp(ab->name, PCF(pc)->fname)) {
3845                                                 fprintf(of, "\t0X%06X", ab->address);
3846                                                 break;
3847                                         }
3848                         }
3849                         fprintf(of, "\n");
3850                 }
3851                 printpCode(of,pc);
3852         }
3853 }
3854
3855 /*-----------------------------------------------------------------*/
3856 /*                                                                 */
3857 /*       pCode processing                                          */
3858 /*                                                                 */
3859 /*                                                                 */
3860 /*                                                                 */
3861 /*-----------------------------------------------------------------*/
3862
3863 void pic16_unlinkpCode(pCode *pc)
3864 {
3865
3866
3867   if(pc) {
3868 #ifdef PCODE_DEBUG
3869     fprintf(stderr,"Unlinking: ");
3870     printpCode(stderr, pc);
3871 #endif
3872     if(pc->prev) 
3873       pc->prev->next = pc->next;
3874     if(pc->next)
3875       pc->next->prev = pc->prev;
3876
3877     pc->prev = pc->next = NULL;
3878   }
3879 }
3880
3881 /*-----------------------------------------------------------------*/
3882 /*-----------------------------------------------------------------*/
3883
3884 static void genericDestruct(pCode *pc)
3885 {
3886
3887   pic16_unlinkpCode(pc);
3888
3889   if(isPCI(pc)) {
3890     /* For instructions, tell the register (if there's one used)
3891      * that it's no longer needed */
3892     regs *reg = pic16_getRegFromInstruction(pc);
3893     if(reg)
3894       deleteSetItem (&(reg->reglives.usedpCodes),pc);
3895
3896         if(PCI(pc)->is2MemOp) {
3897                 reg = pic16_getRegFromInstruction2(pc);
3898                 if(reg)
3899                         deleteSetItem(&(reg->reglives.usedpCodes), pc);
3900         }
3901   }
3902
3903   /* Instead of deleting the memory used by this pCode, mark
3904    * the object as bad so that if there's a pointer to this pCode
3905    * dangling around somewhere then (hopefully) when the type is
3906    * checked we'll catch it.
3907    */
3908
3909   pc->type = PC_BAD;
3910
3911   pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3912
3913   //free(pc);
3914
3915 }
3916
3917
3918
3919 /*-----------------------------------------------------------------*/
3920 /*-----------------------------------------------------------------*/
3921 /* modifiers for constant immediate */
3922 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
3923
3924 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
3925 {
3926   regs *r;
3927   static char b[50];
3928   char *s;
3929   int use_buffer = 1;    // copy the string to the passed buffer pointer
3930
3931   if(!buffer) {
3932     buffer = b;
3933     size = sizeof(b);
3934     use_buffer = 0;     // Don't bother copying the string to the buffer.
3935   } 
3936
3937   if(pcop) {
3938     switch(pcop->type) {
3939     case PO_INDF0:
3940     case PO_FSR0:
3941       if(use_buffer) {
3942         SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3943         return buffer;
3944       }
3945       return PCOR(pcop)->r->name;
3946       break;
3947     case PO_GPR_TEMP:
3948       r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
3949
3950       if(use_buffer) {
3951         SAFE_snprintf(&buffer,&size,"%s",r->name);
3952         return buffer;
3953       }
3954
3955       return r->name;
3956
3957
3958     case PO_IMMEDIATE:
3959         s = buffer;
3960
3961         if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3962                 if(PCOI(pcop)->index) {
3963                         SAFE_snprintf(&s,&size, "%s(%s + %d)",
3964                                 immdmod[ PCOI(pcop)->offset ],
3965                                 pcop->name,
3966                                 PCOI(pcop)->index);
3967                 } else {
3968                         SAFE_snprintf(&s,&size,"%s(%s)",
3969                                 immdmod[ PCOI(pcop)->offset ],
3970                                 pcop->name);
3971                 }
3972         } else {
3973                 if(PCOI(pcop)->index) {
3974                         SAFE_snprintf(&s,&size, "%s(%s + %d)",
3975                                 immdmod[ 0 ],
3976                                 pcop->name,
3977                                 PCOI(pcop)->index);
3978                 } else {
3979                         SAFE_snprintf(&s,&size, "%s(%s)",
3980                                 immdmod[ 0 ],
3981                                 pcop->name);
3982                 }
3983         }
3984                 
3985 #if 0
3986         if(PCOI(pcop)->_const) {
3987                 if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
3988                         if(PCOI(pcop)->index) {
3989                                 SAFE_snprintf(&s,&size,"%s(%s + %d)",
3990                                         immdmod[ PCOI(pcop)->offset ],
3991                                         pcop->name,
3992                                         PCOI(pcop)->index);
3993                         } else {
3994                                 SAFE_snprintf(&s,&size,"%s(%s)",
3995                                         immdmod[ PCOI(pcop)->offset ],
3996                                         pcop->name);
3997                         }
3998
3999                 } else {
4000                         if(PCOI(pcop)->index)
4001                                 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4002                         else
4003                                 SAFE_snprintf(&s,&size,"LOW(%s)",pcop->name);
4004                 }
4005         } else {
4006                 if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) 
4007                         SAFE_snprintf(&s,&size,"(%s + %d)",
4008                                 pcop->name,
4009                                 PCOI(pcop)->index );
4010                 } else {
4011                         if(PCOI(pcop)->offset)
4012                                 SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4013                         else
4014                                 SAFE_snprintf(&s,&size,"(%s)",pcop->name);
4015                 }
4016         }
4017 #endif
4018
4019         return buffer;
4020
4021     case PO_DIR:
4022       s = buffer;
4023       //size = sizeof(buffer);
4024       if( PCOR(pcop)->instance) {
4025                 SAFE_snprintf(&s,&size,"(%s + %d)",
4026                         pcop->name,
4027                         PCOR(pcop)->instance );
4028         }
4029         //fprintf(stderr,"PO_DIR %s\n",buffer);
4030        else
4031         SAFE_snprintf(&s,&size,"%s",pcop->name);
4032       return buffer;
4033
4034     default:
4035       if  (pcop->name) {
4036         if(use_buffer) {
4037           SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4038           return buffer;
4039         }
4040         return pcop->name;
4041       }
4042
4043     }
4044   }
4045
4046   return "NO operand";
4047
4048 }
4049
4050 /*-----------------------------------------------------------------*/
4051 /* pic16_get_op2 - variant to support two memory operand commands  */
4052 /*-----------------------------------------------------------------*/
4053 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4054 {
4055   regs *r;
4056   static char b[50];
4057   char *s;
4058   int use_buffer = 1;    // copy the string to the passed buffer pointer
4059
4060   if(!buffer) {
4061     buffer = b;
4062     size = sizeof(b);
4063     use_buffer = 0;     // Don't bother copying the string to the buffer.
4064   } 
4065
4066 #if 0
4067         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",
4068                 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4069                 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4070 #endif
4071
4072   if(pcop) {
4073     switch(PCOR2(pcop)->pcop2->type) {
4074     case PO_INDF0:
4075     case PO_FSR0:
4076       if(use_buffer) {
4077         SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4078         return buffer;
4079       }
4080       return PCOR(PCOR2(pcop)->pcop2)->r->name;
4081       break;
4082     case PO_GPR_TEMP:
4083       r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4084
4085       if(use_buffer) {
4086         SAFE_snprintf(&buffer,&size,"%s",r->name);
4087         return buffer;
4088       }
4089
4090       return r->name;
4091
4092
4093     case PO_IMMEDIATE:
4094         break;
4095 #if 0
4096       s = buffer;
4097
4098       if(PCOI(pcop)->_const) {
4099
4100         if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4101           SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4102                         pcop->name,
4103                         PCOI(pcop)->index,
4104                         8 * PCOI(pcop)->offset );
4105         } else
4106           SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4107       } else {
4108       
4109         if( PCOI(pcop)->index) { // && PCOI(pcc->pcop)->offset<4) {
4110           SAFE_snprintf(&s,&size,"(%s + %d)",
4111                         pcop->name,
4112                         PCOI(pcop)->index );
4113         } else {
4114           if(PCOI(pcop)->offset)
4115             SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4116           else
4117             SAFE_snprintf(&s,&size,"%s",pcop->name);
4118         }
4119       }
4120
4121       return buffer;
4122 #endif
4123
4124     case PO_DIR:
4125       s = buffer;
4126       //size = sizeof(buffer);
4127       if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4128                 SAFE_snprintf(&s,&size,"(%s + %d)",
4129                         PCOR(PCOR2(pcop)->pcop2)->r->name,
4130                         PCOR(PCOR2(pcop)->pcop2)->instance );
4131         }
4132         //fprintf(stderr,"PO_DIR %s\n",buffer);
4133        else
4134         SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4135       return buffer;
4136
4137     default:
4138 #if 0
4139       if  (PCOR2(pcop)->r1->name) {
4140         if(use_buffer) {
4141           SAFE_snprintf(&buffer,&size,"%s",PCOR2(pcop)->r1->name);
4142           return buffer;
4143         }
4144         return PCOR2(pcop)->r1->name;
4145       }
4146 #else
4147       break;
4148 #endif
4149     }
4150   }
4151
4152   return "NO operand";
4153
4154 }
4155
4156 /*-----------------------------------------------------------------*/
4157 /*-----------------------------------------------------------------*/
4158 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4159 {
4160
4161   if(pcc )
4162     return pic16_get_op(pcc->pcop,NULL,0);
4163
4164   /* gcc 3.2:  warning: concatenation of string literals with __FUNCTION__ is deprecated 
4165    *   return ("ERROR Null: "__FUNCTION__);
4166    */
4167   return ("ERROR Null: pic16_get_op_from_instruction");
4168
4169 }
4170
4171 /*-----------------------------------------------------------------*/
4172 /*-----------------------------------------------------------------*/
4173 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4174 {
4175
4176   fprintf(of,"pcodeopprint- not implemented\n");
4177 }
4178
4179 /*-----------------------------------------------------------------*/
4180 /* pic16_pCode2str - convert a pCode instruction to string               */
4181 /*-----------------------------------------------------------------*/
4182 static char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4183 {
4184   char *s = str;
4185   regs *r;
4186
4187 #if 0
4188         if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4189                 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4190                         __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4191                 exit(-1);
4192         }
4193 #endif
4194
4195   switch(pc->type) {
4196
4197   case PC_OPCODE:
4198     SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4199
4200     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4201
4202         if(PCI(pc)->is2MemOp) {
4203                 SAFE_snprintf(&s,&size, "%s, %s", 
4204                 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4205                 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4206                 break;
4207         }
4208
4209         if(PCI(pc)->is2LitOp) {
4210                 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4211                 break;
4212         }
4213
4214       if(PCI(pc)->isBitInst) {
4215         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4216           if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4217             SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
4218                           PCI(pc)->pcop->name ,
4219                           PCI(pc)->pcop->name );
4220           else
4221             SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)), 
4222                           (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4223         } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4224           SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4225         }else
4226           SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4227         //PCI(pc)->pcop->t.bit );
4228       } else {
4229
4230         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4231           if( PCI(pc)->num_ops == 3)
4232             SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4233           else
4234             SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4235
4236         }else {
4237           SAFE_snprintf(&s,&size,"%s",pic16_get_op_from_instruction(PCI(pc)));
4238
4239                 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4240                         if(PCI(pc)->num_ops == 3)
4241                                 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4242
4243                         r = pic16_getRegFromInstruction(pc);
4244 //                      fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4245 //                                      __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4246
4247                         if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", "B");
4248           }
4249         }
4250       }
4251
4252     }
4253     break;
4254
4255   case PC_COMMENT:
4256     /* assuming that comment ends with a \n */
4257     SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4258     break;
4259
4260   case PC_INLINE:
4261     /* assuming that inline code ends with a \n */
4262     SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4263     break;
4264
4265   case PC_LABEL:
4266     SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4267     break;
4268   case PC_FUNCTION:
4269     SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4270     break;
4271   case PC_WILD:
4272     SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4273     break;
4274   case PC_FLOW:
4275     SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4276     break;
4277   case PC_CSOURCE:
4278     SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4279     break;
4280   case PC_ASMDIR:
4281         SAFE_snprintf(&s,&size,"\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4282         break;
4283
4284   case PC_BAD:
4285     SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4286   }
4287
4288   return str;
4289
4290 }
4291
4292 /*-----------------------------------------------------------------*/
4293 /* genericPrint - the contents of a pCode to a file                */
4294 /*-----------------------------------------------------------------*/
4295 static void genericPrint(FILE *of, pCode *pc)
4296 {
4297
4298   if(!pc || !of)
4299     return;
4300
4301   switch(pc->type) {
4302   case PC_COMMENT:
4303     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4304     break;
4305
4306   case PC_INLINE:
4307     fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4308      break;
4309
4310   case PC_OPCODE:
4311     // If the opcode has a label, print that first
4312     {
4313       pBranch *pbl = PCI(pc)->label;
4314       while(pbl && pbl->pc) {
4315         if(pbl->pc->type == PC_LABEL)
4316           pCodePrintLabel(of, pbl->pc);
4317         pbl = pbl->next;
4318       }
4319     }
4320
4321     if(PCI(pc)->cline) 
4322       genericPrint(of,PCODE(PCI(pc)->cline));
4323
4324     {
4325       char str[256];
4326       
4327       pic16_pCode2str(str, 256, pc);
4328
4329       fprintf(of,"%s",str);
4330
4331       /* Debug */
4332       if(pic16_debug_verbose) {
4333         fprintf(of, "\t;key=%03x",pc->seq);
4334         if(PCI(pc)->pcflow)
4335           fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4336       }
4337     }
4338     fprintf(of, "\n");
4339     break;
4340       
4341   case PC_WILD:
4342     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4343     if(PCW(pc)->pci.label)
4344       pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4345
4346     if(PCW(pc)->operand) {
4347       fprintf(of,";\toperand  ");
4348       pCodeOpPrint(of,PCW(pc)->operand );
4349     }
4350     break;
4351
4352   case PC_FLOW:
4353     if(pic16_debug_verbose) {
4354       fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4355       if(PCFL(pc)->ancestor)
4356         fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4357       fprintf(of,"\n");
4358
4359     }
4360     break;
4361
4362   case PC_CSOURCE:
4363     fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4364     break;
4365   case PC_ASMDIR:
4366         {
4367           pBranch *pbl = PCAD(pc)->label;
4368                 while(pbl && pbl->pc) {
4369                         if(pbl->pc->type == PC_LABEL)
4370                                 pCodePrintLabel(of, pbl->pc);
4371                         pbl = pbl->next;
4372                 }
4373         }
4374         fprintf(of, "\t%s\t%s\n", PCAD(pc)->directive, PCAD(pc)->arg?PCAD(pc)->arg:"");
4375         break;
4376         
4377   case PC_LABEL:
4378   default:
4379     fprintf(of,"unknown pCode type %d\n",pc->type);
4380   }
4381
4382 }
4383
4384 /*-----------------------------------------------------------------*/
4385 /* pCodePrintFunction - prints function begin/end                  */
4386 /*-----------------------------------------------------------------*/
4387
4388 static void pCodePrintFunction(FILE *of, pCode *pc)
4389 {
4390
4391   if(!pc || !of)
4392     return;
4393
4394 #if 0
4395   if( ((pCodeFunction *)pc)->modname) 
4396     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4397 #endif
4398
4399   if(PCF(pc)->fname) {
4400     pBranch *exits = PCF(pc)->to;
4401     int i=0;
4402     fprintf(of,"%s", PCF(pc)->fname);
4403     
4404 //      if(pic16_pcode_verbose)
4405                 fprintf(of, "\t;Function start");
4406     
4407     fprintf(of, "\n");
4408     
4409     while(exits) {
4410       i++;
4411       exits = exits->next;
4412     }
4413     //if(i) i--;
4414
4415         if(pic16_pcode_verbose)
4416                 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4417     
4418   } else {
4419         if((PCF(pc)->from && 
4420                 PCF(pc)->from->pc->type == PC_FUNCTION &&
4421                 PCF(PCF(pc)->from->pc)->fname) ) {
4422
4423                 if(pic16_pcode_verbose)
4424                         fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4425         } else {
4426                 if(pic16_pcode_verbose)
4427                         fprintf(of,"; exit point [can't find entry point]\n");
4428         }
4429         fprintf(of, "\n");
4430   }
4431 }
4432 /*-----------------------------------------------------------------*/
4433 /* pCodePrintLabel - prints label                                  */
4434 /*-----------------------------------------------------------------*/
4435
4436 static void pCodePrintLabel(FILE *of, pCode *pc)
4437 {
4438
4439   if(!pc || !of)
4440     return;
4441
4442   if(PCL(pc)->label) 
4443     fprintf(of,"%s:\n",PCL(pc)->label);
4444   else if (PCL(pc)->key >=0) 
4445     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
4446   else
4447     fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
4448
4449 }
4450 /*-----------------------------------------------------------------*/
4451 /* unlinkpCodeFromBranch - Search for a label in a pBranch and     */
4452 /*                         remove it if it is found.               */
4453 /*-----------------------------------------------------------------*/
4454 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
4455 {
4456   pBranch *b, *bprev;
4457
4458
4459   bprev = NULL;
4460
4461   if(pcl->type == PC_OPCODE)
4462     b = PCI(pcl)->label;
4463   else {
4464     fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
4465     exit(1);
4466
4467   }
4468
4469   //fprintf (stderr, "%s \n",__FUNCTION__);
4470   //pcl->print(stderr,pcl);
4471   //pc->print(stderr,pc);
4472   while(b) {
4473     if(b->pc == pc) {
4474       //fprintf (stderr, "found label\n");
4475
4476       /* Found a label */
4477       if(bprev) {
4478         bprev->next = b->next;  /* Not first pCode in chain */
4479         free(b);
4480       } else {
4481         pc->destruct(pc);
4482         PCI(pcl)->label = b->next;   /* First pCode in chain */
4483         free(b);
4484       }
4485       return;  /* A label can't occur more than once */
4486     }
4487     bprev = b;
4488     b = b->next;
4489   }
4490
4491 }
4492
4493 /*-----------------------------------------------------------------*/
4494 /*-----------------------------------------------------------------*/
4495 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
4496 {
4497   pBranch *b;
4498
4499   if(!h)
4500     return n;
4501
4502   if(h == n)
4503     return n;
4504
4505   b = h;
4506   while(b->next)
4507     b = b->next;
4508
4509   b->next = n;
4510
4511   return h;
4512   
4513 }  
4514 /*-----------------------------------------------------------------*/
4515 /* pBranchLink - given two pcodes, this function will link them    */
4516 /*               together through their pBranches                  */
4517 /*-----------------------------------------------------------------*/
4518 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
4519 {
4520   pBranch *b;
4521
4522   // Declare a new branch object for the 'from' pCode.
4523
4524   //_ALLOC(b,sizeof(pBranch));
4525   b = Safe_calloc(1,sizeof(pBranch));
4526   b->pc = PCODE(t);             // The link to the 'to' pCode.
4527   b->next = NULL;
4528
4529   f->to = pic16_pBranchAppend(f->to,b);
4530
4531   // Now do the same for the 'to' pCode.
4532
4533   //_ALLOC(b,sizeof(pBranch));
4534   b = Safe_calloc(1,sizeof(pBranch));
4535   b->pc = PCODE(f);
4536   b->next = NULL;
4537
4538   t->from = pic16_pBranchAppend(t->from,b);
4539   
4540 }
4541
4542 #if 0
4543 /*-----------------------------------------------------------------*/
4544 /* pBranchFind - find the pBranch in a pBranch chain that contains */
4545 /*               a pCode                                           */
4546 /*-----------------------------------------------------------------*/
4547 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
4548 {
4549   while(pb) {
4550
4551     if(pb->pc == pc)
4552       return pb;
4553
4554     pb = pb->next;
4555   }
4556
4557   return NULL;
4558 }
4559
4560 /*-----------------------------------------------------------------*/
4561 /* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
4562 /*-----------------------------------------------------------------*/
4563 static void pCodeUnlink(pCode *pc)
4564 {
4565   pBranch *pb1,*pb2;
4566   pCode *pc1;
4567
4568   if(!pc->prev || !pc->next) {
4569     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
4570     exit(1);
4571   }
4572
4573   /* first remove the pCode from the chain */
4574   pc->prev->next = pc->next;
4575   pc->next->prev = pc->prev;
4576
4577   /* Now for the hard part... */
4578
4579   /* Remove the branches */
4580
4581   pb1 = pc->from;
4582   while(pb1) {
4583     pc1 = pb1->pc;    /* Get the pCode that branches to the
4584                        * one we're unlinking */
4585
4586     /* search for the link back to this pCode (the one we're
4587      * unlinking) */
4588     if(pb2 = pBranchFind(pc1->to,pc)) {
4589       pb2->pc = pc->to->pc;  // make the replacement
4590
4591       /* if the pCode we're unlinking contains multiple 'to'
4592        * branches (e.g. this a skip instruction) then we need
4593        * to copy these extra branches to the chain. */
4594       if(pc->to->next)
4595         pic16_pBranchAppend(pb2, pc->to->next);
4596     }
4597     
4598     pb1 = pb1->next;
4599   }
4600
4601
4602 }
4603 #endif
4604 /*-----------------------------------------------------------------*/
4605 /*-----------------------------------------------------------------*/
4606 #if 0
4607 static void genericAnalyze(pCode *pc)
4608 {
4609   switch(pc->type) {
4610   case PC_WILD:
4611   case PC_COMMENT:
4612     return;
4613   case PC_LABEL:
4614   case PC_FUNCTION:
4615   case PC_OPCODE:
4616     {
4617       // Go through the pCodes that are in pCode chain and link
4618       // them together through the pBranches. Note, the pCodes
4619       // are linked together as a contiguous stream like the 
4620       // assembly source code lines. The linking here mimics this
4621       // except that comments are not linked in.
4622       // 
4623       pCode *npc = pc->next;
4624       while(npc) {
4625         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
4626           pBranchLink(pc,npc);
4627           return;
4628         } else
4629           npc = npc->next;
4630       }
4631       /* reached the end of the pcode chain without finding
4632        * an instruction we could link to. */
4633     }
4634     break;
4635   case PC_FLOW:
4636     fprintf(stderr,"analyze PC_FLOW\n");
4637
4638     return;
4639   case PC_BAD:
4640     fprintf(stderr,,";A bad pCode is being used\n");
4641
4642   }
4643 }
4644 #endif
4645
4646 /*-----------------------------------------------------------------*/
4647 /*-----------------------------------------------------------------*/
4648 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
4649 {
4650   pBranch *pbr;
4651
4652   if(pc->type == PC_LABEL) {
4653     if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
4654       return TRUE;
4655   }
4656   if(pc->type == PC_OPCODE) {
4657     pbr = PCI(pc)->label;
4658     while(pbr) {
4659       if(pbr->pc->type == PC_LABEL) {
4660         if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
4661           return TRUE;
4662       }
4663       pbr = pbr->next;
4664     }
4665   }
4666
4667   return FALSE;
4668 }
4669
4670 /*-----------------------------------------------------------------*/
4671 /*-----------------------------------------------------------------*/
4672 static int checkLabel(pCode *pc)
4673 {
4674   pBranch *pbr;
4675
4676   if(pc && isPCI(pc)) {
4677     pbr = PCI(pc)->label;
4678     while(pbr) {
4679       if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
4680         return TRUE;
4681
4682       pbr = pbr->next;
4683     }
4684   }
4685
4686   return FALSE;
4687 }
4688
4689 /*-----------------------------------------------------------------*/
4690 /* findLabelinpBlock - Search the pCode for a particular label     */
4691 /*-----------------------------------------------------------------*/
4692 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
4693 {
4694   pCode  *pc;
4695
4696   if(!pb)
4697     return NULL;
4698
4699   for(pc = pb->pcHead; pc; pc = pc->next) 
4700     if(compareLabel(pc,pcop_label))
4701       return pc;
4702     
4703   return NULL;
4704 }
4705 #if 0
4706 /*-----------------------------------------------------------------*/
4707 /* findLabel - Search the pCode for a particular label             */
4708 /*-----------------------------------------------------------------*/
4709 static pCode * findLabel(pCodeOpLabel *pcop_label)
4710 {
4711   pBlock *pb;
4712   pCode  *pc;
4713
4714   if(!the_pFile)
4715     return NULL;
4716
4717   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
4718     if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
4719       return pc;
4720   }
4721
4722   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
4723   return NULL;
4724 }
4725 #endif
4726 /*-----------------------------------------------------------------*/
4727 /* pic16_findNextpCode - given a pCode, find the next of type 'pct'      */
4728 /*                 in the linked list                              */
4729 /*-----------------------------------------------------------------*/
4730 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
4731 {
4732
4733   while(pc) {
4734     if(pc->type == pct)
4735       return pc;
4736
4737     pc = pc->next;
4738   }
4739
4740   return NULL;
4741 }
4742
4743 /*-----------------------------------------------------------------*/
4744 /* findPrevpCode - given a pCode, find the previous of type 'pct'  */
4745 /*                 in the linked list                              */
4746 /*-----------------------------------------------------------------*/
4747 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
4748 {
4749
4750   while(pc) {
4751     if(pc->type == pct)
4752       return pc;
4753
4754     pc = pc->prev;
4755   }
4756
4757   return NULL;
4758 }
4759 /*-----------------------------------------------------------------*/
4760 /* pic16_findNextInstruction - given a pCode, find the next instruction  */
4761 /*                       in the linked list                        */
4762 /*-----------------------------------------------------------------*/
4763 pCode * pic16_findNextInstruction(pCode *pci)
4764 {
4765   pCode *pc = pci;
4766
4767   while(pc) {
4768     if((pc->type == PC_OPCODE) || (pc->type == PC_WILD))
4769       return pc;
4770
4771 #ifdef PCODE_DEBUG
4772     fprintf(stderr,"pic16_findNextInstruction:  ");
4773     printpCode(stderr, pc);
4774 #endif
4775     pc = pc->next;
4776   }
4777
4778   //fprintf(stderr,"Couldn't find instruction\n");
4779   return NULL;
4780 }
4781
4782 /*-----------------------------------------------------------------*/
4783 /* pic16_findNextInstruction - given a pCode, find the next instruction  */
4784 /*                       in the linked list                        */
4785 /*-----------------------------------------------------------------*/
4786 pCode * pic16_findPrevInstruction(pCode *pci)
4787 {
4788   return findPrevpCode(pci, PC_OPCODE);
4789 }
4790 #if 0
4791 /*-----------------------------------------------------------------*/
4792 /* findFunctionEnd - given a pCode find the end of the function    */
4793 /*                   that contains it                              */
4794 /*-----------------------------------------------------------------*/
4795 static pCode * findFunctionEnd(pCode *pc)
4796 {
4797
4798   while(pc) {
4799     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
4800       return pc;
4801
4802     pc = pc->next;
4803   }
4804
4805   fprintf(stderr,"Couldn't find function end\n");
4806   return NULL;
4807 }
4808 #endif
4809 #if 0
4810 /*-----------------------------------------------------------------*/
4811 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
4812 /*                instruction with which it is associated.         */
4813 /*-----------------------------------------------------------------*/
4814 static void AnalyzeLabel(pCode *pc)
4815 {
4816
4817   pCodeUnlink(pc);
4818
4819 }
4820 #endif
4821
4822 #if 0
4823 static void AnalyzeGOTO(pCode *pc)
4824 {
4825
4826   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
4827
4828 }
4829
4830 static void AnalyzeSKIP(pCode *pc)
4831 {
4832
4833   pBranchLink(pc,pic16_findNextInstruction(pc->next));
4834   pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
4835
4836 }
4837
4838 static void AnalyzeRETURN(pCode *pc)
4839 {
4840
4841   //  branch_link(pc,findFunctionEnd(pc->next));
4842
4843 }
4844
4845 #endif
4846
4847 /*-----------------------------------------------------------------*/
4848 /*-----------------------------------------------------------------*/
4849 regs * pic16_getRegFromInstruction(pCode *pc)
4850 {
4851
4852   if(!pc                   || 
4853      !isPCI(pc)            ||
4854      !PCI(pc)->pcop        ||
4855      PCI(pc)->num_ops == 0 ||
4856      (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
4857     return NULL;
4858
4859   switch(PCI(pc)->pcop->type) {
4860   case PO_INDF0:
4861   case PO_FSR0:
4862     return PCOR(PCI(pc)->pcop)->r;
4863
4864     //    return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4865
4866   case PO_BIT:
4867   case PO_GPR_TEMP:
4868 //      fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4869     return PCOR(PCI(pc)->pcop)->r;
4870
4871   case PO_IMMEDIATE:
4872     if(PCOI(PCI(pc)->pcop)->r)
4873       return (PCOI(PCI(pc)->pcop)->r);
4874
4875     //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4876     return pic16_dirregWithName(PCI(pc)->pcop->name);
4877     //return NULL; // PCOR(PCI(pc)->pcop)->r;
4878
4879   case PO_GPR_BIT:
4880     return PCOR(PCI(pc)->pcop)->r;
4881
4882   case PO_DIR:
4883 //      fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4884     return PCOR(PCI(pc)->pcop)->r;
4885   case PO_LITERAL:
4886     //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4887     break;
4888
4889   default:
4890     //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4891     //genericPrint(stderr, pc);
4892     break;
4893   }
4894
4895   return NULL;
4896
4897 }
4898
4899 /*-------------------------------------------------------------------------------*/
4900 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
4901 /*-------------------------------------------------------------------------------*/
4902 regs * pic16_getRegFromInstruction2(pCode *pc)
4903 {
4904
4905   if(!pc                   || 
4906      !isPCI(pc)            ||
4907      !PCI(pc)->pcop        ||
4908      PCI(pc)->num_ops == 0 ||
4909      (PCI(pc)->num_ops == 1))           // accept only 2 operand commands
4910     return NULL;
4911
4912
4913 /*
4914  * operands supported in MOVFF:
4915  *  PO_INF0/PO_FSR0
4916  *  PO_GPR_TEMP
4917  *  PO_IMMEDIATE
4918  *  PO_DIR
4919  *
4920  */
4921   switch(PCI(pc)->pcop->type) {
4922   case PO_INDF0:
4923   case PO_FSR0:
4924     return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4925
4926     //    return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
4927
4928 //  case PO_BIT:
4929   case PO_GPR_TEMP:
4930     //fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
4931     return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4932
4933   case PO_IMMEDIATE:
4934         break;
4935 #if 0
4936     if(PCOI(PCI(pc)->pcop)->r)
4937       return (PCOI(PCI(pc)->pcop)->r);
4938
4939     //fprintf(stderr, "pic16_getRegFromInstruction - immediate\n");
4940     return pic16_dirregWithName(PCI(pc)->pcop->name);
4941     //return NULL; // PCOR(PCI(pc)->pcop)->r;
4942 #endif
4943
4944   case PO_GPR_BIT:
4945         break;
4946 //    return PCOR2(PCI(pc)->pcop)->r;
4947
4948   case PO_DIR:
4949     //fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
4950     return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
4951
4952   case PO_LITERAL:
4953         break;
4954     //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
4955
4956   default:
4957     //fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
4958     //genericPrint(stderr, pc);
4959     break;
4960   }
4961
4962   return NULL;
4963
4964 }
4965
4966 /*-----------------------------------------------------------------*/
4967 /*-----------------------------------------------------------------*/
4968
4969 static void AnalyzepBlock(pBlock *pb)
4970 {
4971   pCode *pc;
4972
4973   if(!pb)
4974     return;
4975
4976   /* Find all of the registers used in this pBlock 
4977    * by looking at each instruction and examining it's
4978    * operands
4979    */
4980   for(pc = pb->pcHead; pc; pc = pc->next) {
4981
4982     /* Is this an instruction with operands? */
4983     if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
4984
4985       if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
4986
4987         /* Loop through all of the registers declared so far in
4988            this block and see if we find this one there */
4989
4990         regs *r = setFirstItem(pb->tregisters);
4991
4992         while(r) {
4993           if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
4994             PCOR(PCI(pc)->pcop)->r = r;
4995             break;
4996           }
4997           r = setNextItem(pb->tregisters);
4998         }
4999
5000         if(!r) {
5001           /* register wasn't found */
5002           //r = Safe_calloc(1, sizeof(regs));
5003           //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5004           //addSet(&pb->tregisters, r);
5005           addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5006           //PCOR(PCI(pc)->pcop)->r = r;
5007           //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5008         }/* else 
5009           fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5010          */
5011       }
5012       if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5013         if(PCOR(PCI(pc)->pcop)->r) {
5014           pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5015           DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5016         } else {
5017           if(PCI(pc)->pcop->name)
5018             fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5019           else
5020             fprintf(stderr,"ERROR: NULL register\n");
5021         }
5022       }
5023     }
5024
5025
5026   }
5027 }
5028
5029 /*-----------------------------------------------------------------*/
5030 /* */
5031 /*-----------------------------------------------------------------*/
5032 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5033
5034 static void InsertpFlow(pCode *pc, pCode **pflow)
5035 {
5036   if(*pflow)
5037     PCFL(*pflow)->end = pc;
5038
5039   if(!pc || !pc->next)
5040     return;
5041
5042   *pflow = pic16_newpCodeFlow();
5043   pic16_pCodeInsertAfter(pc, *pflow);
5044 }
5045
5046 /*-----------------------------------------------------------------*/
5047 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
5048 /*                         the flow blocks.                        */
5049 /*
5050  * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5051  * point the instruction flow changes. 
5052  */
5053 /*-----------------------------------------------------------------*/
5054 void pic16_BuildFlow(pBlock *pb)
5055 {
5056   pCode *pc;
5057   pCode *last_pci=NULL;
5058   pCode *pflow=NULL;
5059   int seq = 0;
5060
5061   if(!pb)
5062     return;
5063
5064   //fprintf (stderr,"build flow start seq %d  ",GpcFlowSeq);
5065   /* Insert a pCodeFlow object at the beginning of a pBlock */
5066
5067   InsertpFlow(pb->pcHead, &pflow);
5068
5069   //pflow = pic16_newpCodeFlow();    /* Create a new Flow object */
5070   //pflow->next = pb->pcHead;  /* Make the current head the next object */
5071   //pb->pcHead->prev = pflow;  /* let the current head point back to the flow object */
5072   //pb->pcHead = pflow;        /* Make the Flow object the head */
5073   //pflow->pb = pb;
5074
5075   for( pc = pic16_findNextInstruction(pb->pcHead);
5076        pc != NULL;
5077        pc=pic16_findNextInstruction(pc)) { 
5078
5079     pc->seq = seq++;
5080     PCI(pc)->pcflow = PCFL(pflow);
5081
5082     //fprintf(stderr," build: ");
5083     //pflow->print(stderr,pflow);
5084
5085     if( PCI(pc)->isSkip) {
5086
5087       /* The two instructions immediately following this one 
5088        * mark the beginning of a new flow segment */
5089
5090       while(pc && PCI(pc)->isSkip) {
5091
5092         PCI(pc)->pcflow = PCFL(pflow);
5093         pc->seq = seq-1;
5094         seq = 1;
5095
5096         InsertpFlow(pc, &pflow);
5097         pc=pic16_findNextInstruction(pc->next);
5098       }
5099
5100       seq = 0;
5101
5102       if(!pc)
5103         break;
5104
5105       PCI(pc)->pcflow = PCFL(pflow);
5106       pc->seq = 0;
5107       InsertpFlow(pc, &pflow);
5108
5109     } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next)))  {
5110
5111       InsertpFlow(pc, &pflow);
5112       seq = 0;
5113
5114     } else if (checkLabel(pc)) { 
5115
5116       /* This instruction marks the beginning of a
5117        * new flow segment */
5118
5119       pc->seq = 0;
5120       seq = 1;
5121
5122       /* If the previous pCode is not a flow object, then 
5123        * insert a new flow object. (This check prevents 
5124        * two consecutive flow objects from being insert in
5125        * the case where a skip instruction preceeds an
5126        * instruction containing a label.) */
5127
5128       if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5129         InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5130
5131       PCI(pc)->pcflow = PCFL(pflow);
5132       
5133     }
5134     last_pci = pc;
5135     pc = pc->next;
5136   }
5137
5138   //fprintf (stderr,",end seq %d",GpcFlowSeq);
5139   if(pflow)
5140     PCFL(pflow)->end = pb->pcTail;
5141 }
5142
5143 /*-------------------------------------------------------------------*/
5144 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
5145 /*                           the flow blocks.                        */
5146 /*
5147  * unBuildFlow removes pCodeFlow objects from a pCode chain
5148  */
5149 /*-----------------------------------------------------------------*/
5150 static void unBuildFlow(pBlock *pb)
5151 {
5152   pCode *pc,*pcnext;
5153
5154   if(!pb)
5155     return;
5156
5157   pc = pb->pcHead;
5158
5159   while(pc) {
5160     pcnext = pc->next;
5161
5162     if(isPCI(pc)) {
5163
5164       pc->seq = 0;
5165       if(PCI(pc)->pcflow) {
5166         //free(PCI(pc)->pcflow);
5167         PCI(pc)->pcflow = NULL;
5168       }
5169
5170     } else if(isPCFL(pc) )
5171       pc->destruct(pc);
5172
5173     pc = pcnext;
5174   }
5175
5176
5177 }
5178 #if 0
5179 /*-----------------------------------------------------------------*/
5180 /*-----------------------------------------------------------------*/
5181 static void dumpCond(int cond)
5182 {
5183
5184   static char *pcc_str[] = {
5185     //"PCC_NONE",
5186     "PCC_REGISTER",
5187     "PCC_REGISTER2",
5188     "PCC_C",
5189     "PCC_Z",
5190     "PCC_DC",
5191     "PCC_OV",
5192     "PCC_N",
5193     "PCC_W",
5194     "PCC_EXAMINE_PCOP",
5195     "PCC_LITERAL",
5196     "PCC_REL_ADDR"
5197   };
5198
5199   int ncond = sizeof(pcc_str) / sizeof(char *);
5200   int i,j;
5201
5202   fprintf(stderr, "0x%04X\n",cond);
5203
5204   for(i=0,j=1; i<ncond; i++, j<<=1)
5205     if(cond & j)
5206       fprintf(stderr, "  %s\n",pcc_str[i]);
5207
5208 }
5209 #endif
5210
5211 #if 0
5212 /*-----------------------------------------------------------------*/
5213 /*-----------------------------------------------------------------*/
5214 static void FlowStats(pCodeFlow *pcflow)
5215 {
5216
5217   pCode *pc;
5218
5219   if(!isPCFL(pcflow))
5220     return;
5221
5222   fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5223
5224   pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE); 
5225
5226   if(!pc) {
5227     fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5228     return;
5229   }
5230
5231
5232   fprintf(stderr, "  FlowStats inCond: ");
5233   dumpCond(pcflow->inCond);
5234   fprintf(stderr, "  FlowStats outCond: ");
5235   dumpCond(pcflow->outCond);
5236
5237 }
5238 #endif
5239 /*-----------------------------------------------------------------*
5240  * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5241  *    if it affects the banking bits. 
5242  * 
5243  * return: -1 == Banking bits are unaffected by this pCode.
5244  *
5245  * return: > 0 == Banking bits are affected.
5246  *
5247  *  If the banking bits are affected, then the returned value describes
5248  * which bits are affected and how they're affected. The lower half
5249  * of the integer maps to the bits that are affected, the upper half
5250  * to whether they're set or cleared.
5251  *
5252  *-----------------------------------------------------------------*/
5253
5254 static int isBankInstruction(pCode *pc)
5255 {
5256   regs *reg;
5257   int bank = -1;
5258
5259   if(!isPCI(pc))
5260     return -1;
5261
5262   if( PCI(pc)->op == POC_MOVLB ||
5263       (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5264     bank = PCOL(pc)->lit;
5265   }
5266
5267   return bank;
5268 }
5269
5270
5271 /*-----------------------------------------------------------------*/
5272 /*-----------------------------------------------------------------*/
5273 static void FillFlow(pCodeFlow *pcflow)
5274 {
5275
5276   pCode *pc;
5277   int cur_bank;
5278
5279   if(!isPCFL(pcflow))
5280     return;
5281
5282   //  fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5283
5284   pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE); 
5285
5286   if(!pc) {
5287     //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5288     return;
5289   }
5290
5291   cur_bank = -1;
5292
5293   do {
5294     isBankInstruction(pc);
5295     pc = pc->next;
5296   } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5297
5298 /*
5299   if(!pc ) {
5300     fprintf(stderr, "  FillFlow - Bad end of flow\n");
5301   } else {
5302     fprintf(stderr, "  FillFlow - Ending flow with\n  ");
5303     pc->print(stderr,pc);
5304   }
5305
5306   fprintf(stderr, "  FillFlow inCond: ");
5307   dumpCond(pcflow->inCond);
5308   fprintf(stderr, "  FillFlow outCond: ");
5309   dumpCond(pcflow->outCond);
5310 */
5311 }
5312
5313 /*-----------------------------------------------------------------*/
5314 /*-----------------------------------------------------------------*/
5315 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5316 {
5317   pCodeFlowLink *fromLink, *toLink;
5318
5319   if(!from || !to || !to->pcflow || !from->pcflow)
5320     return;
5321
5322   fromLink = pic16_newpCodeFlowLink(from->pcflow);
5323   toLink   = pic16_newpCodeFlowLink(to->pcflow);
5324
5325   addSetIfnotP(&(from->pcflow->to), toLink);   //to->pcflow);
5326   addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5327
5328 }
5329
5330 /*-----------------------------------------------------------------*
5331  * void LinkFlow(pBlock *pb)
5332  *
5333  * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5334  * non-branching segments. In LinkFlow, we determine the execution
5335  * order of these segments. For example, if one of the segments ends
5336  * with a skip, then we know that there are two possible flow segments
5337  * to which control may be passed.
5338  *-----------------------------------------------------------------*/
5339 static void LinkFlow(pBlock *pb)
5340 {
5341   pCode *pc=NULL;
5342   pCode *pcflow;
5343   pCode *pct;
5344
5345   //fprintf(stderr,"linkflow \n");
5346
5347   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
5348        pcflow != NULL;
5349        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5350
5351     if(!isPCFL(pcflow))
5352       fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5353
5354     //fprintf(stderr," link: ");
5355     //pcflow->print(stderr,pcflow);
5356
5357     //FillFlow(PCFL(pcflow));
5358
5359     pc = PCFL(pcflow)->end;
5360
5361     //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5362     if(isPCI_SKIP(pc)) {
5363       //fprintf(stderr, "ends with skip\n");
5364       //pc->print(stderr,pc);
5365       pct=pic16_findNextInstruction(pc->next);
5366       LinkFlow_pCode(PCI(pc),PCI(pct));
5367       pct=pic16_findNextInstruction(pct->next);
5368       LinkFlow_pCode(PCI(pc),PCI(pct));
5369       continue;
5370     }
5371
5372     if(isPCI_BRANCH(pc)) {
5373       pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5374
5375       //fprintf(stderr, "ends with branch\n  ");
5376       //pc->print(stderr,pc);
5377
5378       if(!(pcol && isPCOLAB(pcol))) {
5379         if((PCI(pc)->op != POC_RETLW)
5380                 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5381         
5382                 /* continue if label is '$' which assembler knows how to parse */
5383                 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5384
5385                 pc->print(stderr,pc);
5386                 fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5387         }
5388         continue;
5389       }
5390
5391       if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
5392         LinkFlow_pCode(PCI(pc),PCI(pct));
5393       else
5394         fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
5395                 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
5396   //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
5397
5398       continue;
5399     }
5400
5401     if(isPCI(pc)) {
5402       //fprintf(stderr, "ends with non-branching instruction:\n");
5403       //pc->print(stderr,pc);
5404
5405       LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
5406
5407       continue;
5408     }
5409
5410     if(pc) {
5411       //fprintf(stderr, "ends with unknown\n");
5412       //pc->print(stderr,pc);
5413       continue;
5414     }
5415
5416     //fprintf(stderr, "ends with nothing: ERROR\n");
5417     
5418   }
5419 }
5420 /*-----------------------------------------------------------------*/
5421 /*-----------------------------------------------------------------*/
5422
5423 /*-----------------------------------------------------------------*/
5424 /*-----------------------------------------------------------------*/
5425 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
5426 {
5427
5428   if(!pc || !pcflow)
5429     return 0;
5430
5431   if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
5432     return 0;
5433
5434   if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
5435     return 1;
5436
5437   return 0;
5438 }
5439
5440
5441
5442
5443
5444 /*-----------------------------------------------------------------*/
5445 /* insertBankSwitch - inserts a bank switch statement in the assembly listing */
5446 /*-----------------------------------------------------------------*/
5447 static void insertBankSwitch(int position, pCode *pc, int bsr)
5448 {
5449   pCode *new_pc;
5450   regs *reg;
5451
5452   if(!pc)
5453     return;
5454
5455 /*
5456  * if bsr == -1 then do not insert a MOVLB instruction, but rather
5457  * insert a BANKSEL assembler directive for the symbol used by
5458  * the pCode. This will allow the linker to setup the correct
5459  * bank at linking time
5460  */
5461
5462         if(!pic16_options.gen_banksel || bsr != -1) {
5463 //              new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(bsr));
5464                 return;
5465         } else {
5466                 /* emit the BANKSEL [symbol] */
5467
5468                 /* FIXME */
5469                 /* IMPORTANT: The following code does not check if a symbol is
5470                  * split in multiple banks. This should be corrected. - VR 6/6/2003 */
5471
5472                 reg = pic16_getRegFromInstruction(pc);
5473                 if(!reg)return;
5474                 new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", reg->name);
5475                 
5476                 position = 0;           // position is always before (sanity check!)
5477         }
5478
5479 #if 0
5480         fprintf(stderr, "%s:%d: inserting bank switch\tbank = %d\n", __FUNCTION__, __LINE__, bsr);
5481         pc->print(stderr, pc);
5482 #endif
5483
5484         if(position) {
5485                 /* insert the bank switch after this pc instruction */
5486                 pCode *pcnext = pic16_findNextInstruction(pc);
5487                 pic16_pCodeInsertAfter(pc, new_pc);
5488                 if(pcnext)
5489                         pc = pcnext;
5490
5491         } else
5492                 pic16_pCodeInsertAfter(pc->prev, new_pc);
5493
5494   /* Move the label, if there is one */
5495
5496         if(PCI(pc)->label) {
5497 //              fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
5498 //                      __FILE__, __LINE__, pc, new_pc);
5499                 PCAD(new_pc)->label = PCI(pc)->label;
5500                 PCI(pc)->label = NULL;
5501         }
5502
5503 //  fprintf(stderr, "BankSwitch has been inserted\n");
5504 }
5505
5506
5507 /*-----------------------------------------------------------------*/
5508 /*int compareBankFlow - compare the banking requirements between   */
5509 /*  flow objects. */
5510 /*-----------------------------------------------------------------*/
5511 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
5512 {
5513
5514   if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
5515     return 0;
5516
5517   if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
5518     return 0;
5519
5520   if(pcflow->firstBank == -1)
5521     return 0;
5522
5523
5524   if(pcflowLink->pcflow->firstBank == -1) {
5525     pCodeFlowLink *pctl = setFirstItem( toORfrom ? 
5526                                         pcflowLink->pcflow->to : 
5527                                         pcflowLink->pcflow->from);
5528     return compareBankFlow(pcflow, pctl, toORfrom);
5529   }
5530
5531   if(toORfrom) {
5532     if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
5533       return 0;
5534
5535     pcflowLink->bank_conflict++;
5536     pcflowLink->pcflow->FromConflicts++;
5537     pcflow->ToConflicts++;
5538   } else {
5539     
5540     if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
5541       return 0;
5542
5543     pcflowLink->bank_conflict++;
5544     pcflowLink->pcflow->ToConflicts++;
5545     pcflow->FromConflicts++;
5546
5547   }
5548   /*
5549   fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
5550           pcflowLink->pcflow->pc.seq,
5551           pcflowLink->pcflow->FromConflicts,
5552           pcflowLink->pcflow->ToConflicts);
5553   */
5554   return 1;
5555
5556 }
5557
5558 #if 0
5559 /*-----------------------------------------------------------------*/
5560 /*-----------------------------------------------------------------*/
5561 static void DumpFlow(pBlock *pb)
5562 {
5563   pCode *pc=NULL;
5564   pCode *pcflow;
5565   pCodeFlowLink *pcfl;
5566
5567
5568   fprintf(stderr,"Dump flow \n");
5569   pb->pcHead->print(stderr, pb->pcHead);
5570
5571   pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
5572   pcflow->print(stderr,pcflow);
5573
5574   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
5575        pcflow != NULL;
5576        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5577
5578     if(!isPCFL(pcflow)) {
5579       fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
5580       continue;
5581     }
5582     fprintf(stderr,"dumping: ");
5583     pcflow->print(stderr,pcflow);
5584     FlowStats(PCFL(pcflow));
5585
5586     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5587
5588       pc = PCODE(pcfl->pcflow);
5589
5590       fprintf(stderr, "    from seq %d:\n",pc->seq);
5591       if(!isPCFL(pc)) {
5592         fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
5593         pc->print(stderr,pc);
5594       }
5595
5596     }
5597
5598     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
5599
5600       pc = PCODE(pcfl->pcflow);
5601
5602       fprintf(stderr, "    to seq %d:\n",pc->seq);
5603       if(!isPCFL(pc)) {
5604         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
5605         pc->print(stderr,pc);
5606       }
5607
5608     }
5609
5610   }
5611
5612 }
5613 #endif
5614 /*-----------------------------------------------------------------*/
5615 /*-----------------------------------------------------------------*/
5616 static int OptimizepBlock(pBlock *pb)
5617 {
5618   pCode *pc, *pcprev;
5619   int matches =0;
5620
5621   if(!pb || !peepOptimizing)
5622     return 0;
5623
5624   DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
5625 /*
5626   for(pc = pb->pcHead; pc; pc = pc->next)
5627     matches += pic16_pCodePeepMatchRule(pc);
5628 */
5629
5630   pc = pic16_findNextInstruction(pb->pcHead);
5631   if(!pc)
5632     return 0;
5633
5634   pcprev = pc->prev;
5635   do {
5636
5637
5638     if(pic16_pCodePeepMatchRule(pc)) {
5639
5640       matches++;
5641
5642       if(pcprev)
5643         pc = pic16_findNextInstruction(pcprev->next);
5644       else 
5645         pc = pic16_findNextInstruction(pb->pcHead);
5646     } else
5647       pc = pic16_findNextInstruction(pc->next);
5648   } while(pc);
5649
5650   if(matches)
5651     DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
5652   return matches;
5653
5654 }
5655
5656 /*-----------------------------------------------------------------*/
5657 /*-----------------------------------------------------------------*/
5658 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
5659 {
5660   pCode *pc;
5661
5662   for(pc = pcs; pc; pc = pc->next) {
5663
5664     if((pc->type == PC_OPCODE) && 
5665        (PCI(pc)->pcop) && 
5666        (PCI(pc)->pcop->type == PO_LABEL) &&
5667        (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
5668       return pc;
5669   }
5670  
5671
5672   return NULL;
5673 }
5674
5675 /*-----------------------------------------------------------------*/
5676 /*-----------------------------------------------------------------*/
5677 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
5678 {
5679
5680   char *s=NULL;
5681
5682   if(isPCI(pc) && 
5683      (PCI(pc)->pcop) && 
5684      (PCI(pc)->pcop->type == PO_LABEL)) {
5685
5686     pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5687
5688     //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
5689     if(pcol->pcop.name)
5690       free(pcol->pcop.name);
5691
5692     /* If the key is negative, then we (probably) have a label to
5693      * a function and the name is already defined */
5694        
5695     if(pcl->key>0)
5696       sprintf(s=buffer,"_%05d_DS_",pcl->key);
5697     else 
5698       s = pcl->label;
5699
5700     //sprintf(buffer,"_%05d_DS_",pcl->key);
5701     if(!s) {
5702       fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
5703     }
5704     pcol->pcop.name = Safe_strdup(s);
5705     pcol->key = pcl->key;
5706     //pc->print(stderr,pc);
5707
5708   }
5709
5710
5711 }
5712
5713 /*-----------------------------------------------------------------*/
5714 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
5715 /*                            pCode chain if they're not used.     */
5716 /*-----------------------------------------------------------------*/
5717 static void pBlockRemoveUnusedLabels(pBlock *pb)
5718 {
5719   pCode *pc; pCodeLabel *pcl;
5720
5721   if(!pb)
5722     return;
5723
5724   for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
5725
5726     pBranch *pbr = PCI(pc)->label;
5727     if(pbr && pbr->next) {
5728       pCode *pcd = pb->pcHead;
5729
5730       //fprintf(stderr, "multiple labels\n");
5731       //pc->print(stderr,pc);
5732
5733       pbr = pbr->next;
5734       while(pbr) {
5735
5736         while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
5737           //fprintf(stderr,"Used by:\n");
5738           //pcd->print(stderr,pcd);
5739
5740           exchangeLabels(PCL(pbr->pc),pcd);
5741
5742           pcd = pcd->next;
5743         }
5744         pbr = pbr->next;
5745       }
5746     }
5747   }
5748
5749   for(pc = pb->pcHead; pc; pc = pc->next) {
5750
5751     if(isPCL(pc)) // pc->type == PC_LABEL)
5752       pcl = PCL(pc);
5753     else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
5754       pcl = PCL(PCI(pc)->label->pc);
5755     else continue;
5756
5757     //fprintf(stderr," found  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5758
5759     /* This pCode is a label, so search the pBlock to see if anyone
5760      * refers to it */
5761
5762     if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
5763     //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
5764       /* Couldn't find an instruction that refers to this label
5765        * So, unlink the pCode label from it's pCode chain
5766        * and destroy the label */
5767       //fprintf(stderr," removed  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
5768
5769       DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
5770       if(pc->type == PC_LABEL) {
5771         pic16_unlinkpCode(pc);
5772         pCodeLabelDestruct(pc);
5773       } else {
5774         unlinkpCodeFromBranch(pc, PCODE(pcl));
5775         /*if(pc->label->next == NULL && pc->label->pc == NULL) {
5776           free(pc->label);
5777         }*/
5778       }
5779
5780     }
5781   }
5782
5783 }
5784
5785
5786 /*-----------------------------------------------------------------*/
5787 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode      */
5788 /*                     chain and put them into pBranches that are  */
5789 /*                     associated with the appropriate pCode       */
5790 /*                     instructions.                               */
5791 /*-----------------------------------------------------------------*/
5792 void pic16_pBlockMergeLabels(pBlock *pb)
5793 {
5794   pBranch *pbr;
5795   pCode *pc, *pcnext=NULL;
5796
5797   if(!pb)
5798     return;
5799
5800   /* First, Try to remove any unused labels */
5801   //pBlockRemoveUnusedLabels(pb);
5802
5803   /* Now loop through the pBlock and merge the labels with the opcodes */
5804
5805   pc = pb->pcHead;
5806   //  for(pc = pb->pcHead; pc; pc = pc->next) {
5807
5808   while(pc) {
5809     pCode *pcn = pc->next;
5810
5811     if(pc->type == PC_LABEL) {
5812
5813 //      fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
5814 //      fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
5815
5816       if((pcnext = pic16_findNextInstruction(pc) )) {
5817
5818         // Unlink the pCode label from it's pCode chain
5819         pic16_unlinkpCode(pc);
5820         
5821 //      fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
5822         // And link it into the instruction's pBranch labels. (Note, since
5823         // it's possible to have multiple labels associated with one instruction
5824         // we must provide a means to accomodate the additional labels. Thus
5825         // the labels are placed into the singly-linked list "label" as 
5826         // opposed to being a single member of the pCodeInstruction.)
5827
5828         //_ALLOC(pbr,sizeof(pBranch));
5829 #if 1
5830         pbr = Safe_calloc(1,sizeof(pBranch));
5831         pbr->pc = pc;
5832         pbr->next = NULL;
5833
5834         PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
5835 #endif
5836       } else {
5837         fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
5838       }
5839     } else if(pc->type == PC_CSOURCE) {
5840
5841       /* merge the source line symbolic info into the next instruction */
5842       if((pcnext = pic16_findNextInstruction(pc) )) {
5843
5844         // Unlink the pCode label from it's pCode chain
5845         pic16_unlinkpCode(pc);
5846         PCI(pcnext)->cline = PCCS(pc);
5847         //fprintf(stderr, "merging CSRC\n");
5848         //genericPrint(stderr,pcnext);
5849       }
5850
5851     }
5852     pc = pcn;
5853   }
5854   pBlockRemoveUnusedLabels(pb);
5855
5856 }
5857
5858 /*-----------------------------------------------------------------*/
5859 /*-----------------------------------------------------------------*/
5860 static int OptimizepCode(char dbName)
5861 {
5862 #define MAX_PASSES 4
5863
5864   int matches = 0;
5865   int passes = 0;
5866   pBlock *pb;
5867
5868   if(!the_pFile)
5869     return 0;
5870
5871   DFPRINTF((stderr," Optimizing pCode\n"));
5872
5873   do {
5874     matches = 0;
5875     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5876       if('*' == dbName || getpBlock_dbName(pb) == dbName)
5877         matches += OptimizepBlock(pb);
5878     }
5879   }
5880   while(matches && ++passes < MAX_PASSES);
5881
5882   return matches;
5883 }
5884
5885 /*-----------------------------------------------------------------*/
5886 /* pic16_popCopyGPR2Bit - copy a pcode operator                          */
5887 /*-----------------------------------------------------------------*/
5888
5889 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
5890 {
5891   pCodeOp *pcop;
5892
5893   pcop = pic16_newpCodeOpBit(pc->name, bitval, 0);
5894
5895   if( !( (pcop->type == PO_LABEL) ||
5896          (pcop->type == PO_LITERAL) ||
5897          (pcop->type == PO_STR) ))
5898     PCOR(pcop)->r = PCOR(pc)->r;  /* This is dangerous... */
5899     PCOR(pcop)->r->wasUsed = 1;
5900
5901   return pcop;
5902 }
5903
5904
5905 /*----------------------------------------------------------------------*
5906  * pic16_areRegsSame - check to see if the names of two registers match *
5907  *----------------------------------------------------------------------*/
5908 int pic16_areRegsSame(regs *r1, regs *r2)
5909 {
5910         if(!strcmp(r1->name, r2->name))return 1;
5911
5912   return 0;
5913 }
5914
5915
5916 /*-----------------------------------------------------------------*/
5917 /*-----------------------------------------------------------------*/
5918 static void pic16_FixRegisterBanking(pBlock *pb)
5919 {
5920   pCode *pc=NULL;
5921   pCode *pcprev=NULL;
5922   regs *reg, *prevreg;
5923
5924         if(!pb)
5925                 return;
5926
5927         pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
5928         if(!pc)
5929                 return;
5930
5931         /* loop through all of the flow blocks with in one pblock */
5932
5933 //      fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
5934
5935   prevreg = NULL;
5936   do {
5937     /* at this point, pc should point to a PC_FLOW object */
5938     /* for each flow block, determine the register banking 
5939        requirements */
5940
5941       if(isPCI(pc) && !PCI(pc)->is2MemOp) {
5942                 reg = pic16_getRegFromInstruction(pc);
5943
5944 #if 0
5945                 fprintf(stderr, "reg = %p\n", reg);
5946                 if(reg) {
5947                         fprintf(stderr, "%s:%d:  %s  %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
5948                         fprintf(stderr, "addr = 0x%03x, bank = %d, bit=%d\tmapped = %d sfr=%d fix=%d\n",
5949                                 reg->address,REG_BANK(reg),reg->isBitField, reg->isMapped,
5950                                 pic16_finalMapping[ reg->address ].isSFR, reg->isFixed);
5951                 }
5952 #endif
5953
5954                 /* we can be 99% that within a pBlock, between two consequtive
5955                  * refernces to the same register, the extra banksel is needless */
5956
5957                 if((reg && !isACCESS_BANK(reg) && (isBankInstruction(pc) == -1))
5958                         && (!isPCI_LIT(pc))
5959                         && (PCI(pc)->op != POC_CALL)
5960
5961                         && ( ((pic16_options.opt_banksel>0)
5962                                 && (!prevreg || (prevreg && !pic16_areRegsSame(reg, prevreg))))
5963                             || (!pic16_options.opt_banksel)
5964                            )
5965                                    )
5966                            {
5967                   /* Examine the instruction before this one to make sure it is
5968                    * not a skip type instruction */
5969                         pcprev = findPrevpCode(pc->prev, PC_OPCODE);
5970
5971                         /* FIXME: if previous is SKIP pCode, we should move the BANKSEL
5972                          * before SKIP, but we have to check if the SKIP uses BANKSEL, etc... */
5973                         if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) {
5974                                 prevreg = reg;
5975                                 insertBankSwitch(0, pc, (pic16_options.gen_banksel)?-1:0);
5976                         }
5977                 }
5978
5979         pcprev = pc;
5980
5981       }
5982
5983       pc = pc->next;
5984   }while (pc);
5985
5986 #if 0
5987   if(pcprev && cur_bank) {
5988
5989     int pos = 1;  /* Assume that the bank switch instruction(s)
5990                    * are inserted after this instruction */
5991
5992     if((PCI(pcprev)->op == POC_RETLW) || 
5993        (PCI(pcprev)->op == POC_RETURN) || 
5994        (PCI(pcprev)->op == POC_RETFIE)) {
5995
5996       /* oops, a RETURN - we need to switch banks *before* the RETURN */
5997
5998       pos = 0;
5999
6000     } 
6001             
6002     /* Brute force - make sure that we point to bank 0 at the
6003      * end of each flow block */
6004
6005 //    insertBankSwitch(pos, pcprev, 0);
6006 /*
6007     new_pc = pic16_newpCode(POC_MOVLB, pic16_newpCodeOpLit(0));
6008     pic16_pCodeInsertAfter(pcprev, new_pc);
6009 */
6010     cur_bank = 0;
6011     //fprintf(stderr, "Brute force switch\n");
6012   }
6013 #endif
6014
6015 }
6016
6017
6018 static void pBlockDestruct(pBlock *pb)
6019 {
6020
6021   if(!pb)
6022     return;
6023
6024
6025   free(pb);
6026
6027 }
6028
6029 /*-----------------------------------------------------------------*/
6030 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6031 /*                                  name dbName and combine them   */
6032 /*                                  into one block                 */
6033 /*-----------------------------------------------------------------*/
6034 static void mergepBlocks(char dbName)
6035 {
6036
6037   pBlock *pb, *pbmerged = NULL,*pbn;
6038
6039   pb = the_pFile->pbHead;
6040
6041   //fprintf(stderr," merging blocks named %c\n",dbName);
6042   while(pb) {
6043
6044     pbn = pb->next;
6045     //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6046     if( getpBlock_dbName(pb) == dbName) {
6047
6048       //fprintf(stderr," merged block %c\n",dbName);
6049
6050       if(!pbmerged) {
6051         pbmerged = pb;
6052       } else {
6053         pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6054         /* pic16_addpCode2pBlock doesn't handle the tail: */
6055         pbmerged->pcTail = pb->pcTail;
6056
6057         pb->prev->next = pbn;
6058         if(pbn) 
6059           pbn->prev = pb->prev;
6060
6061
6062         pBlockDestruct(pb);
6063       }
6064       //pic16_printpBlock(stderr, pbmerged);
6065     } 
6066     pb = pbn;
6067   }
6068
6069 }
6070
6071 /*-----------------------------------------------------------------*/
6072 /* AnalyzeFlow - Examine the flow of the code and optimize         */
6073 /*                                                                 */
6074 /* level 0 == minimal optimization                                 */
6075 /*   optimize registers that are used only by two instructions     */
6076 /* level 1 == maximal optimization                                 */
6077 /*   optimize by looking at pairs of instructions that use the     */
6078 /*   register.                                                     */
6079 /*-----------------------------------------------------------------*/
6080
6081 static void AnalyzeFlow(int level)
6082 {
6083   static int times_called=0;
6084   pBlock *pb;
6085
6086         if(!the_pFile) {
6087
6088                 /* remove unused allocated registers before exiting */
6089                 pic16_RemoveUnusedRegisters();
6090         
6091           return;
6092         }
6093
6094
6095   /* if this is not the first time this function has been called,
6096      then clean up old flow information */
6097         if(times_called++) {
6098                 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6099                         unBuildFlow(pb);
6100
6101                 pic16_RegsUnMapLiveRanges();
6102         }
6103
6104         GpcFlowSeq = 1;
6105
6106   /* Phase 2 - Flow Analysis - Register Banking
6107    *
6108    * In this phase, the individual flow blocks are examined
6109    * and register banking is fixed.
6110    */
6111
6112 #if 0
6113         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6114                 pic16_FixRegisterBanking(pb);
6115 #endif
6116
6117   /* Phase 2 - Flow Analysis
6118    *
6119    * In this phase, the pCode is partition into pCodeFlow 
6120    * blocks. The flow blocks mark the points where a continuous
6121    * stream of instructions changes flow (e.g. because of
6122    * a call or goto or whatever).
6123    */
6124
6125         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6126                 pic16_BuildFlow(pb);
6127
6128
6129   /* Phase 2 - Flow Analysis - linking flow blocks
6130    *
6131    * In this phase, the individual flow blocks are examined
6132    * to determine their order of excution.
6133    */
6134
6135         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6136                 LinkFlow(pb);
6137
6138   /* Phase 3 - Flow Analysis - Flow Tree
6139    *
6140    * In this phase, the individual flow blocks are examined
6141    * to determine their order of execution.
6142    */
6143
6144         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6145                 pic16_BuildFlowTree(pb);
6146
6147
6148   /* Phase x - Flow Analysis - Used Banks
6149    *
6150    * In this phase, the individual flow blocks are examined
6151    * to determine the Register Banks they use
6152    */
6153
6154 #if 0
6155         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6156                 FixBankFlow(pb);
6157 #endif
6158
6159
6160         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6161                 pic16_pCodeRegMapLiveRanges(pb);
6162
6163         pic16_RemoveUnusedRegisters();
6164
6165   //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
6166         pic16_pCodeRegOptimizeRegUsage(level);
6167
6168
6169         if(!options.nopeep)
6170                 OptimizepCode('*');
6171
6172
6173 #if 0
6174         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6175                 DumpFlow(pb);
6176 #endif
6177
6178   /* debug stuff */ 
6179         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6180           pCode *pcflow;
6181                 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
6182                         (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6183                         pcflow = pcflow->next) {
6184
6185                         FillFlow(PCFL(pcflow));
6186                 }
6187         }
6188
6189 #if 0
6190         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6191           pCode *pcflow;
6192
6193                 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
6194                         (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6195                         pcflow = pcflow->next) {
6196
6197                         FlowStats(PCFL(pcflow));
6198                 }
6199         }
6200 #endif
6201 }
6202
6203 /* VR -- no need to analyze banking in flow, but left here :
6204  *      1. because it may be used in the future for other purposes
6205  *      2. because if omitted we'll miss some optimization done here
6206  *
6207  * Perhaps I should rename it to something else
6208  */
6209
6210 /*-----------------------------------------------------------------*/
6211 /* pic16_AnalyzeBanking - Called after the memory addresses have been    */
6212 /*                  assigned to the registers.                     */
6213 /*                                                                 */
6214 /*-----------------------------------------------------------------*/
6215
6216 void pic16_AnalyzeBanking(void)
6217 {
6218   pBlock  *pb;
6219
6220         if(!pic16_picIsInitialized()) {
6221                 fprintf(stderr,"Temporary ERROR: at the moment you have to use\n");
6222                 fprintf(stderr,"an include file create by inc2h.pl. See SDCC source:\n");
6223                 fprintf(stderr,"support/scripts/inc2h.pl\n");
6224                 fprintf(stderr,"this is a nuisance bug that will be fixed shortly\n");
6225
6226                 /* I think it took a long long time to fix this bug! ;-) -- VR */
6227
6228                 exit(1);
6229         }
6230
6231
6232         /* Phase x - Flow Analysis - Used Banks
6233          *
6234          * In this phase, the individual flow blocks are examined
6235          * to determine the Register Banks they use
6236          */
6237
6238         AnalyzeFlow(0);
6239         AnalyzeFlow(1);
6240
6241 //      for(pb = the_pFile->pbHead; pb; pb = pb->next)
6242 //              BanksUsedFlow(pb);
6243
6244         if(!the_pFile)return;
6245
6246         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6247 //              fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6248                 pic16_FixRegisterBanking(pb);
6249         }
6250
6251 }
6252
6253 /*-----------------------------------------------------------------*/
6254 /* buildCallTree - Look at the flow and extract all of the calls.  */
6255 /*-----------------------------------------------------------------*/
6256 static set *register_usage(pBlock *pb);
6257
6258 static void buildCallTree(void    )
6259 {
6260   pBranch *pbr;
6261   pBlock  *pb;
6262   pCode   *pc;
6263
6264   if(!the_pFile)
6265     return;
6266
6267
6268
6269   /* Now build the call tree.
6270      First we examine all of the pCodes for functions.
6271      Keep in mind that the function boundaries coincide
6272      with pBlock boundaries. 
6273
6274      The algorithm goes something like this:
6275      We have two nested loops. The outer loop iterates
6276      through all of the pBlocks/functions. The inner
6277      loop iterates through all of the pCodes for
6278      a given pBlock. When we begin iterating through
6279      a pBlock, the variable pc_fstart, pCode of the start
6280      of a function, is cleared. We then search for pCodes
6281      of type PC_FUNCTION. When one is encountered, we
6282      initialize pc_fstart to this and at the same time
6283      associate a new pBranch object that signifies a 
6284      branch entry. If a return is found, then this signifies
6285      a function exit point. We'll link the pCodes of these
6286      returns to the matching pc_fstart.
6287
6288      When we're done, a doubly linked list of pBranches
6289      will exist. The head of this list is stored in
6290      `the_pFile', which is the meta structure for all
6291      of the pCode. Look at the pic16_printCallTree function
6292      on how the pBranches are linked together.
6293
6294    */
6295   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6296     pCode *pc_fstart=NULL;
6297     for(pc = pb->pcHead; pc; pc = pc->next) {
6298       if(isPCF(pc)) {
6299         if (PCF(pc)->fname) {
6300
6301           if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6302             //fprintf(stderr," found main \n");
6303             pb->cmemmap = NULL;  /* FIXME do we need to free ? */
6304             pb->dbName = 'M';
6305           }
6306
6307           pbr = Safe_calloc(1,sizeof(pBranch));
6308           pbr->pc = pc_fstart = pc;
6309           pbr->next = NULL;
6310
6311           the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6312
6313           // Here's a better way of doing the same:
6314           addSet(&pb->function_entries, pc);
6315
6316         } else {
6317           // Found an exit point in a function, e.g. return
6318           // (Note, there may be more than one return per function)
6319           if(pc_fstart)
6320             pBranchLink(PCF(pc_fstart), PCF(pc));
6321
6322           addSet(&pb->function_exits, pc);
6323         }
6324       } else if(isCALL(pc)) {
6325         addSet(&pb->function_calls,pc);
6326       }
6327     }
6328   }
6329
6330   /* Re-allocate the registers so that there are no collisions
6331    * between local variables when one function call another */
6332
6333   // this is weird...
6334   //  pic16_deallocateAllRegs();
6335
6336   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6337     if(!pb->visited)
6338       register_usage(pb);
6339   }
6340
6341 }
6342
6343 /*-----------------------------------------------------------------*/
6344 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6345 /*                all of the logical connections.                  */
6346 /*                                                                 */
6347 /* Essentially what's done here is that the pCode flow is          */
6348 /* determined.                                                     */
6349 /*-----------------------------------------------------------------*/
6350
6351 void pic16_AnalyzepCode(char dbName)
6352 {
6353   pBlock *pb;
6354   int i,changes;
6355
6356   if(!the_pFile)
6357     return;
6358
6359   mergepBlocks('D');
6360
6361
6362   /* Phase 1 - Register allocation and peep hole optimization
6363    *
6364    * The first part of the analysis is to determine the registers
6365    * that are used in the pCode. Once that is done, the peep rules
6366    * are applied to the code. We continue to loop until no more
6367    * peep rule optimizations are found (or until we exceed the
6368    * MAX_PASSES threshold). 
6369    *
6370    * When done, the required registers will be determined.
6371    *
6372    */
6373   i = 0;
6374   do {
6375
6376     DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
6377     //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
6378
6379     /* First, merge the labels with the instructions */
6380     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6381       if('*' == dbName || getpBlock_dbName(pb) == dbName) {
6382
6383         DFPRINTF((stderr," analyze and merging block %c\n",dbName));
6384         //fprintf(stderr," analyze and merging block %c\n",dbName);
6385         pic16_pBlockMergeLabels(pb);
6386         AnalyzepBlock(pb);
6387       } else {
6388         DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
6389       }
6390     }
6391
6392         if(!options.nopeep)
6393                 changes = OptimizepCode(dbName);
6394         else changes = 0;
6395
6396   } while(changes && (i++ < MAX_PASSES));
6397
6398   buildCallTree();
6399 }
6400
6401 /*-----------------------------------------------------------------*/
6402 /* ispCodeFunction - returns true if *pc is the pCode of a         */
6403 /*                   function                                      */
6404 /*-----------------------------------------------------------------*/
6405 static bool ispCodeFunction(pCode *pc)
6406 {
6407
6408   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
6409     return 1;
6410
6411   return 0;
6412 }
6413
6414 /*-----------------------------------------------------------------*/
6415 /* findFunction - Search for a function by name (given the name)   */
6416 /*                in the set of all functions that are in a pBlock */
6417 /* (note - I expect this to change because I'm planning to limit   */
6418 /*  pBlock's to just one function declaration                      */
6419 /*-----------------------------------------------------------------*/
6420 static pCode *findFunction(char *fname)
6421 {
6422   pBlock *pb;
6423   pCode *pc;
6424   if(!fname)
6425     return NULL;
6426
6427   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6428
6429     pc = setFirstItem(pb->function_entries);
6430     while(pc) {
6431     
6432       if((pc->type == PC_FUNCTION) &&
6433          (PCF(pc)->fname) && 
6434          (strcmp(fname, PCF(pc)->fname)==0))
6435         return pc;
6436
6437       pc = setNextItem(pb->function_entries);
6438
6439     }
6440
6441   }
6442   return NULL;
6443 }
6444
6445 static void MarkUsedRegisters(set *regset)
6446 {
6447
6448   regs *r1,*r2;
6449
6450   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
6451 //      fprintf(stderr, "marking register = %s\t", r1->name);
6452     r2 = pic16_regWithIdx(r1->rIdx);
6453 //      fprintf(stderr, "to register = %s\n", r2->name);
6454     r2->isFree = 0;
6455     r2->wasUsed = 1;
6456   }
6457 }
6458
6459 static void pBlockStats(FILE *of, pBlock *pb)
6460 {
6461
6462   pCode *pc;
6463   regs  *r;
6464
6465         if(!pic16_pcode_verbose)return;
6466         
6467   fprintf(of,";***\n;  pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
6468
6469   // for now just print the first element of each set
6470   pc = setFirstItem(pb->function_entries);
6471   if(pc) {
6472     fprintf(of,";entry:  ");
6473     pc->print(of,pc);
6474   }
6475   pc = setFirstItem(pb->function_exits);
6476   if(pc) {
6477     fprintf(of,";has an exit\n");
6478     //pc->print(of,pc);
6479   }
6480
6481   pc = setFirstItem(pb->function_calls);
6482   if(pc) {
6483     fprintf(of,";functions called:\n");
6484
6485     while(pc) {
6486       if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6487         fprintf(of,";   %s\n",pic16_get_op_from_instruction(PCI(pc)));
6488       }
6489       pc = setNextItem(pb->function_calls);
6490     }
6491   }
6492
6493   r = setFirstItem(pb->tregisters);
6494   if(r) {
6495     int n = elementsInSet(pb->tregisters);
6496
6497     fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
6498
6499     while (r) {
6500       fprintf(of,";   %s\n",r->name);
6501       r = setNextItem(pb->tregisters);
6502     }
6503   }
6504 }
6505
6506 /*-----------------------------------------------------------------*/
6507 /*-----------------------------------------------------------------*/
6508 #if 0
6509 static void sequencepCode(void)
6510 {
6511   pBlock *pb;
6512   pCode *pc;
6513
6514
6515   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6516
6517     pb->seq = GpCodeSequenceNumber+1;
6518
6519     for( pc = pb->pcHead; pc; pc = pc->next)
6520       pc->seq = ++GpCodeSequenceNumber;
6521   }
6522
6523 }
6524 #endif
6525
6526 /*-----------------------------------------------------------------*/
6527 /*-----------------------------------------------------------------*/
6528 static set *register_usage(pBlock *pb)
6529 {
6530   pCode *pc,*pcn;
6531   set *registers=NULL;
6532   set *registersInCallPath = NULL;
6533
6534   /* check recursion */
6535
6536   pc = setFirstItem(pb->function_entries);
6537
6538   if(!pc)
6539     return registers;
6540
6541   pb->visited = 1;
6542
6543   if(pc->type != PC_FUNCTION)
6544     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
6545
6546   pc = setFirstItem(pb->function_calls);
6547   for( ; pc; pc = setNextItem(pb->function_calls)) {
6548
6549     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6550       char *dest = pic16_get_op_from_instruction(PCI(pc));
6551
6552       pcn = findFunction(dest);
6553       if(pcn) 
6554         registersInCallPath = register_usage(pcn->pb);
6555     } else
6556       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6557
6558   }
6559
6560 #ifdef PCODE_DEBUG
6561   pBlockStats(stderr,pb);  // debug
6562 #endif
6563
6564   // Mark the registers in this block as used.
6565
6566   MarkUsedRegisters(pb->tregisters);
6567   if(registersInCallPath) {
6568     /* registers were used in the functions this pBlock has called */
6569     /* so now, we need to see if these collide with the ones we are */
6570     /* using here */
6571
6572     regs *r1,*r2, *newreg;
6573
6574     DFPRINTF((stderr,"comparing registers\n"));
6575
6576     r1 = setFirstItem(registersInCallPath);
6577     while(r1) {
6578
6579       r2 = setFirstItem(pb->tregisters);
6580
6581       while(r2 && (r1->type != REG_STK)) {
6582
6583         if(r2->rIdx == r1->rIdx) {
6584           newreg = pic16_findFreeReg(REG_GPR);
6585
6586
6587           if(!newreg) {
6588             DFPRINTF((stderr,"Bummer, no more registers.\n"));
6589             exit(1);
6590           }
6591
6592           DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
6593                   r1->rIdx, newreg->rIdx));
6594           r2->rIdx = newreg->rIdx;
6595           //if(r2->name) free(r2->name);
6596           if(newreg->name)
6597             r2->name = Safe_strdup(newreg->name);
6598           else
6599             r2->name = NULL;
6600           newreg->isFree = 0;
6601           newreg->wasUsed = 1;
6602         }
6603         r2 = setNextItem(pb->tregisters);
6604       }
6605
6606       r1 = setNextItem(registersInCallPath);
6607     }
6608
6609     /* Collisions have been resolved. Now free the registers in the call path */
6610     r1 = setFirstItem(registersInCallPath);
6611     while(r1) {
6612       if(r1->type != REG_STK) {
6613         newreg = pic16_regWithIdx(r1->rIdx);
6614         newreg->isFree = 1;
6615       }
6616       r1 = setNextItem(registersInCallPath);
6617     }
6618
6619   }// else
6620   //    MarkUsedRegisters(pb->registers);
6621
6622   registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
6623 #ifdef PCODE_DEBUG
6624   if(registers) 
6625     DFPRINTF((stderr,"returning regs\n"));
6626   else
6627     DFPRINTF((stderr,"not returning regs\n"));
6628
6629   DFPRINTF((stderr,"pBlock after register optim.\n"));
6630   pBlockStats(stderr,pb);  // debug
6631 #endif
6632
6633   return registers;
6634 }
6635
6636 /*-----------------------------------------------------------------*/
6637 /* pct2 - writes the call tree to a file                           */
6638 /*                                                                 */
6639 /*-----------------------------------------------------------------*/
6640 static void pct2(FILE *of,pBlock *pb,int indent)
6641 {
6642   pCode *pc,*pcn;
6643   int i;
6644   //  set *registersInCallPath = NULL;
6645
6646   if(!of)
6647     return;
6648
6649   if(indent > 10)
6650     return; //recursion ?
6651
6652   pc = setFirstItem(pb->function_entries);
6653
6654   if(!pc)
6655     return;
6656
6657   pb->visited = 0;
6658
6659   for(i=0;i<indent;i++)   // Indentation
6660     fputc(' ',of);
6661
6662   if(pc->type == PC_FUNCTION)
6663     fprintf(of,"%s\n",PCF(pc)->fname);
6664   else
6665     return;  // ???
6666
6667
6668   pc = setFirstItem(pb->function_calls);
6669   for( ; pc; pc = setNextItem(pb->function_calls)) {
6670
6671     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
6672       char *dest = pic16_get_op_from_instruction(PCI(pc));
6673
6674       pcn = findFunction(dest);
6675       if(pcn) 
6676         pct2(of,pcn->pb,indent+1);
6677     } else
6678       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6679
6680   }
6681
6682
6683 }
6684
6685
6686 /*-----------------------------------------------------------------*/
6687 /* pic16_printCallTree - writes the call tree to a file                  */
6688 /*                                                                 */
6689 /*-----------------------------------------------------------------*/
6690
6691 void pic16_printCallTree(FILE *of)
6692 {
6693   pBranch *pbr;
6694   pBlock  *pb;
6695   pCode   *pc;
6696
6697   if(!the_pFile)
6698     return;
6699
6700   if(!of)
6701     of = stderr;
6702
6703   fprintf(of, "\npBlock statistics\n");
6704   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
6705     pBlockStats(of,pb);
6706
6707
6708
6709   fprintf(of,"Call Tree\n");
6710   pbr = the_pFile->functions;
6711   while(pbr) {
6712     if(pbr->pc) {
6713       pc = pbr->pc;
6714       if(!ispCodeFunction(pc))
6715         fprintf(of,"bug in call tree");
6716
6717
6718       fprintf(of,"Function: %s\n", PCF(pc)->fname);
6719
6720       while(pc->next && !ispCodeFunction(pc->next)) {
6721         pc = pc->next;
6722         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
6723           fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
6724       }
6725     }
6726
6727     pbr = pbr->next;
6728   }
6729
6730
6731   fprintf(of,"\n**************\n\na better call tree\n");
6732   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6733     if(pb->visited)
6734       pct2(of,pb,0);
6735   }
6736
6737   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6738     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
6739   }
6740 }
6741
6742
6743
6744 /*-----------------------------------------------------------------*/
6745 /*                                                                 */
6746 /*-----------------------------------------------------------------*/
6747
6748 static void InlineFunction(pBlock *pb)
6749 {
6750   pCode *pc;
6751   pCode *pc_call;
6752
6753   if(!pb)
6754     return;
6755
6756   pc = setFirstItem(pb->function_calls);
6757
6758   for( ; pc; pc = setNextItem(pb->function_calls)) {
6759
6760     if(isCALL(pc)) {
6761       pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6762       pCode *pct;
6763       pCode *pce;
6764
6765       pBranch *pbr;
6766
6767       if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) {               /* change 0 to 1 to enable inlining */
6768         
6769         //fprintf(stderr,"Cool can inline:\n");
6770         //pcn->print(stderr,pcn);
6771
6772         //fprintf(stderr,"recursive call Inline\n");
6773         InlineFunction(pcn->pb);
6774         //fprintf(stderr,"return from recursive call Inline\n");
6775
6776         /*
6777           At this point, *pc points to a CALL mnemonic, and
6778           *pcn points to the function that is being called.
6779
6780           To in-line this call, we need to remove the CALL
6781           and RETURN(s), and link the function pCode in with
6782           the CALLee pCode.
6783
6784         */
6785
6786
6787         /* Remove the CALL */
6788         pc_call = pc;
6789         pc = pc->prev;
6790
6791         /* remove callee pBlock from the pBlock linked list */
6792         removepBlock(pcn->pb);
6793
6794         pce = pcn;
6795         while(pce) {
6796           pce->pb = pb;
6797           pce = pce->next;
6798         }
6799
6800         /* Remove the Function pCode */
6801         pct = pic16_findNextInstruction(pcn->next);
6802
6803         /* Link the function with the callee */
6804         pc->next = pcn->next;
6805         pcn->next->prev = pc;
6806         
6807         /* Convert the function name into a label */
6808
6809         pbr = Safe_calloc(1,sizeof(pBranch));
6810         pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
6811         pbr->next = NULL;
6812         PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
6813         PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
6814
6815         /* turn all of the return's except the last into goto's */
6816         /* check case for 2 instruction pBlocks */
6817         pce = pic16_findNextInstruction(pcn->next);
6818         while(pce) {
6819           pCode *pce_next = pic16_findNextInstruction(pce->next);
6820
6821           if(pce_next == NULL) {
6822             /* found the last return */
6823             pCode *pc_call_next =  pic16_findNextInstruction(pc_call->next);
6824
6825             //fprintf(stderr,"found last return\n");
6826             //pce->print(stderr,pce);
6827             pce->prev->next = pc_call->next;
6828             pc_call->next->prev = pce->prev;
6829             PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
6830                                                       PCI(pce)->label);
6831           }
6832
6833           pce = pce_next;
6834         }
6835
6836
6837       }
6838     } else
6839       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6840
6841   }
6842
6843 }
6844
6845 /*-----------------------------------------------------------------*/
6846 /*                                                                 */
6847 /*-----------------------------------------------------------------*/
6848
6849 void pic16_InlinepCode(void)
6850 {
6851
6852   pBlock  *pb;
6853   pCode   *pc;
6854
6855   if(!the_pFile)
6856     return;
6857
6858   if(!functionInlining)
6859     return;
6860
6861   /* Loop through all of the function definitions and count the
6862    * number of times each one is called */
6863   //fprintf(stderr,"inlining %d\n",__LINE__);
6864
6865   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6866
6867     pc = setFirstItem(pb->function_calls);
6868
6869     for( ; pc; pc = setNextItem(pb->function_calls)) {
6870
6871       if(isCALL(pc)) {
6872         pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
6873         if(pcn && isPCF(pcn)) {
6874           PCF(pcn)->ncalled++;
6875         }
6876       } else
6877         fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6878
6879     }
6880   }
6881
6882   //fprintf(stderr,"inlining %d\n",__LINE__);
6883
6884   /* Now, Loop through the function definitions again, but this
6885    * time inline those functions that have only been called once. */
6886   
6887   InlineFunction(the_pFile->pbHead);
6888   //fprintf(stderr,"inlining %d\n",__LINE__);
6889
6890   for(pb = the_pFile->pbHead; pb; pb = pb->next)
6891     unBuildFlow(pb);
6892
6893 }