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