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