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