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