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