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