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