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