* as/mcs51/lkarea.c: removed old K&R style,
[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 //                                      fprintf(stderr, "%s:%d testing %s <-> %s\n", __FILE__, __LINE__, PCF(pc)->fname, ab->name);
4422                                         if(!strcmp(ab->name, PCF(pc)->fname)) {
4423 //                                              fprintf(stderr, "%s:%d address = %x\n", __FILE__, __LINE__, ab->address);
4424                                                 fprintf(of, "\t0X%06X", ab->address);
4425                                                 break;
4426                                         }
4427                                 }
4428                         }
4429                         fprintf(of, "\n");
4430                 }
4431                 printpCode(of,pc);
4432         }
4433 }
4434
4435 /*-----------------------------------------------------------------*/
4436 /*                                                                 */
4437 /*       pCode processing                                          */
4438 /*                                                                 */
4439 /*                                                                 */
4440 /*                                                                 */
4441 /*-----------------------------------------------------------------*/
4442
4443 void pic16_unlinkpCode(pCode *pc)
4444 {
4445
4446
4447   if(pc) {
4448 #ifdef PCODE_DEBUG
4449     fprintf(stderr,"Unlinking: ");
4450     printpCode(stderr, pc);
4451 #endif
4452     if(pc->prev) 
4453       pc->prev->next = pc->next;
4454     if(pc->next)
4455       pc->next->prev = pc->prev;
4456
4457     pc->prev = pc->next = NULL;
4458   }
4459 }
4460
4461 /*-----------------------------------------------------------------*/
4462 /*-----------------------------------------------------------------*/
4463
4464 static void genericDestruct(pCode *pc)
4465 {
4466
4467   pic16_unlinkpCode(pc);
4468
4469   if(isPCI(pc)) {
4470     /* For instructions, tell the register (if there's one used)
4471      * that it's no longer needed */
4472     regs *reg = pic16_getRegFromInstruction(pc);
4473     if(reg)
4474       deleteSetItem (&(reg->reglives.usedpCodes),pc);
4475
4476         if(PCI(pc)->is2MemOp) {
4477                 reg = pic16_getRegFromInstruction2(pc);
4478                 if(reg)
4479                         deleteSetItem(&(reg->reglives.usedpCodes), pc);
4480         }
4481   }
4482
4483   /* Instead of deleting the memory used by this pCode, mark
4484    * the object as bad so that if there's a pointer to this pCode
4485    * dangling around somewhere then (hopefully) when the type is
4486    * checked we'll catch it.
4487    */
4488
4489   pc->type = PC_BAD;
4490   pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4491
4492   //free(pc);
4493 }
4494
4495
4496 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4497 /*-----------------------------------------------------------------*/
4498 /*-----------------------------------------------------------------*/
4499 /* modifiers for constant immediate */
4500 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4501
4502 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4503 {
4504   regs *r;
4505   static char b[50];
4506   char *s;
4507   int use_buffer = 1;    // copy the string to the passed buffer pointer
4508
4509         if(!buffer) {
4510                 buffer = b;
4511                 size = sizeof(b);
4512                 use_buffer = 0;     // Don't bother copying the string to the buffer.
4513         } 
4514
4515         if(pcop) {
4516                 switch(pcop->type) {
4517                         case PO_W:
4518                         case PO_WREG:
4519                         case PO_PRODL:
4520                         case PO_PRODH:
4521                         case PO_INDF0:
4522                         case PO_FSR0:
4523                                 if(use_buffer) {
4524                                         SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4525                                         return buffer;
4526                                 }
4527                                 return PCOR(pcop)->r->name;
4528                                 break;
4529                         case PO_GPR_TEMP:
4530                                 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4531                                 if(use_buffer) {
4532                                         SAFE_snprintf(&buffer,&size,"%s",r->name);
4533                                         return buffer;
4534                                 }
4535                                 return r->name;
4536
4537                         case PO_IMMEDIATE:
4538                                 s = buffer;
4539                                 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4540                                         if(PCOI(pcop)->index) {
4541                                                 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4542                                                         immdmod[ PCOI(pcop)->offset ],
4543                                                         pcop->name,
4544                                                         PCOI(pcop)->index);
4545                                         } else {
4546                                                 SAFE_snprintf(&s,&size,"%s(%s)",
4547                                                         immdmod[ PCOI(pcop)->offset ],
4548                                                         pcop->name);
4549                                         }
4550                                 } else {
4551                                         if(PCOI(pcop)->index) {
4552                                                 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4553                                                         immdmod[ 0 ],
4554                                                         pcop->name,
4555                                                         PCOI(pcop)->index);
4556                                         } else {
4557                                                 SAFE_snprintf(&s,&size, "%s(%s)",
4558                                                         immdmod[ 0 ],
4559                                                         pcop->name);
4560                                         }
4561                                 }
4562                                 return buffer;
4563
4564                         case PO_GPR_REGISTER:
4565                         case PO_DIR:
4566                                 s = buffer;
4567 //                              size = sizeof(buffer);
4568                                 if( PCOR(pcop)->instance) {
4569                                         SAFE_snprintf(&s,&size,"(%s + %d)",
4570                                                 pcop->name,
4571                                                 PCOR(pcop)->instance );
4572                                 } else {
4573                                         SAFE_snprintf(&s,&size,"%s",pcop->name);
4574                                 }
4575                                 return buffer;
4576
4577                         default:
4578                                 if(pcop->name) {
4579                                         if(use_buffer) {
4580                                                 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4581                                                 return buffer;
4582                                         }
4583                                 return pcop->name;
4584                                 }
4585
4586                 }
4587         }
4588
4589   return "NO operand1";
4590 }
4591
4592 /*-----------------------------------------------------------------*/
4593 /* pic16_get_op2 - variant to support two memory operand commands  */
4594 /*-----------------------------------------------------------------*/
4595 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4596 {
4597   regs *r;
4598   static char b[50];
4599   char *s;
4600   int use_buffer = 1;    // copy the string to the passed buffer pointer
4601
4602         if(!buffer) {
4603                 buffer = b;
4604                 size = sizeof(b);
4605                 use_buffer = 0;     // Don't bother copying the string to the buffer.
4606         } 
4607
4608 #if 0
4609         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",
4610                 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4611                 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4612 #endif
4613
4614         if(pcop) {
4615                 switch(PCOR2(pcop)->pcop2->type) {
4616                         case PO_W:
4617                         case PO_WREG:
4618                         case PO_PRODL:
4619                         case PO_PRODH:
4620                         case PO_INDF0:
4621                         case PO_FSR0:
4622                                 if(use_buffer) {
4623                                         SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4624                                         return buffer;
4625                                 }
4626                                 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4627                                 break;
4628                         case PO_GPR_TEMP:
4629                                 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4630
4631                                 if(use_buffer) {
4632                                         SAFE_snprintf(&buffer,&size,"%s",r->name);
4633                                         return buffer;
4634                                 }
4635                                 return r->name;
4636
4637                         case PO_IMMEDIATE:
4638                                         assert( 0 );
4639                                 break;
4640 #if 0
4641                                 s = buffer;
4642
4643                                 if(PCOI(pcop)->_const) {
4644                                         if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4645                                                 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4646                                                         pcop->name,
4647                                                         PCOI(pcop)->index,
4648                                                         8 * PCOI(pcop)->offset );
4649                                         } else
4650                                                 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4651                                 } else {
4652                                         if( PCOI(pcop)->index) {
4653                                                 SAFE_snprintf(&s,&size,"(%s + %d)",
4654                                                         pcop->name,
4655                                                         PCOI(pcop)->index );
4656                                         } else {
4657                                                 if(PCOI(pcop)->offset)
4658                                                         SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4659                                                 else
4660                                                         SAFE_snprintf(&s,&size,"%s",pcop->name);
4661                                         }
4662                                 }
4663                                 return buffer;
4664 #endif
4665                         case PO_DIR:
4666                                 s = buffer;
4667                                 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4668                                         SAFE_snprintf(&s,&size,"(%s + %d)",
4669                                                 PCOR(PCOR2(pcop)->pcop2)->r->name,
4670                                                 PCOR(PCOR2(pcop)->pcop2)->instance );
4671                                 } else {
4672                                         SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4673                                 }
4674                                 return buffer;
4675
4676                         default:
4677                                 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4678                                         if(use_buffer) {
4679                                                 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4680                                                 return buffer;
4681                                         }
4682                                         return PCOR(PCOR2(pcop)->pcop2)->r->name;
4683                                 }
4684                 }
4685         }
4686
4687   return "NO operand2";
4688 }
4689
4690 /*-----------------------------------------------------------------*/
4691 /*-----------------------------------------------------------------*/
4692 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4693 {
4694
4695   if(pcc )
4696     return pic16_get_op(pcc->pcop,NULL,0);
4697
4698   /* gcc 3.2:  warning: concatenation of string literals with __FUNCTION__ is deprecated 
4699    *   return ("ERROR Null: "__FUNCTION__);
4700    */
4701   return ("ERROR Null: pic16_get_op_from_instruction");
4702
4703 }
4704
4705 /*-----------------------------------------------------------------*/
4706 /*-----------------------------------------------------------------*/
4707 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4708 {
4709
4710   fprintf(of,"pcodeopprint- not implemented\n");
4711 }
4712
4713 /*-----------------------------------------------------------------*/
4714 /* pic16_pCode2str - convert a pCode instruction to string               */
4715 /*-----------------------------------------------------------------*/
4716 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4717 {
4718   char *s = str;
4719   regs *r;
4720
4721 #if 0
4722         if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4723                 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4724                         __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4725 //              exit(-1);
4726         }
4727 #endif
4728
4729   switch(pc->type) {
4730
4731   case PC_OPCODE:
4732     SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4733
4734     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4735
4736         if(PCI(pc)->is2MemOp) {
4737                 SAFE_snprintf(&s,&size, "%s, %s", 
4738                 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4739                 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4740                 break;
4741         }
4742
4743         if(PCI(pc)->is2LitOp) {
4744                 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4745                 break;
4746         }
4747
4748       if(PCI(pc)->isBitInst) {
4749         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4750           if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4751             SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
4752                           PCI(pc)->pcop->name ,
4753                           PCI(pc)->pcop->name );
4754           else
4755             SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)), 
4756                           (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4757         } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4758           SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4759         }else
4760           SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4761         //PCI(pc)->pcop->t.bit );
4762       } else {
4763
4764         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4765           if( PCI(pc)->num_ops == 3)
4766             SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4767           else
4768             SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4769
4770         }else {
4771           SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4772
4773                 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4774                         if(PCI(pc)->num_ops == 3)
4775                                 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4776
4777                         r = pic16_getRegFromInstruction(pc);
4778 //                      fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4779 //                                      __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4780
4781                         if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
4782           }
4783         }
4784       }
4785
4786     }
4787     break;
4788
4789   case PC_COMMENT:
4790     /* assuming that comment ends with a \n */
4791     SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4792     break;
4793
4794   case PC_INLINE:
4795     /* assuming that inline code ends with a \n */
4796     SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
4797     break;
4798
4799   case PC_LABEL:
4800     SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
4801     break;
4802   case PC_FUNCTION:
4803     SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
4804     break;
4805   case PC_WILD:
4806     SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
4807     break;
4808   case PC_FLOW:
4809     SAFE_snprintf(&s,&size,";\t--FLOW change\n");
4810     break;
4811   case PC_CSOURCE:
4812 //    SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4813       SAFE_snprintf(&s,&size,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
4814         PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4815     break;
4816   case PC_ASMDIR:
4817         if(PCAD(pc)->directive) {
4818                 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4819         } else
4820         if(PCAD(pc)->arg) {
4821                 /* special case to handle inline labels without a tab */
4822                 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
4823         }
4824         break;
4825
4826   case PC_BAD:
4827     SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
4828     break;
4829
4830   case PC_INFO:
4831     SAFE_snprintf(&s,&size,"; PC INFO pcode\n");
4832     break;
4833   }
4834
4835   return str;
4836
4837 }
4838
4839 /*-----------------------------------------------------------------*/
4840 /* genericPrint - the contents of a pCode to a file                */
4841 /*-----------------------------------------------------------------*/
4842 static void genericPrint(FILE *of, pCode *pc)
4843 {
4844
4845   if(!pc || !of)
4846     return;
4847
4848   switch(pc->type) {
4849   case PC_COMMENT:
4850     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
4851     break;
4852
4853   case PC_INLINE:
4854     fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
4855      break;
4856
4857   case PC_OPCODE:
4858     // If the opcode has a label, print that first
4859     {
4860       pBranch *pbl = PCI(pc)->label;
4861       while(pbl && pbl->pc) {
4862         if(pbl->pc->type == PC_LABEL)
4863           pCodePrintLabel(of, pbl->pc);
4864         pbl = pbl->next;
4865       }
4866     }
4867
4868     if(PCI(pc)->cline) 
4869       genericPrint(of,PCODE(PCI(pc)->cline));
4870
4871     {
4872       char str[256];
4873       
4874       pic16_pCode2str(str, 256, pc);
4875
4876       fprintf(of,"%s",str);
4877       /* Debug */
4878       if(pic16_debug_verbose) {
4879         fprintf(of, "\t;key=%03x",pc->seq);
4880         if(PCI(pc)->pcflow)
4881           fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
4882       }
4883     }
4884     fprintf(of, "\n");
4885     break;
4886       
4887   case PC_WILD:
4888     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
4889     if(PCW(pc)->pci.label)
4890       pCodePrintLabel(of, PCW(pc)->pci.label->pc);
4891
4892     if(PCW(pc)->operand) {
4893       fprintf(of,";\toperand  ");
4894       pCodeOpPrint(of,PCW(pc)->operand );
4895     }
4896     break;
4897
4898   case PC_FLOW:
4899     if(pic16_debug_verbose) {
4900       fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
4901       if(PCFL(pc)->ancestor)
4902         fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
4903       fprintf(of,"\n");
4904
4905     }
4906     break;
4907
4908   case PC_CSOURCE:
4909 //    fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
4910     fprintf(of,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
4911         PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
4912          
4913     break;
4914
4915   case PC_ASMDIR:
4916         {
4917           pBranch *pbl = PCAD(pc)->pci.label;
4918                 while(pbl && pbl->pc) {
4919                         if(pbl->pc->type == PC_LABEL)
4920                                 pCodePrintLabel(of, pbl->pc);
4921                         pbl = pbl->next;
4922                 }
4923         }
4924         if(PCAD(pc)->directive) {
4925                 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
4926         } else
4927         if(PCAD(pc)->arg) {
4928                 /* special case to handle inline labels without tab */
4929                 fprintf(of, "%s\n", PCAD(pc)->arg);
4930         }
4931         break;
4932         
4933   case PC_LABEL:
4934   default:
4935     fprintf(of,"unknown pCode type %d\n",pc->type);
4936   }
4937
4938 }
4939
4940 /*-----------------------------------------------------------------*/
4941 /* pCodePrintFunction - prints function begin/end                  */
4942 /*-----------------------------------------------------------------*/
4943
4944 static void pCodePrintFunction(FILE *of, pCode *pc)
4945 {
4946
4947   if(!pc || !of)
4948     return;
4949
4950 #if 0
4951   if( ((pCodeFunction *)pc)->modname) 
4952     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
4953 #endif
4954
4955   if(!PCF(pc)->absblock) {
4956       if(PCF(pc)->fname) {
4957       pBranch *exits = PCF(pc)->to;
4958       int i=0;
4959
4960       fprintf(of,"%s:", PCF(pc)->fname);
4961     
4962       if(pic16_pcode_verbose)
4963         fprintf(of, "\t;Function start");
4964     
4965       fprintf(of, "\n");
4966     
4967       while(exits) {
4968         i++;
4969         exits = exits->next;
4970       }
4971       //if(i) i--;
4972
4973       if(pic16_pcode_verbose)
4974         fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
4975     
4976     } else {
4977         if((PCF(pc)->from && 
4978                 PCF(pc)->from->pc->type == PC_FUNCTION &&
4979                 PCF(PCF(pc)->from->pc)->fname) ) {
4980
4981                 if(pic16_pcode_verbose)
4982                         fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
4983         } else {
4984                 if(pic16_pcode_verbose)
4985                         fprintf(of,"; exit point [can't find entry point]\n");
4986         }
4987         fprintf(of, "\n");
4988     }
4989   }
4990 }
4991 /*-----------------------------------------------------------------*/
4992 /* pCodePrintLabel - prints label                                  */
4993 /*-----------------------------------------------------------------*/
4994
4995 static void pCodePrintLabel(FILE *of, pCode *pc)
4996 {
4997
4998   if(!pc || !of)
4999     return;
5000
5001   if(PCL(pc)->label) 
5002     fprintf(of,"%s:\n",PCL(pc)->label);
5003   else if (PCL(pc)->key >=0) 
5004     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
5005   else
5006     fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
5007
5008 }
5009 /*-----------------------------------------------------------------*/
5010 /* unlinkpCodeFromBranch - Search for a label in a pBranch and     */
5011 /*                         remove it if it is found.               */
5012 /*-----------------------------------------------------------------*/
5013 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
5014 {
5015   pBranch *b, *bprev;
5016
5017
5018   bprev = NULL;
5019
5020   if(pcl->type == PC_OPCODE)
5021     b = PCI(pcl)->label;
5022   else {
5023     fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
5024     exit(1);
5025
5026   }
5027
5028   //fprintf (stderr, "%s \n",__FUNCTION__);
5029   //pcl->print(stderr,pcl);
5030   //pc->print(stderr,pc);
5031   while(b) {
5032     if(b->pc == pc) {
5033       //fprintf (stderr, "found label\n");
5034       //pc->print(stderr, pc);
5035
5036       /* Found a label */
5037       if(bprev) {
5038         bprev->next = b->next;  /* Not first pCode in chain */
5039 //      free(b);
5040       } else {
5041         pc->destruct(pc);
5042         PCI(pcl)->label = b->next;   /* First pCode in chain */
5043 //      free(b);
5044       }
5045       return;  /* A label can't occur more than once */
5046     }
5047     bprev = b;
5048     b = b->next;
5049   }
5050
5051 }
5052
5053 /*-----------------------------------------------------------------*/
5054 /*-----------------------------------------------------------------*/
5055 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5056 {
5057   pBranch *b;
5058
5059   if(!h)
5060     return n;
5061
5062   if(h == n)
5063     return n;
5064
5065   b = h;
5066   while(b->next)
5067     b = b->next;
5068
5069   b->next = n;
5070
5071   return h;
5072   
5073 }  
5074 /*-----------------------------------------------------------------*/
5075 /* pBranchLink - given two pcodes, this function will link them    */
5076 /*               together through their pBranches                  */
5077 /*-----------------------------------------------------------------*/
5078 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5079 {
5080   pBranch *b;
5081
5082   // Declare a new branch object for the 'from' pCode.
5083
5084   //_ALLOC(b,sizeof(pBranch));
5085   b = Safe_calloc(1,sizeof(pBranch));
5086   b->pc = PCODE(t);             // The link to the 'to' pCode.
5087   b->next = NULL;
5088
5089   f->to = pic16_pBranchAppend(f->to,b);
5090
5091   // Now do the same for the 'to' pCode.
5092
5093   //_ALLOC(b,sizeof(pBranch));
5094   b = Safe_calloc(1,sizeof(pBranch));
5095   b->pc = PCODE(f);
5096   b->next = NULL;
5097
5098   t->from = pic16_pBranchAppend(t->from,b);
5099   
5100 }
5101
5102 #if 0
5103 /*-----------------------------------------------------------------*/
5104 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5105 /*               a pCode                                           */
5106 /*-----------------------------------------------------------------*/
5107 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5108 {
5109   while(pb) {
5110
5111     if(pb->pc == pc)
5112       return pb;
5113
5114     pb = pb->next;
5115   }
5116
5117   return NULL;
5118 }
5119
5120 /*-----------------------------------------------------------------*/
5121 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain.      */
5122 /*-----------------------------------------------------------------*/
5123 void pic16_pCodeUnlink(pCode *pc)
5124 {
5125   pBranch *pb1,*pb2;
5126   pCode *pc1;
5127
5128   if(!pc->prev || !pc->next) {
5129     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5130     exit(1);
5131   }
5132
5133   /* first remove the pCode from the chain */
5134   pc->prev->next = pc->next;
5135   pc->next->prev = pc->prev;
5136
5137   /* Now for the hard part... */
5138
5139   /* Remove the branches */
5140
5141   pb1 = PCI(pc)->from;
5142   while(pb1) {
5143     PCI(pc1) = pb1->pc;    /* Get the pCode that branches to the
5144                        * one we're unlinking */
5145
5146     /* search for the link back to this pCode (the one we're
5147      * unlinking) */
5148     if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5149       pb2->pc = PCI(pc)->to->pc;  // make the replacement
5150
5151       /* if the pCode we're unlinking contains multiple 'to'
5152        * branches (e.g. this a skip instruction) then we need
5153        * to copy these extra branches to the chain. */
5154       if(PCI(pc)->to->next)
5155         pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5156     }
5157     
5158     pb1 = pb1->next;
5159   }
5160
5161
5162 }
5163 #endif
5164 /*-----------------------------------------------------------------*/
5165 /*-----------------------------------------------------------------*/
5166 #if 0
5167 static void genericAnalyze(pCode *pc)
5168 {
5169   switch(pc->type) {
5170   case PC_WILD:
5171   case PC_COMMENT:
5172     return;
5173   case PC_LABEL:
5174   case PC_FUNCTION:
5175   case PC_OPCODE:
5176     {
5177       // Go through the pCodes that are in pCode chain and link
5178       // them together through the pBranches. Note, the pCodes
5179       // are linked together as a contiguous stream like the 
5180       // assembly source code lines. The linking here mimics this
5181       // except that comments are not linked in.
5182       // 
5183       pCode *npc = pc->next;
5184       while(npc) {
5185         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5186           pBranchLink(pc,npc);
5187           return;
5188         } else
5189           npc = npc->next;
5190       }
5191       /* reached the end of the pcode chain without finding
5192        * an instruction we could link to. */
5193     }
5194     break;
5195   case PC_FLOW:
5196     fprintf(stderr,"analyze PC_FLOW\n");
5197
5198     return;
5199   case PC_BAD:
5200     fprintf(stderr,,";A bad pCode is being used\n");
5201
5202   }
5203 }
5204 #endif
5205
5206 /*-----------------------------------------------------------------*/
5207 /*-----------------------------------------------------------------*/
5208 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5209 {
5210   pBranch *pbr;
5211
5212   if(pc->type == PC_LABEL) {
5213     if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
5214       return TRUE;
5215   }
5216   if((pc->type == PC_OPCODE)
5217         || (pc->type == PC_ASMDIR)
5218         ) {
5219     pbr = PCI(pc)->label;
5220     while(pbr) {
5221       if(pbr->pc->type == PC_LABEL) {
5222         if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
5223           return TRUE;
5224       }
5225       pbr = pbr->next;
5226     }
5227   }
5228
5229   return FALSE;
5230 }
5231
5232 /*-----------------------------------------------------------------*/
5233 /*-----------------------------------------------------------------*/
5234 static int checkLabel(pCode *pc)
5235 {
5236   pBranch *pbr;
5237
5238   if(pc && isPCI(pc)) {
5239     pbr = PCI(pc)->label;
5240     while(pbr) {
5241       if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5242         return TRUE;
5243
5244       pbr = pbr->next;
5245     }
5246   }
5247
5248   return FALSE;
5249 }
5250
5251 /*-----------------------------------------------------------------*/
5252 /* findLabelinpBlock - Search the pCode for a particular label     */
5253 /*-----------------------------------------------------------------*/
5254 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5255 {
5256   pCode  *pc;
5257
5258   if(!pb)
5259     return NULL;
5260
5261   for(pc = pb->pcHead; pc; pc = pc->next) 
5262     if(compareLabel(pc,pcop_label))
5263       return pc;
5264     
5265   return NULL;
5266 }
5267 #if 0
5268 /*-----------------------------------------------------------------*/
5269 /* findLabel - Search the pCode for a particular label             */
5270 /*-----------------------------------------------------------------*/
5271 static pCode * findLabel(pCodeOpLabel *pcop_label)
5272 {
5273   pBlock *pb;
5274   pCode  *pc;
5275
5276   if(!the_pFile)
5277     return NULL;
5278
5279   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5280     if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5281       return pc;
5282   }
5283
5284   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5285   return NULL;
5286 }
5287 #endif
5288 /*-----------------------------------------------------------------*/
5289 /* pic16_findNextpCode - given a pCode, find the next of type 'pct'      */
5290 /*                 in the linked list                              */
5291 /*-----------------------------------------------------------------*/
5292 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5293 {
5294
5295   while(pc) {
5296     if(pc->type == pct)
5297       return pc;
5298
5299     pc = pc->next;
5300   }
5301
5302   return NULL;
5303 }
5304
5305 /*-----------------------------------------------------------------*/
5306 /* findPrevpCode - given a pCode, find the previous of type 'pct'  */
5307 /*                 in the linked list                              */
5308 /*-----------------------------------------------------------------*/
5309 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5310 {
5311
5312   while(pc) {
5313     if(pc->type == pct)
5314       return pc;
5315
5316     pc = pc->prev;
5317   }
5318
5319   return NULL;
5320 }
5321
5322
5323 //#define PCODE_DEBUG
5324 /*-----------------------------------------------------------------*/
5325 /* pic16_findNextInstruction - given a pCode, find the next instruction  */
5326 /*                       in the linked list                        */
5327 /*-----------------------------------------------------------------*/
5328 pCode * pic16_findNextInstruction(pCode *pci)
5329 {
5330   pCode *pc = pci;
5331
5332   while(pc) {
5333     if((pc->type == PC_OPCODE)
5334         || (pc->type == PC_WILD)
5335         || (pc->type == PC_ASMDIR)
5336         )
5337       return pc;
5338
5339 #ifdef PCODE_DEBUG
5340     fprintf(stderr,"pic16_findNextInstruction:  ");
5341     printpCode(stderr, pc);
5342 #endif
5343     pc = pc->next;
5344   }
5345
5346   //fprintf(stderr,"Couldn't find instruction\n");
5347   return NULL;
5348 }
5349
5350 /*-----------------------------------------------------------------*/
5351 /* pic16_findPrevInstruction - given a pCode, find the next instruction  */
5352 /*                       in the linked list                        */
5353 /*-----------------------------------------------------------------*/
5354 pCode * pic16_findPrevInstruction(pCode *pci)
5355 {
5356   pCode *pc = pci;
5357
5358   while(pc) {
5359
5360     if((pc->type == PC_OPCODE)
5361         || (pc->type == PC_WILD)
5362         || (pc->type == PC_ASMDIR)
5363         )
5364       return pc;
5365       
5366
5367 #ifdef PCODE_DEBUG
5368     fprintf(stderr,"pic16_findPrevInstruction:  ");
5369     printpCode(stderr, pc);
5370 #endif
5371     pc = pc->prev;
5372   }
5373
5374   //fprintf(stderr,"Couldn't find instruction\n");
5375   return NULL;
5376 }
5377
5378 #undef PCODE_DEBUG
5379
5380 #if 0
5381 /*-----------------------------------------------------------------*/
5382 /* findFunctionEnd - given a pCode find the end of the function    */
5383 /*                   that contains it                              */
5384 /*-----------------------------------------------------------------*/
5385 static pCode * findFunctionEnd(pCode *pc)
5386 {
5387
5388   while(pc) {
5389     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
5390       return pc;
5391
5392     pc = pc->next;
5393   }
5394
5395   fprintf(stderr,"Couldn't find function end\n");
5396   return NULL;
5397 }
5398 #endif
5399 #if 0
5400 /*-----------------------------------------------------------------*/
5401 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
5402 /*                instruction with which it is associated.         */
5403 /*-----------------------------------------------------------------*/
5404 static void AnalyzeLabel(pCode *pc)
5405 {
5406
5407   pic16_pCodeUnlink(pc);
5408
5409 }
5410 #endif
5411
5412 #if 0
5413 static void AnalyzeGOTO(pCode *pc)
5414 {
5415
5416   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5417
5418 }
5419
5420 static void AnalyzeSKIP(pCode *pc)
5421 {
5422
5423   pBranchLink(pc,pic16_findNextInstruction(pc->next));
5424   pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5425
5426 }
5427
5428 static void AnalyzeRETURN(pCode *pc)
5429 {
5430
5431   //  branch_link(pc,findFunctionEnd(pc->next));
5432
5433 }
5434
5435 #endif
5436
5437 /*-----------------------------------------------------------------*/
5438 /*-----------------------------------------------------------------*/
5439 regs * pic16_getRegFromInstruction(pCode *pc)
5440 {
5441
5442   if(!pc                   || 
5443      !isPCI(pc)            ||
5444      !PCI(pc)->pcop        ||
5445      PCI(pc)->num_ops == 0 ||
5446      (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5447     return NULL;
5448
5449 #if 0
5450   fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5451         dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5452 #endif
5453
5454   switch(PCI(pc)->pcop->type) {
5455   case PO_PRODL:
5456   case PO_PRODH:
5457
5458   case PO_INDF0:
5459   case PO_FSR0:
5460     return PCOR(PCI(pc)->pcop)->r;
5461
5462   case PO_BIT:
5463   case PO_GPR_TEMP:
5464 //      fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5465     return PCOR(PCI(pc)->pcop)->r;
5466
5467   case PO_IMMEDIATE:
5468 //    return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5469
5470     if(PCOI(PCI(pc)->pcop)->r)
5471       return (PCOI(PCI(pc)->pcop)->r);
5472     else
5473       return NULL;
5474     
5475   case PO_GPR_BIT:
5476     return PCOR(PCI(pc)->pcop)->r;
5477
5478   case PO_GPR_REGISTER:
5479   case PO_DIR:
5480 //      fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5481     return PCOR(PCI(pc)->pcop)->r;
5482
5483   case PO_LITERAL:
5484     //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5485     break;
5486
5487   default:
5488 //      fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5489 //      genericPrint(stderr, pc);
5490 //      assert( 0 );
5491         break;
5492   }
5493
5494   return NULL;
5495 }
5496
5497 /*-------------------------------------------------------------------------------*/
5498 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5499 /*-------------------------------------------------------------------------------*/
5500 regs * pic16_getRegFromInstruction2(pCode *pc)
5501 {
5502
5503   if(!pc                   || 
5504      !isPCI(pc)            ||
5505      !PCI(pc)->pcop        ||
5506      PCI(pc)->num_ops == 0 ||
5507      (PCI(pc)->num_ops == 1))           // accept only 2 operand commands
5508     return NULL;
5509
5510
5511 #if 0
5512   fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5513         dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5514 #endif
5515
5516 /*
5517  * operands supported in MOVFF:
5518  *  PO_INF0/PO_FSR0
5519  *  PO_GPR_TEMP
5520  *  PO_IMMEDIATE
5521  *  PO_DIR
5522  *
5523  */
5524   switch(PCI(pc)->pcop->type) {
5525   case PO_PRODL:
5526   case PO_PRODH:
5527
5528   case PO_INDF0:
5529   case PO_FSR0:
5530     return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5531
5532     //    return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5533
5534 //  case PO_BIT:
5535   case PO_GPR_TEMP:
5536     //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5537     return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5538
5539   case PO_IMMEDIATE:
5540 #if 0
5541 //    if(PCOI(PCI(pc)->pcop)->r)
5542 //      return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5543
5544     //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5545     return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5546 #endif
5547
5548     if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5549       return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5550     else
5551       return NULL;
5552
5553
5554   case PO_GPR_BIT:
5555         break;
5556 //    return PCOR2(PCI(pc)->pcop)->r;
5557
5558   case PO_GPR_REGISTER:
5559   case PO_DIR:
5560     //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5561     return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5562
5563   case PO_LITERAL:
5564         break;
5565     //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5566
5567   default:
5568     //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5569     //genericPrint(stderr, pc);
5570     break;
5571   }
5572
5573   return NULL;
5574
5575 }
5576
5577 /*-----------------------------------------------------------------*/
5578 /*-----------------------------------------------------------------*/
5579
5580 static void AnalyzepBlock(pBlock *pb)
5581 {
5582   pCode *pc;
5583
5584   if(!pb)
5585     return;
5586
5587   /* Find all of the registers used in this pBlock 
5588    * by looking at each instruction and examining it's
5589    * operands
5590    */
5591   for(pc = pb->pcHead; pc; pc = pc->next) {
5592
5593     /* Is this an instruction with operands? */
5594     if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5595
5596       if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5597
5598         /* Loop through all of the registers declared so far in
5599            this block and see if we find this one there */
5600
5601         regs *r = setFirstItem(pb->tregisters);
5602
5603         while(r) {
5604           if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5605             PCOR(PCI(pc)->pcop)->r = r;
5606             break;
5607           }
5608           r = setNextItem(pb->tregisters);
5609         }
5610
5611         if(!r) {
5612           /* register wasn't found */
5613           //r = Safe_calloc(1, sizeof(regs));
5614           //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5615           //addSet(&pb->tregisters, r);
5616           addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5617           //PCOR(PCI(pc)->pcop)->r = r;
5618           //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5619         }/* else 
5620           fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5621          */
5622       }
5623       if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5624         if(PCOR(PCI(pc)->pcop)->r) {
5625           pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5626           DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5627         } else {
5628           if(PCI(pc)->pcop->name)
5629             fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5630           else
5631             fprintf(stderr,"ERROR: NULL register\n");
5632         }
5633       }
5634     }
5635
5636
5637   }
5638 }
5639
5640 /*-----------------------------------------------------------------*/
5641 /* */
5642 /*-----------------------------------------------------------------*/
5643 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5644
5645 static void InsertpFlow(pCode *pc, pCode **pflow)
5646 {
5647   if(*pflow)
5648     PCFL(*pflow)->end = pc;
5649
5650   if(!pc || !pc->next)
5651     return;
5652
5653   *pflow = pic16_newpCodeFlow();
5654   pic16_pCodeInsertAfter(pc, *pflow);
5655 }
5656
5657 /*-----------------------------------------------------------------*/
5658 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
5659 /*                         the flow blocks.                        */
5660 /*
5661  * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5662  * point the instruction flow changes. 
5663  */
5664 /*-----------------------------------------------------------------*/
5665 void pic16_BuildFlow(pBlock *pb)
5666 {
5667   pCode *pc;
5668   pCode *last_pci=NULL;
5669   pCode *pflow=NULL;
5670   int seq = 0;
5671
5672   if(!pb)
5673     return;
5674
5675   //fprintf (stderr,"build flow start seq %d  ",GpcFlowSeq);
5676   /* Insert a pCodeFlow object at the beginning of a pBlock */
5677
5678   InsertpFlow(pb->pcHead, &pflow);
5679
5680   //pflow = pic16_newpCodeFlow();    /* Create a new Flow object */
5681   //pflow->next = pb->pcHead;  /* Make the current head the next object */
5682   //pb->pcHead->prev = pflow;  /* let the current head point back to the flow object */
5683   //pb->pcHead = pflow;        /* Make the Flow object the head */
5684   //pflow->pb = pb;
5685
5686   for( pc = pic16_findNextInstruction(pb->pcHead);
5687        pc != NULL;
5688        pc=pic16_findNextInstruction(pc)) { 
5689
5690     pc->seq = seq++;
5691     PCI(pc)->pcflow = PCFL(pflow);
5692
5693     //fprintf(stderr," build: ");
5694     //pflow->print(stderr,pflow);
5695
5696     if( PCI(pc)->isSkip) {
5697
5698       /* The two instructions immediately following this one 
5699        * mark the beginning of a new flow segment */
5700
5701       while(pc && PCI(pc)->isSkip) {
5702
5703         PCI(pc)->pcflow = PCFL(pflow);
5704         pc->seq = seq-1;
5705         seq = 1;
5706
5707         InsertpFlow(pc, &pflow);
5708         pc=pic16_findNextInstruction(pc->next);
5709       }
5710
5711       seq = 0;
5712
5713       if(!pc)
5714         break;
5715
5716       PCI(pc)->pcflow = PCFL(pflow);
5717       pc->seq = 0;
5718       InsertpFlow(pc, &pflow);
5719
5720     } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next)))  {
5721
5722       InsertpFlow(pc, &pflow);
5723       seq = 0;
5724
5725     } else if (checkLabel(pc)) { 
5726
5727       /* This instruction marks the beginning of a
5728        * new flow segment */
5729
5730       pc->seq = 0;
5731       seq = 1;
5732
5733       /* If the previous pCode is not a flow object, then 
5734        * insert a new flow object. (This check prevents 
5735        * two consecutive flow objects from being insert in
5736        * the case where a skip instruction preceeds an
5737        * instruction containing a label.) */
5738
5739       if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5740         InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5741
5742       PCI(pc)->pcflow = PCFL(pflow);
5743       
5744     }
5745     last_pci = pc;
5746     pc = pc->next;
5747   }
5748
5749   //fprintf (stderr,",end seq %d",GpcFlowSeq);
5750   if(pflow)
5751     PCFL(pflow)->end = pb->pcTail;
5752 }
5753
5754 /*-------------------------------------------------------------------*/
5755 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
5756 /*                           the flow blocks.                        */
5757 /*
5758  * unBuildFlow removes pCodeFlow objects from a pCode chain
5759  */
5760 /*-----------------------------------------------------------------*/
5761 static void unBuildFlow(pBlock *pb)
5762 {
5763   pCode *pc,*pcnext;
5764
5765   if(!pb)
5766     return;
5767
5768   pc = pb->pcHead;
5769
5770   while(pc) {
5771     pcnext = pc->next;
5772
5773     if(isPCI(pc)) {
5774
5775       pc->seq = 0;
5776       if(PCI(pc)->pcflow) {
5777         //free(PCI(pc)->pcflow);
5778         PCI(pc)->pcflow = NULL;
5779       }
5780
5781     } else if(isPCFL(pc) )
5782       pc->destruct(pc);
5783
5784     pc = pcnext;
5785   }
5786
5787
5788 }
5789 #if 0
5790 /*-----------------------------------------------------------------*/
5791 /*-----------------------------------------------------------------*/
5792 static void dumpCond(int cond)
5793 {
5794
5795   static char *pcc_str[] = {
5796     //"PCC_NONE",
5797     "PCC_REGISTER",
5798     "PCC_C",
5799     "PCC_Z",
5800     "PCC_DC",
5801     "PCC_OV",
5802     "PCC_N",
5803     "PCC_W",
5804     "PCC_EXAMINE_PCOP",
5805     "PCC_LITERAL",
5806     "PCC_REL_ADDR"
5807   };
5808
5809   int ncond = sizeof(pcc_str) / sizeof(char *);
5810   int i,j;
5811
5812   fprintf(stderr, "0x%04X\n",cond);
5813
5814   for(i=0,j=1; i<ncond; i++, j<<=1)
5815     if(cond & j)
5816       fprintf(stderr, "  %s\n",pcc_str[i]);
5817
5818 }
5819 #endif
5820
5821 #if 0
5822 /*-----------------------------------------------------------------*/
5823 /*-----------------------------------------------------------------*/
5824 static void FlowStats(pCodeFlow *pcflow)
5825 {
5826
5827   pCode *pc;
5828
5829   if(!isPCFL(pcflow))
5830     return;
5831
5832   fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
5833
5834   pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE); 
5835
5836   if(!pc) {
5837     fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
5838     return;
5839   }
5840
5841
5842   fprintf(stderr, "  FlowStats inCond: ");
5843   dumpCond(pcflow->inCond);
5844   fprintf(stderr, "  FlowStats outCond: ");
5845   dumpCond(pcflow->outCond);
5846
5847 }
5848 #endif
5849 /*-----------------------------------------------------------------*
5850  * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
5851  *    if it affects the banking bits. 
5852  * 
5853  * return: -1 == Banking bits are unaffected by this pCode.
5854  *
5855  * return: > 0 == Banking bits are affected.
5856  *
5857  *  If the banking bits are affected, then the returned value describes
5858  * which bits are affected and how they're affected. The lower half
5859  * of the integer maps to the bits that are affected, the upper half
5860  * to whether they're set or cleared.
5861  *
5862  *-----------------------------------------------------------------*/
5863
5864 static int isBankInstruction(pCode *pc)
5865 {
5866   regs *reg;
5867   int bank = -1;
5868
5869   if(!isPCI(pc))
5870     return -1;
5871
5872   if( PCI(pc)->op == POC_MOVLB ||
5873       (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
5874     bank = PCOL(pc)->lit;
5875   }
5876
5877   return bank;
5878 }
5879
5880
5881 /*-----------------------------------------------------------------*/
5882 /*-----------------------------------------------------------------*/
5883 static void FillFlow(pCodeFlow *pcflow)
5884 {
5885
5886   pCode *pc;
5887   int cur_bank;
5888
5889   if(!isPCFL(pcflow))
5890     return;
5891
5892   //  fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
5893
5894   pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE); 
5895
5896   if(!pc) {
5897     //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
5898     return;
5899   }
5900
5901   cur_bank = -1;
5902
5903   do {
5904     isBankInstruction(pc);
5905     pc = pc->next;
5906   } while (pc && (pc != pcflow->end) && !isPCFL(pc));
5907
5908 /*
5909   if(!pc ) {
5910     fprintf(stderr, "  FillFlow - Bad end of flow\n");
5911   } else {
5912     fprintf(stderr, "  FillFlow - Ending flow with\n  ");
5913     pc->print(stderr,pc);
5914   }
5915
5916   fprintf(stderr, "  FillFlow inCond: ");
5917   dumpCond(pcflow->inCond);
5918   fprintf(stderr, "  FillFlow outCond: ");
5919   dumpCond(pcflow->outCond);
5920 */
5921 }
5922
5923 /*-----------------------------------------------------------------*/
5924 /*-----------------------------------------------------------------*/
5925 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
5926 {
5927   pCodeFlowLink *fromLink, *toLink;
5928
5929   if(!from || !to || !to->pcflow || !from->pcflow)
5930     return;
5931
5932   fromLink = pic16_newpCodeFlowLink(from->pcflow);
5933   toLink   = pic16_newpCodeFlowLink(to->pcflow);
5934
5935   addSetIfnotP(&(from->pcflow->to), toLink);   //to->pcflow);
5936   addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
5937
5938 }
5939
5940 /*-----------------------------------------------------------------*
5941  * void LinkFlow(pBlock *pb)
5942  *
5943  * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
5944  * non-branching segments. In LinkFlow, we determine the execution
5945  * order of these segments. For example, if one of the segments ends
5946  * with a skip, then we know that there are two possible flow segments
5947  * to which control may be passed.
5948  *-----------------------------------------------------------------*/
5949 static void LinkFlow(pBlock *pb)
5950 {
5951   pCode *pc=NULL;
5952   pCode *pcflow;
5953   pCode *pct;
5954
5955   //fprintf(stderr,"linkflow \n");
5956
5957   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
5958        pcflow != NULL;
5959        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
5960
5961     if(!isPCFL(pcflow))
5962       fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
5963
5964     //fprintf(stderr," link: ");
5965     //pcflow->print(stderr,pcflow);
5966
5967     //FillFlow(PCFL(pcflow));
5968
5969     pc = PCFL(pcflow)->end;
5970
5971     //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
5972     if(isPCI_SKIP(pc)) {
5973       //fprintf(stderr, "ends with skip\n");
5974       //pc->print(stderr,pc);
5975       pct=pic16_findNextInstruction(pc->next);
5976       LinkFlow_pCode(PCI(pc),PCI(pct));
5977       pct=pic16_findNextInstruction(pct->next);
5978       LinkFlow_pCode(PCI(pc),PCI(pct));
5979       continue;
5980     }
5981
5982     if(isPCI_BRANCH(pc)) {
5983       pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
5984
5985       //fprintf(stderr, "ends with branch\n  ");
5986       //pc->print(stderr,pc);
5987
5988       if(!(pcol && isPCOLAB(pcol))) {
5989         if((PCI(pc)->op != POC_RETLW)
5990                 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
5991         
5992                 /* continue if label is '$' which assembler knows how to parse */
5993                 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
5994
5995                 if(pic16_pcode_verbose) {
5996                         pc->print(stderr,pc);
5997                         fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
5998                 }
5999         }
6000         continue;
6001       }
6002
6003       if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
6004         LinkFlow_pCode(PCI(pc),PCI(pct));
6005       else
6006         fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
6007                 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
6008
6009 //      fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6010
6011       continue;
6012     }
6013
6014     if(isPCI(pc)) {
6015       //fprintf(stderr, "ends with non-branching instruction:\n");
6016       //pc->print(stderr,pc);
6017
6018       LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6019
6020       continue;
6021     }
6022
6023     if(pc) {
6024       //fprintf(stderr, "ends with unknown\n");
6025       //pc->print(stderr,pc);
6026       continue;
6027     }
6028
6029     //fprintf(stderr, "ends with nothing: ERROR\n");
6030     
6031   }
6032 }
6033 /*-----------------------------------------------------------------*/
6034 /*-----------------------------------------------------------------*/
6035
6036 /*-----------------------------------------------------------------*/
6037 /*-----------------------------------------------------------------*/
6038 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6039 {
6040
6041   if(!pc || !pcflow)
6042     return 0;
6043
6044   if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6045     return 0;
6046
6047   if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6048     return 1;
6049
6050   return 0;
6051 }
6052
6053
6054
6055
6056
6057 /*-----------------------------------------------------------------*/
6058 /* insertBankSwitch - inserts a bank switch statement in the       */
6059 /*                    assembly listing                             */
6060 /*                                                                 */
6061 /* position == 0: insert before                                    */
6062 /* position == 1: insert after pc                                  */
6063 /* position == 2: like 0 but previous was a skip instruction       */
6064 /*-----------------------------------------------------------------*/
6065 pCodeOp *pic16_popGetLabel(unsigned int key);
6066 extern int pic16_labelOffset;
6067
6068 static void insertBankSwitch(unsigned char position, pCode *pc)
6069 {
6070   pCode *new_pc;
6071
6072         if(!pc)
6073                 return;
6074
6075         /* emit BANKSEL [symbol] */
6076
6077
6078         new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6079         
6080 //      position = 0;           // position is always before (sanity check!)
6081
6082 #if 0
6083         fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6084         pc->print(stderr, pc);
6085 #endif
6086
6087         switch(position) {
6088                 case 1: {
6089                         /* insert the bank switch after this pc instruction */
6090                         pCode *pcnext = pic16_findNextInstruction(pc);
6091
6092                                 pic16_pCodeInsertAfter(pc, new_pc);
6093                                 if(pcnext)pc = pcnext;
6094                 }; break;
6095                 
6096                 case 0:
6097                         /* insert the bank switch BEFORE this pc instruction */
6098                         pic16_pCodeInsertAfter(pc->prev, new_pc);
6099                         break;
6100
6101                 case 2: {
6102                           symbol *tlbl;
6103                           pCode *pcnext, *pcprev, *npci, *ppc;
6104                           PIC_OPCODE ipci;
6105                           int ofs1=0, ofs2=0, len=0;
6106                           
6107                         /* just like 0, but previous was a skip instruction,
6108                          * so some care should be taken */
6109                           
6110                                 pic16_labelOffset += 10000;
6111                                 tlbl = newiTempLabel(NULL);
6112                                 
6113                                 /* invert skip instruction */
6114                                 pcprev = pic16_findPrevInstruction(pc->prev);
6115                                 ipci = PCI(pcprev)->inverted_op;
6116                                 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6117
6118 //                              fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6119
6120                                 /* copy info from old pCode */
6121                                 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6122                                 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6123                                 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6124                                 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6125                                 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6126                                 PCI(npci)->op = PCI(pcprev)->inverted_op;
6127                                 
6128                                 /* unlink old pCode */
6129                                 ppc = pcprev->prev;
6130                                 ppc->next = pcprev->next;
6131                                 pcprev->next->prev = ppc;
6132                                 pic16_pCodeInsertAfter(ppc, npci);
6133                                 
6134                                 /* extra instructions to handle invertion */
6135                                 pcnext = pic16_newpCode(POC_GOTO, pic16_popGetLabel(tlbl->key));
6136                                 pic16_pCodeInsertAfter(npci, pcnext);
6137                                 pic16_pCodeInsertAfter(pc->prev, new_pc);
6138                                 
6139                                 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6140                                 pic16_pCodeInsertAfter(pc, pcnext);
6141                         }; break;
6142         }
6143         
6144
6145         /* Move the label, if there is one */
6146         if(PCI(pc)->label) {
6147 //              fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6148 //                      __FILE__, __LINE__, pc, new_pc);
6149                 PCAD(new_pc)->pci.label = PCI(pc)->label;
6150                 PCI(pc)->label = NULL;
6151         }
6152 }
6153
6154
6155 /*-----------------------------------------------------------------*/
6156 /*int compareBankFlow - compare the banking requirements between   */
6157 /*  flow objects. */
6158 /*-----------------------------------------------------------------*/
6159 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6160 {
6161
6162   if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6163     return 0;
6164
6165   if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6166     return 0;
6167
6168   if(pcflow->firstBank == -1)
6169     return 0;
6170
6171
6172   if(pcflowLink->pcflow->firstBank == -1) {
6173     pCodeFlowLink *pctl = setFirstItem( toORfrom ? 
6174                                         pcflowLink->pcflow->to : 
6175                                         pcflowLink->pcflow->from);
6176     return compareBankFlow(pcflow, pctl, toORfrom);
6177   }
6178
6179   if(toORfrom) {
6180     if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6181       return 0;
6182
6183     pcflowLink->bank_conflict++;
6184     pcflowLink->pcflow->FromConflicts++;
6185     pcflow->ToConflicts++;
6186   } else {
6187     
6188     if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6189       return 0;
6190
6191     pcflowLink->bank_conflict++;
6192     pcflowLink->pcflow->ToConflicts++;
6193     pcflow->FromConflicts++;
6194
6195   }
6196   /*
6197   fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6198           pcflowLink->pcflow->pc.seq,
6199           pcflowLink->pcflow->FromConflicts,
6200           pcflowLink->pcflow->ToConflicts);
6201   */
6202   return 1;
6203
6204 }
6205
6206 #if 0
6207 /*-----------------------------------------------------------------*/
6208 /*-----------------------------------------------------------------*/
6209 static void DumpFlow(pBlock *pb)
6210 {
6211   pCode *pc=NULL;
6212   pCode *pcflow;
6213   pCodeFlowLink *pcfl;
6214
6215
6216   fprintf(stderr,"Dump flow \n");
6217   pb->pcHead->print(stderr, pb->pcHead);
6218
6219   pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6220   pcflow->print(stderr,pcflow);
6221
6222   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
6223        pcflow != NULL;
6224        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6225
6226     if(!isPCFL(pcflow)) {
6227       fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6228       continue;
6229     }
6230     fprintf(stderr,"dumping: ");
6231     pcflow->print(stderr,pcflow);
6232     FlowStats(PCFL(pcflow));
6233
6234     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6235
6236       pc = PCODE(pcfl->pcflow);
6237
6238       fprintf(stderr, "    from seq %d:\n",pc->seq);
6239       if(!isPCFL(pc)) {
6240         fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6241         pc->print(stderr,pc);
6242       }
6243
6244     }
6245
6246     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6247
6248       pc = PCODE(pcfl->pcflow);
6249
6250       fprintf(stderr, "    to seq %d:\n",pc->seq);
6251       if(!isPCFL(pc)) {
6252         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6253         pc->print(stderr,pc);
6254       }
6255
6256     }
6257
6258   }
6259
6260 }
6261 #endif
6262 /*-----------------------------------------------------------------*/
6263 /*-----------------------------------------------------------------*/
6264 static int OptimizepBlock(pBlock *pb)
6265 {
6266   pCode *pc, *pcprev;
6267   int matches =0;
6268
6269   if(!pb || !peepOptimizing)
6270     return 0;
6271
6272   DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6273 /*
6274   for(pc = pb->pcHead; pc; pc = pc->next)
6275     matches += pic16_pCodePeepMatchRule(pc);
6276 */
6277
6278   pc = pic16_findNextInstruction(pb->pcHead);
6279   if(!pc)
6280     return 0;
6281
6282   pcprev = pc->prev;
6283   do {
6284
6285
6286     if(pic16_pCodePeepMatchRule(pc)) {
6287
6288       matches++;
6289
6290       if(pcprev)
6291         pc = pic16_findNextInstruction(pcprev->next);
6292       else 
6293         pc = pic16_findNextInstruction(pb->pcHead);
6294     } else
6295       pc = pic16_findNextInstruction(pc->next);
6296   } while(pc);
6297
6298   if(matches)
6299     DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6300   return matches;
6301
6302 }
6303
6304 /*-----------------------------------------------------------------*/
6305 /*-----------------------------------------------------------------*/
6306 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6307 {
6308   pCode *pc;
6309
6310   for(pc = pcs; pc; pc = pc->next) {
6311
6312     if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) && 
6313        (PCI(pc)->pcop) && 
6314        (PCI(pc)->pcop->type == PO_LABEL) &&
6315        (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6316       return pc;
6317   }
6318  
6319
6320   return NULL;
6321 }
6322
6323 /*-----------------------------------------------------------------*/
6324 /*-----------------------------------------------------------------*/
6325 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6326 {
6327
6328   char *s=NULL;
6329
6330   if(isPCI(pc) && 
6331      (PCI(pc)->pcop) && 
6332      (PCI(pc)->pcop->type == PO_LABEL)) {
6333
6334     pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6335
6336 //      fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6337 //    if(pcol->pcop.name)
6338 //      free(pcol->pcop.name);
6339
6340     /* If the key is negative, then we (probably) have a label to
6341      * a function and the name is already defined */
6342        
6343     if(pcl->key>0)
6344       sprintf(s=buffer,"_%05d_DS_",pcl->key);
6345     else 
6346       s = pcl->label;
6347
6348     //sprintf(buffer,"_%05d_DS_",pcl->key);
6349     if(!s) {
6350       fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6351     }
6352     pcol->pcop.name = Safe_strdup(s);
6353     pcol->key = pcl->key;
6354     //pc->print(stderr,pc);
6355
6356   }
6357
6358
6359 }
6360
6361 /*-----------------------------------------------------------------*/
6362 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
6363 /*                            pCode chain if they're not used.     */
6364 /*-----------------------------------------------------------------*/
6365 static void pBlockRemoveUnusedLabels(pBlock *pb)
6366 {
6367   pCode *pc; pCodeLabel *pcl;
6368
6369   if(!pb)
6370     return;
6371
6372   for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6373
6374     pBranch *pbr = PCI(pc)->label;
6375     if(pbr && pbr->next) {
6376       pCode *pcd = pb->pcHead;
6377
6378 //      fprintf(stderr, "multiple labels\n");
6379 //      pc->print(stderr,pc);
6380
6381       pbr = pbr->next;
6382       while(pbr) {
6383
6384         while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6385           //fprintf(stderr,"Used by:\n");
6386           //pcd->print(stderr,pcd);
6387
6388           exchangeLabels(PCL(pbr->pc),pcd);
6389
6390           pcd = pcd->next;
6391         }
6392         pbr = pbr->next;
6393       }
6394     }
6395   }
6396
6397   for(pc = pb->pcHead; pc; pc = pc->next) {
6398
6399     if(isPCL(pc)) // pc->type == PC_LABEL)
6400       pcl = PCL(pc);
6401     else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6402       pcl = PCL(PCI(pc)->label->pc);
6403     else continue;
6404
6405 //      fprintf(stderr," found  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6406
6407     /* This pCode is a label, so search the pBlock to see if anyone
6408      * refers to it */
6409
6410     if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6411         && (!pcl->force)) {
6412     //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6413       /* Couldn't find an instruction that refers to this label
6414        * So, unlink the pCode label from it's pCode chain
6415        * and destroy the label */
6416 //      fprintf(stderr," removed  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6417
6418       DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6419       if(pc->type == PC_LABEL) {
6420         pic16_unlinkpCode(pc);
6421         pCodeLabelDestruct(pc);
6422       } else {
6423         unlinkpCodeFromBranch(pc, PCODE(pcl));
6424         /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6425           free(pc->label);
6426         }*/
6427       }
6428
6429     }
6430   }
6431
6432 }
6433
6434
6435 /*-----------------------------------------------------------------*/
6436 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode      */
6437 /*                     chain and put them into pBranches that are  */
6438 /*                     associated with the appropriate pCode       */
6439 /*                     instructions.                               */
6440 /*-----------------------------------------------------------------*/
6441 void pic16_pBlockMergeLabels(pBlock *pb)
6442 {
6443   pBranch *pbr;
6444   pCode *pc, *pcnext=NULL;
6445
6446   if(!pb)
6447     return;
6448
6449   /* First, Try to remove any unused labels */
6450   //pBlockRemoveUnusedLabels(pb);
6451
6452   /* Now loop through the pBlock and merge the labels with the opcodes */
6453
6454   pc = pb->pcHead;
6455   //  for(pc = pb->pcHead; pc; pc = pc->next) {
6456
6457   while(pc) {
6458     pCode *pcn = pc->next;
6459
6460     if(pc->type == PC_LABEL) {
6461
6462 //      fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6463 //      fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6464
6465       if((pcnext = pic16_findNextInstruction(pc) )) {
6466
6467 //              pcnext->print(stderr, pcnext);
6468
6469         // Unlink the pCode label from it's pCode chain
6470         pic16_unlinkpCode(pc);
6471         
6472 //      fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6473         // And link it into the instruction's pBranch labels. (Note, since
6474         // it's possible to have multiple labels associated with one instruction
6475         // we must provide a means to accomodate the additional labels. Thus
6476         // the labels are placed into the singly-linked list "label" as 
6477         // opposed to being a single member of the pCodeInstruction.)
6478
6479         //_ALLOC(pbr,sizeof(pBranch));
6480 #if 1
6481         pbr = Safe_calloc(1,sizeof(pBranch));
6482         pbr->pc = pc;
6483         pbr->next = NULL;
6484
6485         PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6486 #endif
6487       } else {
6488         if(pic16_pcode_verbose)
6489         fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6490       }
6491     } else if(pc->type == PC_CSOURCE) {
6492
6493       /* merge the source line symbolic info into the next instruction */
6494       if((pcnext = pic16_findNextInstruction(pc) )) {
6495
6496         // Unlink the pCode label from it's pCode chain
6497         pic16_unlinkpCode(pc);
6498         PCI(pcnext)->cline = PCCS(pc);
6499         //fprintf(stderr, "merging CSRC\n");
6500         //genericPrint(stderr,pcnext);
6501       }
6502
6503     }
6504     pc = pcn;
6505   }
6506   pBlockRemoveUnusedLabels(pb);
6507
6508 }
6509
6510 /*-----------------------------------------------------------------*/
6511 /*-----------------------------------------------------------------*/
6512 static int OptimizepCode(char dbName)
6513 {
6514 #define MAX_PASSES 4
6515
6516   int matches = 0;
6517   int passes = 0;
6518   pBlock *pb;
6519
6520   if(!the_pFile)
6521     return 0;
6522
6523   DFPRINTF((stderr," Optimizing pCode\n"));
6524
6525   do {
6526     matches = 0;
6527     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6528       if('*' == dbName || getpBlock_dbName(pb) == dbName)
6529         matches += OptimizepBlock(pb);
6530     }
6531   }
6532   while(matches && ++passes < MAX_PASSES);
6533
6534   return matches;
6535 }
6536
6537
6538
6539 const char *pic16_pCodeOpType(pCodeOp *pcop);
6540 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6541
6542
6543 /*-----------------------------------------------------------------*/
6544 /* pic16_popCopyGPR2Bit - copy a pcode operator                          */
6545 /*-----------------------------------------------------------------*/
6546
6547 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6548 {
6549   pCodeOp *pcop;
6550
6551 //  fprintf(stderr, "%s:%d pc type: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc));
6552   pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6553
6554   if( !( (pcop->type == PO_LABEL) ||
6555          (pcop->type == PO_LITERAL) ||
6556          (pcop->type == PO_STR) ))
6557     PCOR(pcop)->r = PCOR(pc)->r;  /* This is dangerous... */
6558     PCOR(pcop)->r->wasUsed = 1;
6559
6560   return pcop;
6561 }
6562
6563
6564 /*----------------------------------------------------------------------*
6565  * pic16_areRegsSame - check to see if the names of two registers match *
6566  *----------------------------------------------------------------------*/
6567 int pic16_areRegsSame(regs *r1, regs *r2)
6568 {
6569         if(!strcmp(r1->name, r2->name))return 1;
6570
6571   return 0;
6572 }
6573
6574
6575 /*-----------------------------------------------------------------*/
6576 /*-----------------------------------------------------------------*/
6577 static void pic16_FixRegisterBanking(pBlock *pb)
6578 {
6579   pCode *pc=NULL;
6580   pCode *pcprev=NULL;
6581   regs *reg, *prevreg;
6582   unsigned char flag=0;
6583   
6584         if(!pb)
6585                 return;
6586
6587         pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6588         if(!pc)return;
6589
6590         /* loop through all of the flow blocks with in one pblock */
6591
6592 //      fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6593
6594         prevreg = NULL;
6595         do {
6596                 /* at this point, pc should point to a PC_FLOW object */
6597                 /* for each flow block, determine the register banking 
6598                  * requirements */
6599
6600                 if(!isPCI(pc))goto loop;
6601
6602                 if(PCI(pc)->is2MemOp)goto loop;
6603        
6604                 reg = pic16_getRegFromInstruction(pc);
6605
6606 #if 0
6607                 pc->print(stderr, pc);
6608                 fprintf(stderr, "reg = %p\n", reg);
6609
6610                 if(reg) {
6611                         fprintf(stderr, "%s:%d:  %s  %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6612                         fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6613                                 reg->address,reg->isBitField, reg->isFixed);
6614                 }
6615 #endif
6616
6617                 /* now make some tests to make sure that instruction needs bank switch */
6618
6619                 /* if no register exists, and if not a bit opcode goto loop */
6620                 if(!reg) {
6621                         if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6622                 }
6623                  
6624                 if(isPCI_SKIP(pc)) {
6625 //                      fprintf(stderr, "instruction is SKIP instruction\n");
6626                 }
6627                 if(reg && isACCESS_BANK(reg))goto loop;
6628
6629                 if(!isBankInstruction(pc))goto loop;
6630
6631                 if(isPCI_LIT(pc))goto loop;
6632          
6633                 if(PCI(pc)->op == POC_CALL)goto loop;
6634
6635                 /* Examine the instruction before this one to make sure it is
6636                  * not a skip type instruction */
6637                 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6638
6639                 flag = 0;               /* add before this instruction */
6640                 
6641                 /* if previous instruction is a skip one, then set flag
6642                  * to 2 and call insertBankSwitch */
6643                 if(pcprev && isPCI_SKIP(pcprev))flag=2; //goto loop;
6644                  
6645                 prevreg = reg;
6646                 insertBankSwitch(flag, pc);
6647                 pcprev = pc;
6648
6649 //              fprintf(stderr, "BANK SWITCH inserted\n");
6650                 
6651 loop:
6652                 pc = pc->next;
6653         } while (pc);
6654 }
6655
6656
6657
6658 static void pBlockDestruct(pBlock *pb)
6659 {
6660
6661   if(!pb)
6662     return;
6663
6664
6665 //  free(pb);
6666
6667 }
6668
6669 /*-----------------------------------------------------------------*/
6670 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
6671 /*                                  name dbName and combine them   */
6672 /*                                  into one block                 */
6673 /*-----------------------------------------------------------------*/
6674 static void mergepBlocks(char dbName)
6675 {
6676
6677   pBlock *pb, *pbmerged = NULL,*pbn;
6678
6679   pb = the_pFile->pbHead;
6680
6681   //fprintf(stderr," merging blocks named %c\n",dbName);
6682   while(pb) {
6683
6684     pbn = pb->next;
6685     //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
6686     if( getpBlock_dbName(pb) == dbName) {
6687
6688       //fprintf(stderr," merged block %c\n",dbName);
6689
6690       if(!pbmerged) {
6691         pbmerged = pb;
6692       } else {
6693         pic16_addpCode2pBlock(pbmerged, pb->pcHead);
6694         /* pic16_addpCode2pBlock doesn't handle the tail: */
6695         pbmerged->pcTail = pb->pcTail;
6696
6697         pb->prev->next = pbn;
6698         if(pbn) 
6699           pbn->prev = pb->prev;
6700
6701
6702         pBlockDestruct(pb);
6703       }
6704       //pic16_printpBlock(stderr, pbmerged);
6705     } 
6706     pb = pbn;
6707   }
6708
6709 }
6710
6711 /*-----------------------------------------------------------------*/
6712 /* AnalyzeFlow - Examine the flow of the code and optimize         */
6713 /*                                                                 */
6714 /* level 0 == minimal optimization                                 */
6715 /*   optimize registers that are used only by two instructions     */
6716 /* level 1 == maximal optimization                                 */
6717 /*   optimize by looking at pairs of instructions that use the     */
6718 /*   register.                                                     */
6719 /*-----------------------------------------------------------------*/
6720
6721 static void AnalyzeFlow(int level)
6722 {
6723   static int times_called=0;
6724   pBlock *pb;
6725
6726         if(!the_pFile) {
6727
6728                 /* remove unused allocated registers before exiting */
6729                 pic16_RemoveUnusedRegisters();
6730         
6731           return;
6732         }
6733
6734
6735   /* if this is not the first time this function has been called,
6736      then clean up old flow information */
6737         if(times_called++) {
6738                 for(pb = the_pFile->pbHead; pb; pb = pb->next)
6739                         unBuildFlow(pb);
6740
6741                 pic16_RegsUnMapLiveRanges();
6742         }
6743
6744         GpcFlowSeq = 1;
6745
6746   /* Phase 2 - Flow Analysis - Register Banking
6747    *
6748    * In this phase, the individual flow blocks are examined
6749    * and register banking is fixed.
6750    */
6751
6752 #if 0
6753         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6754                 pic16_FixRegisterBanking(pb);
6755 #endif
6756
6757   /* Phase 2 - Flow Analysis
6758    *
6759    * In this phase, the pCode is partition into pCodeFlow 
6760    * blocks. The flow blocks mark the points where a continuous
6761    * stream of instructions changes flow (e.g. because of
6762    * a call or goto or whatever).
6763    */
6764
6765         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6766                 pic16_BuildFlow(pb);
6767
6768
6769   /* Phase 2 - Flow Analysis - linking flow blocks
6770    *
6771    * In this phase, the individual flow blocks are examined
6772    * to determine their order of excution.
6773    */
6774
6775         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6776                 LinkFlow(pb);
6777
6778   /* Phase 3 - Flow Analysis - Flow Tree
6779    *
6780    * In this phase, the individual flow blocks are examined
6781    * to determine their order of execution.
6782    */
6783
6784         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6785                 pic16_BuildFlowTree(pb);
6786
6787
6788   /* Phase x - Flow Analysis - Used Banks
6789    *
6790    * In this phase, the individual flow blocks are examined
6791    * to determine the Register Banks they use
6792    */
6793
6794 #if 0
6795         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6796                 FixBankFlow(pb);
6797 #endif
6798
6799
6800         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6801                 pic16_pCodeRegMapLiveRanges(pb);
6802
6803         pic16_RemoveUnusedRegisters();
6804
6805   //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
6806         pic16_pCodeRegOptimizeRegUsage(level);
6807
6808
6809         if(!options.nopeep)
6810                 OptimizepCode('*');
6811
6812
6813 #if 0
6814         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6815                 DumpFlow(pb);
6816 #endif
6817
6818   /* debug stuff */ 
6819         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6820           pCode *pcflow;
6821                 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
6822                         (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6823                         pcflow = pcflow->next) {
6824
6825                         FillFlow(PCFL(pcflow));
6826                 }
6827         }
6828
6829 #if 0
6830         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6831           pCode *pcflow;
6832
6833                 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
6834                         (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
6835                         pcflow = pcflow->next) {
6836
6837                         FlowStats(PCFL(pcflow));
6838                 }
6839         }
6840 #endif
6841 }
6842
6843 /* VR -- no need to analyze banking in flow, but left here :
6844  *      1. because it may be used in the future for other purposes
6845  *      2. because if omitted we'll miss some optimization done here
6846  *
6847  * Perhaps I should rename it to something else
6848  */
6849
6850 /*-----------------------------------------------------------------*/
6851 /* pic16_AnalyzeBanking - Called after the memory addresses have been    */
6852 /*                  assigned to the registers.                     */
6853 /*                                                                 */
6854 /*-----------------------------------------------------------------*/
6855
6856 void pic16_AnalyzeBanking(void)
6857 {
6858   pBlock  *pb;
6859
6860
6861         /* Phase x - Flow Analysis - Used Banks
6862          *
6863          * In this phase, the individual flow blocks are examined
6864          * to determine the Register Banks they use
6865          */
6866
6867         AnalyzeFlow(0);
6868         AnalyzeFlow(1);
6869
6870         if(!the_pFile)return;
6871
6872         if(!pic16_options.no_banksel) {
6873                 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6874 //                      fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
6875                         pic16_FixRegisterBanking(pb);
6876                 }
6877         }
6878
6879 }
6880
6881 /*-----------------------------------------------------------------*/
6882 /* buildCallTree - Look at the flow and extract all of the calls.  */
6883 /*-----------------------------------------------------------------*/
6884 static set *register_usage(pBlock *pb);
6885
6886 static void buildCallTree(void    )
6887 {
6888   pBranch *pbr;
6889   pBlock  *pb;
6890   pCode   *pc;
6891   regs *r;
6892   
6893   if(!the_pFile)
6894     return;
6895
6896
6897
6898   /* Now build the call tree.
6899      First we examine all of the pCodes for functions.
6900      Keep in mind that the function boundaries coincide
6901      with pBlock boundaries. 
6902
6903      The algorithm goes something like this:
6904      We have two nested loops. The outer loop iterates
6905      through all of the pBlocks/functions. The inner
6906      loop iterates through all of the pCodes for
6907      a given pBlock. When we begin iterating through
6908      a pBlock, the variable pc_fstart, pCode of the start
6909      of a function, is cleared. We then search for pCodes
6910      of type PC_FUNCTION. When one is encountered, we
6911      initialize pc_fstart to this and at the same time
6912      associate a new pBranch object that signifies a 
6913      branch entry. If a return is found, then this signifies
6914      a function exit point. We'll link the pCodes of these
6915      returns to the matching pc_fstart.
6916
6917      When we're done, a doubly linked list of pBranches
6918      will exist. The head of this list is stored in
6919      `the_pFile', which is the meta structure for all
6920      of the pCode. Look at the pic16_printCallTree function
6921      on how the pBranches are linked together.
6922
6923    */
6924   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6925     pCode *pc_fstart=NULL;
6926     for(pc = pb->pcHead; pc; pc = pc->next) {
6927
6928         if(isPCI(pc) && pc_fstart) {
6929                 if(PCI(pc)->is2MemOp) {
6930                         r = pic16_getRegFromInstruction2(pc);
6931                         if(r && !strcmp(r->name, "POSTDEC1"))
6932                                 PCF(pc_fstart)->stackusage++;
6933                 } else {
6934                         r = pic16_getRegFromInstruction(pc);
6935                         if(r && !strcmp(r->name, "PREINC1"))
6936                                 PCF(pc_fstart)->stackusage--;
6937                 }
6938         }
6939
6940       if(isPCF(pc)) {
6941         if (PCF(pc)->fname) {
6942
6943           if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
6944             //fprintf(stderr," found main \n");
6945             pb->cmemmap = NULL;  /* FIXME do we need to free ? */
6946             pb->dbName = 'M';
6947           }
6948
6949           pbr = Safe_calloc(1,sizeof(pBranch));
6950           pbr->pc = pc_fstart = pc;
6951           pbr->next = NULL;
6952
6953           the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
6954
6955           // Here's a better way of doing the same:
6956           addSet(&pb->function_entries, pc);
6957
6958         } else {
6959           // Found an exit point in a function, e.g. return
6960           // (Note, there may be more than one return per function)
6961           if(pc_fstart)
6962             pBranchLink(PCF(pc_fstart), PCF(pc));
6963
6964           addSet(&pb->function_exits, pc);
6965         }
6966       } else if(isCALL(pc)) {
6967         addSet(&pb->function_calls,pc);
6968       }
6969     }
6970   }
6971
6972
6973 #if 0
6974   /* This is not needed because currently all register used
6975    * by a function are stored in stack -- VR */
6976    
6977   /* Re-allocate the registers so that there are no collisions
6978    * between local variables when one function call another */
6979
6980   // this is weird...
6981   //  pic16_deallocateAllRegs();
6982
6983   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6984     if(!pb->visited)
6985       register_usage(pb);
6986   }
6987 #endif
6988
6989 }
6990
6991 /*-----------------------------------------------------------------*/
6992 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
6993 /*                all of the logical connections.                  */
6994 /*                                                                 */
6995 /* Essentially what's done here is that the pCode flow is          */
6996 /* determined.                                                     */
6997 /*-----------------------------------------------------------------*/
6998
6999 void pic16_AnalyzepCode(char dbName)
7000 {
7001   pBlock *pb;
7002   int i,changes;
7003
7004   if(!the_pFile)
7005     return;
7006
7007   mergepBlocks('D');
7008
7009
7010   /* Phase 1 - Register allocation and peep hole optimization
7011    *
7012    * The first part of the analysis is to determine the registers
7013    * that are used in the pCode. Once that is done, the peep rules
7014    * are applied to the code. We continue to loop until no more
7015    * peep rule optimizations are found (or until we exceed the
7016    * MAX_PASSES threshold). 
7017    *
7018    * When done, the required registers will be determined.
7019    *
7020    */
7021   i = 0;
7022   do {
7023
7024     DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7025     //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7026
7027     /* First, merge the labels with the instructions */
7028     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7029       if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7030
7031         DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7032         //fprintf(stderr," analyze and merging block %c\n",dbName);
7033         pic16_pBlockMergeLabels(pb);
7034         AnalyzepBlock(pb);
7035       } else {
7036         DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7037       }
7038     }
7039
7040         if(!options.nopeep)
7041                 changes = OptimizepCode(dbName);
7042         else changes = 0;
7043
7044   } while(changes && (i++ < MAX_PASSES));
7045
7046   buildCallTree();
7047 }
7048
7049 /*-----------------------------------------------------------------*/
7050 /* ispCodeFunction - returns true if *pc is the pCode of a         */
7051 /*                   function                                      */
7052 /*-----------------------------------------------------------------*/
7053 static bool ispCodeFunction(pCode *pc)
7054 {
7055
7056   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
7057     return 1;
7058
7059   return 0;
7060 }
7061
7062 /*-----------------------------------------------------------------*/
7063 /* findFunction - Search for a function by name (given the name)   */
7064 /*                in the set of all functions that are in a pBlock */
7065 /* (note - I expect this to change because I'm planning to limit   */
7066 /*  pBlock's to just one function declaration                      */
7067 /*-----------------------------------------------------------------*/
7068 static pCode *findFunction(char *fname)
7069 {
7070   pBlock *pb;
7071   pCode *pc;
7072   if(!fname)
7073     return NULL;
7074
7075   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7076
7077     pc = setFirstItem(pb->function_entries);
7078     while(pc) {
7079     
7080       if((pc->type == PC_FUNCTION) &&
7081          (PCF(pc)->fname) && 
7082          (strcmp(fname, PCF(pc)->fname)==0))
7083         return pc;
7084
7085       pc = setNextItem(pb->function_entries);
7086
7087     }
7088
7089   }
7090   return NULL;
7091 }
7092
7093 static void MarkUsedRegisters(set *regset)
7094 {
7095
7096   regs *r1,*r2;
7097
7098   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
7099 //      fprintf(stderr, "marking register = %s\t", r1->name);
7100     r2 = pic16_regWithIdx(r1->rIdx);
7101 //      fprintf(stderr, "to register = %s\n", r2->name);
7102     r2->isFree = 0;
7103     r2->wasUsed = 1;
7104   }
7105 }
7106
7107 static void pBlockStats(FILE *of, pBlock *pb)
7108 {
7109
7110   pCode *pc;
7111   regs  *r;
7112
7113         if(!pic16_pcode_verbose)return;
7114         
7115   fprintf(of,";***\n;  pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
7116
7117   // for now just print the first element of each set
7118   pc = setFirstItem(pb->function_entries);
7119   if(pc) {
7120     fprintf(of,";entry:  ");
7121     pc->print(of,pc);
7122   }
7123   pc = setFirstItem(pb->function_exits);
7124   if(pc) {
7125     fprintf(of,";has an exit\n");
7126     //pc->print(of,pc);
7127   }
7128
7129   pc = setFirstItem(pb->function_calls);
7130   if(pc) {
7131     fprintf(of,";functions called:\n");
7132
7133     while(pc) {
7134       if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7135         fprintf(of,";   %s\n",pic16_get_op_from_instruction(PCI(pc)));
7136       }
7137       pc = setNextItem(pb->function_calls);
7138     }
7139   }
7140
7141   r = setFirstItem(pb->tregisters);
7142   if(r) {
7143     int n = elementsInSet(pb->tregisters);
7144
7145     fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
7146
7147     while (r) {
7148       fprintf(of,";   %s\n",r->name);
7149       r = setNextItem(pb->tregisters);
7150     }
7151   }
7152   
7153   fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
7154 }
7155
7156 /*-----------------------------------------------------------------*/
7157 /*-----------------------------------------------------------------*/
7158 #if 0
7159 static void sequencepCode(void)
7160 {
7161   pBlock *pb;
7162   pCode *pc;
7163
7164
7165   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7166
7167     pb->seq = GpCodeSequenceNumber+1;
7168
7169     for( pc = pb->pcHead; pc; pc = pc->next)
7170       pc->seq = ++GpCodeSequenceNumber;
7171   }
7172
7173 }
7174 #endif
7175
7176 /*-----------------------------------------------------------------*/
7177 /*-----------------------------------------------------------------*/
7178 static set *register_usage(pBlock *pb)
7179 {
7180   pCode *pc,*pcn;
7181   set *registers=NULL;
7182   set *registersInCallPath = NULL;
7183
7184   /* check recursion */
7185
7186   pc = setFirstItem(pb->function_entries);
7187
7188   if(!pc)
7189     return registers;
7190
7191   pb->visited = 1;
7192
7193   if(pc->type != PC_FUNCTION)
7194     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
7195
7196   pc = setFirstItem(pb->function_calls);
7197   for( ; pc; pc = setNextItem(pb->function_calls)) {
7198
7199     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7200       char *dest = pic16_get_op_from_instruction(PCI(pc));
7201
7202       pcn = findFunction(dest);
7203       if(pcn) 
7204         registersInCallPath = register_usage(pcn->pb);
7205     } else
7206       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7207
7208   }
7209
7210 #ifdef PCODE_DEBUG
7211   pBlockStats(stderr,pb);  // debug
7212 #endif
7213
7214   // Mark the registers in this block as used.
7215
7216   MarkUsedRegisters(pb->tregisters);
7217   if(registersInCallPath) {
7218     /* registers were used in the functions this pBlock has called */
7219     /* so now, we need to see if these collide with the ones we are */
7220     /* using here */
7221
7222     regs *r1,*r2, *newreg;
7223
7224     DFPRINTF((stderr,"comparing registers\n"));
7225
7226     r1 = setFirstItem(registersInCallPath);
7227     while(r1) {
7228
7229       r2 = setFirstItem(pb->tregisters);
7230
7231       while(r2 && (r1->type != REG_STK)) {
7232
7233         if(r2->rIdx == r1->rIdx) {
7234           newreg = pic16_findFreeReg(REG_GPR);
7235
7236
7237           if(!newreg) {
7238             DFPRINTF((stderr,"Bummer, no more registers.\n"));
7239             exit(1);
7240           }
7241
7242           DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
7243                   r1->rIdx, newreg->rIdx));
7244           r2->rIdx = newreg->rIdx;
7245           //if(r2->name) free(r2->name);
7246           if(newreg->name)
7247             r2->name = Safe_strdup(newreg->name);
7248           else
7249             r2->name = NULL;
7250           newreg->isFree = 0;
7251           newreg->wasUsed = 1;
7252         }
7253         r2 = setNextItem(pb->tregisters);
7254       }
7255
7256       r1 = setNextItem(registersInCallPath);
7257     }
7258
7259     /* Collisions have been resolved. Now free the registers in the call path */
7260     r1 = setFirstItem(registersInCallPath);
7261     while(r1) {
7262       if(r1->type != REG_STK) {
7263         newreg = pic16_regWithIdx(r1->rIdx);
7264         newreg->isFree = 1;
7265       }
7266       r1 = setNextItem(registersInCallPath);
7267     }
7268
7269   }// else
7270   //    MarkUsedRegisters(pb->registers);
7271
7272   registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
7273 #ifdef PCODE_DEBUG
7274   if(registers) 
7275     DFPRINTF((stderr,"returning regs\n"));
7276   else
7277     DFPRINTF((stderr,"not returning regs\n"));
7278
7279   DFPRINTF((stderr,"pBlock after register optim.\n"));
7280   pBlockStats(stderr,pb);  // debug
7281 #endif
7282
7283   return registers;
7284 }
7285
7286 /*-----------------------------------------------------------------*/
7287 /* pct2 - writes the call tree to a file                           */
7288 /*                                                                 */
7289 /*-----------------------------------------------------------------*/
7290 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
7291 {
7292   pCode *pc,*pcn;
7293   int i;
7294   //  set *registersInCallPath = NULL;
7295
7296   if(!of)
7297     return;
7298
7299   if(indent > 10) {
7300         fprintf(of, "recursive function\n");
7301     return; //recursion ?
7302   }
7303
7304   pc = setFirstItem(pb->function_entries);
7305
7306   if(!pc)
7307     return;
7308
7309   pb->visited = 0;
7310
7311   for(i=0;i<indent;i++)   // Indentation
7312         fputs("+   ", of);
7313   fputs("+- ", of);
7314
7315   if(pc->type == PC_FUNCTION) {
7316     usedstack += PCF(pc)->stackusage;
7317     fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
7318   } else return;  // ???
7319
7320
7321   pc = setFirstItem(pb->function_calls);
7322   for( ; pc; pc = setNextItem(pb->function_calls)) {
7323
7324     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
7325       char *dest = pic16_get_op_from_instruction(PCI(pc));
7326
7327       pcn = findFunction(dest);
7328       if(pcn) 
7329         pct2(of,pcn->pb,indent+1, usedstack);   // + PCF(pcn)->stackusage);
7330     } else
7331       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7332
7333   }
7334
7335
7336 }
7337
7338
7339 /*-----------------------------------------------------------------*/
7340 /* pic16_printCallTree - writes the call tree to a file                  */
7341 /*                                                                 */
7342 /*-----------------------------------------------------------------*/
7343
7344 void pic16_printCallTree(FILE *of)
7345 {
7346   pBranch *pbr;
7347   pBlock  *pb;
7348   pCode   *pc;
7349
7350   if(!the_pFile)
7351     return;
7352
7353   if(!of)
7354     of = stderr;
7355
7356   fprintf(of, "\npBlock statistics\n");
7357   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
7358     pBlockStats(of,pb);
7359
7360
7361   fprintf(of,"Call Tree\n");
7362   pbr = the_pFile->functions;
7363   while(pbr) {
7364     if(pbr->pc) {
7365       pc = pbr->pc;
7366       if(!ispCodeFunction(pc))
7367         fprintf(of,"bug in call tree");
7368
7369
7370       fprintf(of,"Function: %s\n", PCF(pc)->fname);
7371
7372       while(pc->next && !ispCodeFunction(pc->next)) {
7373         pc = pc->next;
7374         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
7375           fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
7376       }
7377     }
7378
7379     pbr = pbr->next;
7380   }
7381
7382
7383   fprintf(of,"\n**************\n\na better call tree\n");
7384   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7385 //    if(pb->visited)
7386       pct2(of,pb,0,0);
7387   }
7388
7389   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7390     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
7391   }
7392 }
7393
7394
7395
7396 /*-----------------------------------------------------------------*/
7397 /*                                                                 */
7398 /*-----------------------------------------------------------------*/
7399
7400 static void InlineFunction(pBlock *pb)
7401 {
7402   pCode *pc;
7403   pCode *pc_call;
7404
7405   if(!pb)
7406     return;
7407
7408   pc = setFirstItem(pb->function_calls);
7409
7410   for( ; pc; pc = setNextItem(pb->function_calls)) {
7411
7412     if(isCALL(pc)) {
7413       pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7414       pCode *pct;
7415       pCode *pce;
7416
7417       pBranch *pbr;
7418
7419       if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) {               /* change 0 to 1 to enable inlining */
7420         
7421         //fprintf(stderr,"Cool can inline:\n");
7422         //pcn->print(stderr,pcn);
7423
7424         //fprintf(stderr,"recursive call Inline\n");
7425         InlineFunction(pcn->pb);
7426         //fprintf(stderr,"return from recursive call Inline\n");
7427
7428         /*
7429           At this point, *pc points to a CALL mnemonic, and
7430           *pcn points to the function that is being called.
7431
7432           To in-line this call, we need to remove the CALL
7433           and RETURN(s), and link the function pCode in with
7434           the CALLee pCode.
7435
7436         */
7437
7438
7439         /* Remove the CALL */
7440         pc_call = pc;
7441         pc = pc->prev;
7442
7443         /* remove callee pBlock from the pBlock linked list */
7444         removepBlock(pcn->pb);
7445
7446         pce = pcn;
7447         while(pce) {
7448           pce->pb = pb;
7449           pce = pce->next;
7450         }
7451
7452         /* Remove the Function pCode */
7453         pct = pic16_findNextInstruction(pcn->next);
7454
7455         /* Link the function with the callee */
7456         pc->next = pcn->next;
7457         pcn->next->prev = pc;
7458         
7459         /* Convert the function name into a label */
7460
7461         pbr = Safe_calloc(1,sizeof(pBranch));
7462         pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
7463         pbr->next = NULL;
7464         PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
7465         PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
7466
7467         /* turn all of the return's except the last into goto's */
7468         /* check case for 2 instruction pBlocks */
7469         pce = pic16_findNextInstruction(pcn->next);
7470         while(pce) {
7471           pCode *pce_next = pic16_findNextInstruction(pce->next);
7472
7473           if(pce_next == NULL) {
7474             /* found the last return */
7475             pCode *pc_call_next =  pic16_findNextInstruction(pc_call->next);
7476
7477             //fprintf(stderr,"found last return\n");
7478             //pce->print(stderr,pce);
7479             pce->prev->next = pc_call->next;
7480             pc_call->next->prev = pce->prev;
7481             PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
7482                                                       PCI(pce)->label);
7483           }
7484
7485           pce = pce_next;
7486         }
7487
7488
7489       }
7490     } else
7491       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7492
7493   }
7494
7495 }
7496
7497 /*-----------------------------------------------------------------*/
7498 /*                                                                 */
7499 /*-----------------------------------------------------------------*/
7500
7501 void pic16_InlinepCode(void)
7502 {
7503
7504   pBlock  *pb;
7505   pCode   *pc;
7506
7507   if(!the_pFile)
7508     return;
7509
7510   if(!functionInlining)
7511     return;
7512
7513   /* Loop through all of the function definitions and count the
7514    * number of times each one is called */
7515   //fprintf(stderr,"inlining %d\n",__LINE__);
7516
7517   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7518
7519     pc = setFirstItem(pb->function_calls);
7520
7521     for( ; pc; pc = setNextItem(pb->function_calls)) {
7522
7523       if(isCALL(pc)) {
7524         pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
7525         if(pcn && isPCF(pcn)) {
7526           PCF(pcn)->ncalled++;
7527         }
7528       } else
7529         fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
7530
7531     }
7532   }
7533
7534   //fprintf(stderr,"inlining %d\n",__LINE__);
7535
7536   /* Now, Loop through the function definitions again, but this
7537    * time inline those functions that have only been called once. */
7538   
7539   InlineFunction(the_pFile->pbHead);
7540   //fprintf(stderr,"inlining %d\n",__LINE__);
7541
7542   for(pb = the_pFile->pbHead; pb; pb = pb->next)
7543     unBuildFlow(pb);
7544
7545 }
7546
7547 char *pic_optype_names[]={
7548         "PO_NONE",         // No operand e.g. NOP
7549         "PO_W",              // The working register (as a destination)
7550         "PO_WREG",           // The working register (as a file register)
7551         "PO_STATUS",         // The 'STATUS' register
7552         "PO_BSR",            // The 'BSR' register
7553         "PO_FSR0",           // The "file select register" (in PIC18 family it's one 
7554                              // of three)
7555         "PO_INDF0",          // The Indirect register
7556         "PO_INTCON",         // Interrupt Control register
7557         "PO_GPR_REGISTER",   // A general purpose register
7558         "PO_GPR_BIT",        // A bit of a general purpose register
7559         "PO_GPR_TEMP",       // A general purpose temporary register
7560         "PO_SFR_REGISTER",   // A special function register (e.g. PORTA)
7561         "PO_PCL",            // Program counter Low register
7562         "PO_PCLATH",         // Program counter Latch high register
7563         "PO_PCLATU",         // Program counter Latch upper register
7564         "PO_PRODL",          // Product Register Low
7565         "PO_PRODH",          // Product Register High
7566         "PO_LITERAL",        // A constant
7567         "PO_REL_ADDR",       // A relative address
7568         "PO_IMMEDIATE",      //  (8051 legacy)
7569         "PO_DIR",            // Direct memory (8051 legacy)
7570         "PO_CRY",            // bit memory (8051 legacy)
7571         "PO_BIT",            // bit operand.
7572         "PO_STR",            //  (8051 legacy)
7573         "PO_LABEL",
7574         "PO_WILD"            // Wild card operand in peep optimizer
7575 };
7576
7577
7578 char *dumpPicOptype(PIC_OPTYPE type)
7579 {
7580         return (pic_optype_names[ type ]);
7581 }