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