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