* src/pic16/pcode.c (assignToSameBank) : fixed cast to pointer of
[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 //  Safe_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 //    Safe_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 //  Safe_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                                                 if(ab->address != -1)
4606                                                   fprintf(of, "\t0X%06X", ab->address);
4607                                                 break;
4608                                         }
4609                                 }
4610                         }
4611                         fprintf(of, "\n");
4612                 }
4613                 printpCode(of,pc);
4614         }
4615 }
4616
4617 /*-----------------------------------------------------------------*/
4618 /*                                                                 */
4619 /*       pCode processing                                          */
4620 /*                                                                 */
4621 /*                                                                 */
4622 /*                                                                 */
4623 /*-----------------------------------------------------------------*/
4624
4625 void pic16_unlinkpCode(pCode *pc)
4626 {
4627
4628
4629   if(pc) {
4630 #ifdef PCODE_DEBUG
4631     fprintf(stderr,"Unlinking: ");
4632     printpCode(stderr, pc);
4633 #endif
4634     if(pc->prev) 
4635       pc->prev->next = pc->next;
4636     if(pc->next)
4637       pc->next->prev = pc->prev;
4638
4639     pc->prev = pc->next = NULL;
4640   }
4641 }
4642
4643 /*-----------------------------------------------------------------*/
4644 /*-----------------------------------------------------------------*/
4645
4646 static void genericDestruct(pCode *pc)
4647 {
4648
4649   pic16_unlinkpCode(pc);
4650
4651   if(isPCI(pc)) {
4652     /* For instructions, tell the register (if there's one used)
4653      * that it's no longer needed */
4654     regs *reg = pic16_getRegFromInstruction(pc);
4655     if(reg)
4656       deleteSetItem (&(reg->reglives.usedpCodes),pc);
4657
4658         if(PCI(pc)->is2MemOp) {
4659                 reg = pic16_getRegFromInstruction2(pc);
4660                 if(reg)
4661                         deleteSetItem(&(reg->reglives.usedpCodes), pc);
4662         }
4663   }
4664
4665   /* Instead of deleting the memory used by this pCode, mark
4666    * the object as bad so that if there's a pointer to this pCode
4667    * dangling around somewhere then (hopefully) when the type is
4668    * checked we'll catch it.
4669    */
4670
4671   pc->type = PC_BAD;
4672   pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4673
4674   //Safe_free(pc);
4675 }
4676
4677
4678 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4679 /*-----------------------------------------------------------------*/
4680 /*-----------------------------------------------------------------*/
4681 /* modifiers for constant immediate */
4682 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4683
4684 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4685 {
4686   regs *r;
4687   static char b[128];
4688   char *s;
4689   int use_buffer = 1;    // copy the string to the passed buffer pointer
4690
4691         if(!buffer) {
4692                 buffer = b;
4693                 size = sizeof(b);
4694                 use_buffer = 0;     // Don't bother copying the string to the buffer.
4695         } 
4696
4697         if(pcop) {
4698                 switch(pcop->type) {
4699                         case PO_W:
4700                         case PO_WREG:
4701                         case PO_PRODL:
4702                         case PO_PRODH:
4703                         case PO_INDF0:
4704                         case PO_FSR0:
4705                                 if(use_buffer) {
4706                                         SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4707                                         return buffer;
4708                                 }
4709                                 return PCOR(pcop)->r->name;
4710                                 break;
4711                         case PO_GPR_TEMP:
4712                                 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4713                                 if(use_buffer) {
4714                                         SAFE_snprintf(&buffer,&size,"%s",r->name);
4715                                         return buffer;
4716                                 }
4717                                 return r->name;
4718
4719                         case PO_IMMEDIATE:
4720                                 s = buffer;
4721                                 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4722                                         if(PCOI(pcop)->index) {
4723                                                 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4724                                                         immdmod[ PCOI(pcop)->offset ],
4725                                                         pcop->name,
4726                                                         PCOI(pcop)->index);
4727                                         } else {
4728                                                 SAFE_snprintf(&s,&size,"%s(%s)",
4729                                                         immdmod[ PCOI(pcop)->offset ],
4730                                                         pcop->name);
4731                                         }
4732                                 } else {
4733                                         if(PCOI(pcop)->index) {
4734                                                 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4735                                                         immdmod[ 0 ],
4736                                                         pcop->name,
4737                                                         PCOI(pcop)->index);
4738                                         } else {
4739                                                 SAFE_snprintf(&s,&size, "%s(%s)",
4740                                                         immdmod[ 0 ],
4741                                                         pcop->name);
4742                                         }
4743                                 }
4744                                 return buffer;
4745
4746                         case PO_GPR_REGISTER:
4747                         case PO_DIR:
4748                                 s = buffer;
4749 //                              size = sizeof(buffer);
4750                                 if( PCOR(pcop)->instance) {
4751                                         SAFE_snprintf(&s,&size,"(%s + %d)",
4752                                                 pcop->name,
4753                                                 PCOR(pcop)->instance );
4754                                 } else {
4755                                         SAFE_snprintf(&s,&size,"%s",pcop->name);
4756                                 }
4757                                 return buffer;
4758                         case PO_GPR_BIT:
4759                                 s = buffer;
4760                                 if(PCORB(pcop)->subtype == PO_GPR_TEMP) {
4761                                         SAFE_snprintf(&s, &size, "%s", pcop->name);
4762                                 } else {
4763                                         if(PCORB(pcop)->pcor.instance)
4764                                                 SAFE_snprintf(&s, &size, "(%s + %d)", pcop->name, PCORB(pcop)->pcor.instance);
4765                                         else
4766                                                 SAFE_snprintf(&s, &size, "%s", pcop->name);
4767                                 }
4768
4769                                 return (buffer);
4770                         default:
4771                                 if(pcop->name) {
4772                                         if(use_buffer) {
4773                                                 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4774                                                 return buffer;
4775                                         }
4776                                 return pcop->name;
4777                                 }
4778
4779                 }
4780         }
4781
4782   return "NO operand1";
4783 }
4784
4785 /*-----------------------------------------------------------------*/
4786 /* pic16_get_op2 - variant to support two memory operand commands  */
4787 /*-----------------------------------------------------------------*/
4788 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4789 {
4790   regs *r;
4791   static char b[50];
4792   char *s;
4793   int use_buffer = 1;    // copy the string to the passed buffer pointer
4794
4795         if(!buffer) {
4796                 buffer = b;
4797                 size = sizeof(b);
4798                 use_buffer = 0;     // Don't bother copying the string to the buffer.
4799         } 
4800
4801 #if 0
4802         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",
4803                 __FUNCTION__, __LINE__, PCOR(PCOR2(pcop)->pcop2)->r->name, PCOR2(pcop)->pcop2->type,
4804                 PO_DIR, PO_GPR_TEMP, PO_IMMEDIATE, PO_INDF0, PO_FSR0);
4805 #endif
4806
4807         if(pcop) {
4808                 switch(PCOR2(pcop)->pcop2->type) {
4809                         case PO_W:
4810                         case PO_WREG:
4811                         case PO_PRODL:
4812                         case PO_PRODH:
4813                         case PO_INDF0:
4814                         case PO_FSR0:
4815                                 if(use_buffer) {
4816                                         SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4817                                         return buffer;
4818                                 }
4819                                 return PCOR(PCOR2(pcop)->pcop2)->r->name;
4820                                 break;
4821                         case PO_GPR_TEMP:
4822                                 r = pic16_regWithIdx(PCOR(PCOR2(pcop)->pcop2)->r->rIdx);
4823
4824                                 if(use_buffer) {
4825                                         SAFE_snprintf(&buffer,&size,"%s",r->name);
4826                                         return buffer;
4827                                 }
4828                                 return r->name;
4829
4830                         case PO_IMMEDIATE:
4831                                         assert( 0 );
4832                                 break;
4833 #if 0
4834                                 s = buffer;
4835
4836                                 if(PCOI(pcop)->_const) {
4837                                         if( PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4838                                                 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
4839                                                         pcop->name,
4840                                                         PCOI(pcop)->index,
4841                                                         8 * PCOI(pcop)->offset );
4842                                         } else
4843                                                 SAFE_snprintf(&s,&size,"LOW(%s+%d)",pcop->name,PCOI(pcop)->index);
4844                                 } else {
4845                                         if( PCOI(pcop)->index) {
4846                                                 SAFE_snprintf(&s,&size,"(%s + %d)",
4847                                                         pcop->name,
4848                                                         PCOI(pcop)->index );
4849                                         } else {
4850                                                 if(PCOI(pcop)->offset)
4851                                                         SAFE_snprintf(&s,&size,"(%s >> %d)&0xff",pcop->name, 8*PCOI(pcop)->offset);
4852                                                 else
4853                                                         SAFE_snprintf(&s,&size,"%s",pcop->name);
4854                                         }
4855                                 }
4856                                 return buffer;
4857 #endif
4858                         case PO_DIR:
4859                                 s = buffer;
4860                                 if( PCOR(PCOR2(pcop)->pcop2)->instance) {
4861                                         SAFE_snprintf(&s,&size,"(%s + %d)",
4862                                                 PCOR(PCOR2(pcop)->pcop2)->r->name,
4863                                                 PCOR(PCOR2(pcop)->pcop2)->instance );
4864                                 } else {
4865                                         SAFE_snprintf(&s,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4866                                 }
4867                                 return buffer;
4868
4869                         default:
4870                                 if(PCOR(PCOR2(pcop)->pcop2)->r->name) {
4871                                         if(use_buffer) {
4872                                                 SAFE_snprintf(&buffer,&size,"%s",PCOR(PCOR2(pcop)->pcop2)->r->name);
4873                                                 return buffer;
4874                                         }
4875                                         return PCOR(PCOR2(pcop)->pcop2)->r->name;
4876                                 }
4877                 }
4878         }
4879
4880   return "NO operand2";
4881 }
4882
4883 /*-----------------------------------------------------------------*/
4884 /*-----------------------------------------------------------------*/
4885 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4886 {
4887
4888   if(pcc )
4889     return pic16_get_op(pcc->pcop,NULL,0);
4890
4891   /* gcc 3.2:  warning: concatenation of string literals with __FUNCTION__ is deprecated 
4892    *   return ("ERROR Null: "__FUNCTION__);
4893    */
4894   return ("ERROR Null: pic16_get_op_from_instruction");
4895
4896 }
4897
4898 /*-----------------------------------------------------------------*/
4899 /*-----------------------------------------------------------------*/
4900 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4901 {
4902
4903   fprintf(of,"pcodeopprint- not implemented\n");
4904 }
4905
4906 /*-----------------------------------------------------------------*/
4907 /* pic16_pCode2str - convert a pCode instruction to string               */
4908 /*-----------------------------------------------------------------*/
4909 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4910 {
4911   char *s = str;
4912   regs *r;
4913
4914 #if 0
4915         if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4916                 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4917                         __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4918 //              exit(-1);
4919         }
4920 #endif
4921
4922   switch(pc->type) {
4923
4924   case PC_OPCODE:
4925     SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4926
4927     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4928
4929         if(PCI(pc)->is2MemOp) {
4930                 SAFE_snprintf(&s,&size, "%s, %s", 
4931                 pic16_get_op(PCOP(PCI(pc)->pcop), NULL, 0),
4932                 pic16_get_op2(PCOP(PCI(pc)->pcop), NULL, 0));
4933                 break;
4934         }
4935
4936         if(PCI(pc)->is2LitOp) {
4937                 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4938                 break;
4939         }
4940
4941       if(PCI(pc)->isBitInst) {
4942         if(PCI(pc)->pcop->type != PO_GPR_BIT) {
4943           if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4944             SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
4945                           PCI(pc)->pcop->name ,
4946                           PCI(pc)->pcop->name );
4947           else
4948             SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4949 //                        (((pCodeOpRegBit *)(PCI(pc)->pcop))->pcor.instance),
4950                           (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4951                           
4952         } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4953           SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4954         }else
4955           SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
4956         //PCI(pc)->pcop->t.bit );
4957       } else {
4958
4959         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4960           if( PCI(pc)->num_ops == 3)
4961             SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
4962           else
4963             SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
4964
4965         }else {
4966           SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
4967
4968                 if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
4969                         if(PCI(pc)->num_ops == 3)
4970                                 SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
4971
4972                         r = pic16_getRegFromInstruction(pc);
4973 //                      fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
4974 //                                      __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?r->accessBank:-1);
4975
4976                         if(r && !r->accessBank)SAFE_snprintf(&s,&size,", %s", (!pic16_mplab_comp?"B":"BANKED"));
4977           }
4978         }
4979       }
4980
4981     }
4982     break;
4983
4984   case PC_COMMENT:
4985     /* assuming that comment ends with a \n */
4986     SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
4987     break;
4988
4989   case PC_INFO:
4990     SAFE_snprintf(&s,&size,"; info ==>");
4991     switch(((pCodeInfo *)pc)->type) {
4992       case INF_OPTIMIZATION:
4993           SAFE_snprintf(&s,&size, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
4994           break;
4995       case INF_LOCALREGS:
4996           SAFE_snprintf(&s,&size, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
4997           break;
4998     }; break;
4999
5000   case PC_INLINE:
5001     /* assuming that inline code ends with a \n */
5002     SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
5003     break;
5004
5005   case PC_LABEL:
5006     SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
5007     break;
5008   case PC_FUNCTION:
5009     SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
5010     break;
5011   case PC_WILD:
5012     SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
5013     break;
5014   case PC_FLOW:
5015     SAFE_snprintf(&s,&size,";\t--FLOW change\n");
5016     break;
5017   case PC_CSOURCE:
5018 //    SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
5019       SAFE_snprintf(&s,&size,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
5020         PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
5021     break;
5022   case PC_ASMDIR:
5023         if(PCAD(pc)->directive) {
5024                 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
5025         } else
5026         if(PCAD(pc)->arg) {
5027                 /* special case to handle inline labels without a tab */
5028                 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
5029         }
5030         break;
5031
5032   case PC_BAD:
5033     SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
5034     break;
5035   }
5036
5037   return str;
5038
5039 }
5040
5041 /*-----------------------------------------------------------------*/
5042 /* genericPrint - the contents of a pCode to a file                */
5043 /*-----------------------------------------------------------------*/
5044 static void genericPrint(FILE *of, pCode *pc)
5045 {
5046
5047   if(!pc || !of)
5048     return;
5049
5050   switch(pc->type) {
5051   case PC_COMMENT:
5052 //    fputs(((pCodeComment *)pc)->comment, of);
5053     fprintf(of,"; %s\n", ((pCodeComment *)pc)->comment);
5054     break;
5055
5056   case PC_INFO:
5057     {
5058       pBranch *pbl = PCI(pc)->label;
5059       while(pbl && pbl->pc) {
5060         if(pbl->pc->type == PC_LABEL)
5061           pCodePrintLabel(of, pbl->pc);
5062         pbl = pbl->next;
5063       }
5064     }
5065           
5066     if(pic16_pcode_verbose) {
5067       fprintf(of, "; info ==>");
5068       switch(((pCodeInfo *)pc)->type) {
5069         case INF_OPTIMIZATION:
5070               fprintf(of, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
5071               break;
5072         case INF_LOCALREGS:
5073               fprintf(of, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
5074               break;
5075         }
5076     };
5077     
5078     break;
5079
5080   case PC_INLINE:
5081     fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
5082      break;
5083
5084   case PC_OPCODE:
5085     // If the opcode has a label, print that first
5086     {
5087       pBranch *pbl = PCI(pc)->label;
5088       while(pbl && pbl->pc) {
5089         if(pbl->pc->type == PC_LABEL)
5090           pCodePrintLabel(of, pbl->pc);
5091         pbl = pbl->next;
5092       }
5093     }
5094
5095     if(PCI(pc)->cline) 
5096       genericPrint(of,PCODE(PCI(pc)->cline));
5097
5098     {
5099       char str[256];
5100       
5101       pic16_pCode2str(str, 256, pc);
5102
5103       fprintf(of,"%s",str);
5104       /* Debug */
5105       if(pic16_debug_verbose) {
5106         fprintf(of, "\t;key=%03x",pc->seq);
5107         if(PCI(pc)->pcflow)
5108           fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
5109       }
5110     }
5111     fprintf(of, "\n");
5112     break;
5113       
5114   case PC_WILD:
5115     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
5116     if(PCW(pc)->pci.label)
5117       pCodePrintLabel(of, PCW(pc)->pci.label->pc);
5118
5119     if(PCW(pc)->operand) {
5120       fprintf(of,";\toperand  ");
5121       pCodeOpPrint(of,PCW(pc)->operand );
5122     }
5123     break;
5124
5125   case PC_FLOW:
5126     if(pic16_debug_verbose) {
5127       fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
5128       if(PCFL(pc)->ancestor)
5129         fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
5130       fprintf(of,"\n");
5131
5132     }
5133     break;
5134
5135   case PC_CSOURCE:
5136 //    fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
5137     fprintf(of,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
5138         PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
5139          
5140     break;
5141
5142   case PC_ASMDIR:
5143         {
5144           pBranch *pbl = PCAD(pc)->pci.label;
5145                 while(pbl && pbl->pc) {
5146                         if(pbl->pc->type == PC_LABEL)
5147                                 pCodePrintLabel(of, pbl->pc);
5148                         pbl = pbl->next;
5149                 }
5150         }
5151         if(PCAD(pc)->directive) {
5152                 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
5153         } else
5154         if(PCAD(pc)->arg) {
5155                 /* special case to handle inline labels without tab */
5156                 fprintf(of, "%s\n", PCAD(pc)->arg);
5157         }
5158         break;
5159         
5160   case PC_LABEL:
5161   default:
5162     fprintf(of,"unknown pCode type %d\n",pc->type);
5163   }
5164
5165 }
5166
5167 /*-----------------------------------------------------------------*/
5168 /* pCodePrintFunction - prints function begin/end                  */
5169 /*-----------------------------------------------------------------*/
5170
5171 static void pCodePrintFunction(FILE *of, pCode *pc)
5172 {
5173
5174   if(!pc || !of)
5175     return;
5176
5177 #if 0
5178   if( ((pCodeFunction *)pc)->modname) 
5179     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
5180 #endif
5181
5182   if(!PCF(pc)->absblock) {
5183       if(PCF(pc)->fname) {
5184       pBranch *exits = PCF(pc)->to;
5185       int i=0;
5186
5187       fprintf(of,"%s:", PCF(pc)->fname);
5188     
5189       if(pic16_pcode_verbose)
5190         fprintf(of, "\t;Function start");
5191     
5192       fprintf(of, "\n");
5193     
5194       while(exits) {
5195         i++;
5196         exits = exits->next;
5197       }
5198       //if(i) i--;
5199
5200       if(pic16_pcode_verbose)
5201         fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
5202     
5203     } else {
5204         if((PCF(pc)->from && 
5205                 PCF(pc)->from->pc->type == PC_FUNCTION &&
5206                 PCF(PCF(pc)->from->pc)->fname) ) {
5207
5208                 if(pic16_pcode_verbose)
5209                         fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
5210         } else {
5211                 if(pic16_pcode_verbose)
5212                         fprintf(of,"; exit point [can't find entry point]\n");
5213         }
5214         fprintf(of, "\n");
5215     }
5216   }
5217 }
5218 /*-----------------------------------------------------------------*/
5219 /* pCodePrintLabel - prints label                                  */
5220 /*-----------------------------------------------------------------*/
5221
5222 static void pCodePrintLabel(FILE *of, pCode *pc)
5223 {
5224
5225   if(!pc || !of)
5226     return;
5227
5228   if(PCL(pc)->label) 
5229     fprintf(of,"%s:\n",PCL(pc)->label);
5230   else if (PCL(pc)->key >=0) 
5231     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
5232   else
5233     fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
5234
5235 }
5236 /*-----------------------------------------------------------------*/
5237 /* unlinkpCodeFromBranch - Search for a label in a pBranch and     */
5238 /*                         remove it if it is found.               */
5239 /*-----------------------------------------------------------------*/
5240 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
5241 {
5242   pBranch *b, *bprev;
5243
5244
5245   bprev = NULL;
5246
5247   if(pcl->type == PC_OPCODE)
5248     b = PCI(pcl)->label;
5249   else {
5250     fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
5251     exit(1);
5252
5253   }
5254
5255   //fprintf (stderr, "%s \n",__FUNCTION__);
5256   //pcl->print(stderr,pcl);
5257   //pc->print(stderr,pc);
5258   while(b) {
5259     if(b->pc == pc) {
5260       //fprintf (stderr, "found label\n");
5261       //pc->print(stderr, pc);
5262
5263       /* Found a label */
5264       if(bprev) {
5265         bprev->next = b->next;  /* Not first pCode in chain */
5266 //      Safe_free(b);
5267       } else {
5268         pc->destruct(pc);
5269         PCI(pcl)->label = b->next;   /* First pCode in chain */
5270 //      Safe_free(b);
5271       }
5272       return;  /* A label can't occur more than once */
5273     }
5274     bprev = b;
5275     b = b->next;
5276   }
5277
5278 }
5279
5280 /*-----------------------------------------------------------------*/
5281 /*-----------------------------------------------------------------*/
5282 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5283 {
5284   pBranch *b;
5285
5286   if(!h)
5287     return n;
5288
5289   if(h == n)
5290     return n;
5291
5292   b = h;
5293   while(b->next)
5294     b = b->next;
5295
5296   b->next = n;
5297
5298   return h;
5299   
5300 }  
5301 /*-----------------------------------------------------------------*/
5302 /* pBranchLink - given two pcodes, this function will link them    */
5303 /*               together through their pBranches                  */
5304 /*-----------------------------------------------------------------*/
5305 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5306 {
5307   pBranch *b;
5308
5309   // Declare a new branch object for the 'from' pCode.
5310
5311   //_ALLOC(b,sizeof(pBranch));
5312   b = Safe_calloc(1,sizeof(pBranch));
5313   b->pc = PCODE(t);             // The link to the 'to' pCode.
5314   b->next = NULL;
5315
5316   f->to = pic16_pBranchAppend(f->to,b);
5317
5318   // Now do the same for the 'to' pCode.
5319
5320   //_ALLOC(b,sizeof(pBranch));
5321   b = Safe_calloc(1,sizeof(pBranch));
5322   b->pc = PCODE(f);
5323   b->next = NULL;
5324
5325   t->from = pic16_pBranchAppend(t->from,b);
5326   
5327 }
5328
5329 #if 0
5330 /*-----------------------------------------------------------------*/
5331 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5332 /*               a pCode                                           */
5333 /*-----------------------------------------------------------------*/
5334 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5335 {
5336   while(pb) {
5337
5338     if(pb->pc == pc)
5339       return pb;
5340
5341     pb = pb->next;
5342   }
5343
5344   return NULL;
5345 }
5346
5347 /*-----------------------------------------------------------------*/
5348 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain.      */
5349 /*-----------------------------------------------------------------*/
5350 void pic16_pCodeUnlink(pCode *pc)
5351 {
5352   pBranch *pb1,*pb2;
5353   pCode *pc1;
5354
5355   if(!pc->prev || !pc->next) {
5356     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5357     exit(1);
5358   }
5359
5360   /* first remove the pCode from the chain */
5361   pc->prev->next = pc->next;
5362   pc->next->prev = pc->prev;
5363
5364   /* Now for the hard part... */
5365
5366   /* Remove the branches */
5367
5368   pb1 = PCI(pc)->from;
5369   while(pb1) {
5370     PCI(pc1) = pb1->pc;    /* Get the pCode that branches to the
5371                        * one we're unlinking */
5372
5373     /* search for the link back to this pCode (the one we're
5374      * unlinking) */
5375     if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5376       pb2->pc = PCI(pc)->to->pc;  // make the replacement
5377
5378       /* if the pCode we're unlinking contains multiple 'to'
5379        * branches (e.g. this a skip instruction) then we need
5380        * to copy these extra branches to the chain. */
5381       if(PCI(pc)->to->next)
5382         pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5383     }
5384     
5385     pb1 = pb1->next;
5386   }
5387
5388
5389 }
5390 #endif
5391 /*-----------------------------------------------------------------*/
5392 /*-----------------------------------------------------------------*/
5393 #if 0
5394 static void genericAnalyze(pCode *pc)
5395 {
5396   switch(pc->type) {
5397   case PC_WILD:
5398   case PC_COMMENT:
5399     return;
5400   case PC_LABEL:
5401   case PC_FUNCTION:
5402   case PC_OPCODE:
5403     {
5404       // Go through the pCodes that are in pCode chain and link
5405       // them together through the pBranches. Note, the pCodes
5406       // are linked together as a contiguous stream like the 
5407       // assembly source code lines. The linking here mimics this
5408       // except that comments are not linked in.
5409       // 
5410       pCode *npc = pc->next;
5411       while(npc) {
5412         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5413           pBranchLink(pc,npc);
5414           return;
5415         } else
5416           npc = npc->next;
5417       }
5418       /* reached the end of the pcode chain without finding
5419        * an instruction we could link to. */
5420     }
5421     break;
5422   case PC_FLOW:
5423     fprintf(stderr,"analyze PC_FLOW\n");
5424
5425     return;
5426   case PC_BAD:
5427     fprintf(stderr,,";A bad pCode is being used\n");
5428
5429   }
5430 }
5431 #endif
5432
5433 /*-----------------------------------------------------------------*/
5434 /*-----------------------------------------------------------------*/
5435 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5436 {
5437   pBranch *pbr;
5438
5439   if(pc->type == PC_LABEL) {
5440     if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
5441       return TRUE;
5442   }
5443   if((pc->type == PC_OPCODE)
5444         || (pc->type == PC_ASMDIR)
5445         ) {
5446     pbr = PCI(pc)->label;
5447     while(pbr) {
5448       if(pbr->pc->type == PC_LABEL) {
5449         if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
5450           return TRUE;
5451       }
5452       pbr = pbr->next;
5453     }
5454   }
5455
5456   return FALSE;
5457 }
5458
5459 /*-----------------------------------------------------------------*/
5460 /*-----------------------------------------------------------------*/
5461 static int checkLabel(pCode *pc)
5462 {
5463   pBranch *pbr;
5464
5465   if(pc && isPCI(pc)) {
5466     pbr = PCI(pc)->label;
5467     while(pbr) {
5468       if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5469         return TRUE;
5470
5471       pbr = pbr->next;
5472     }
5473   }
5474
5475   return FALSE;
5476 }
5477
5478 /*-----------------------------------------------------------------*/
5479 /* findLabelinpBlock - Search the pCode for a particular label     */
5480 /*-----------------------------------------------------------------*/
5481 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5482 {
5483   pCode  *pc;
5484
5485   if(!pb)
5486     return NULL;
5487
5488   for(pc = pb->pcHead; pc; pc = pc->next) 
5489     if(compareLabel(pc,pcop_label))
5490       return pc;
5491     
5492   return NULL;
5493 }
5494 #if 0
5495 /*-----------------------------------------------------------------*/
5496 /* findLabel - Search the pCode for a particular label             */
5497 /*-----------------------------------------------------------------*/
5498 static pCode * findLabel(pCodeOpLabel *pcop_label)
5499 {
5500   pBlock *pb;
5501   pCode  *pc;
5502
5503   if(!the_pFile)
5504     return NULL;
5505
5506   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5507     if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5508       return pc;
5509   }
5510
5511   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5512   return NULL;
5513 }
5514 #endif
5515 /*-----------------------------------------------------------------*/
5516 /* pic16_findNextpCode - given a pCode, find the next of type 'pct'      */
5517 /*                 in the linked list                              */
5518 /*-----------------------------------------------------------------*/
5519 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5520 {
5521
5522   while(pc) {
5523     if(pc->type == pct)
5524       return pc;
5525
5526     pc = pc->next;
5527   }
5528
5529   return NULL;
5530 }
5531
5532 /*-----------------------------------------------------------------*/
5533 /* findPrevpCode - given a pCode, find the previous of type 'pct'  */
5534 /*                 in the linked list                              */
5535 /*-----------------------------------------------------------------*/
5536 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5537 {
5538
5539   while(pc) {
5540     if(pc->type == pct)
5541       return pc;
5542
5543     pc = pc->prev;
5544   }
5545
5546   return NULL;
5547 }
5548
5549
5550 //#define PCODE_DEBUG
5551 /*-----------------------------------------------------------------*/
5552 /* pic16_findNextInstruction - given a pCode, find the next instruction  */
5553 /*                       in the linked list                        */
5554 /*-----------------------------------------------------------------*/
5555 pCode * pic16_findNextInstruction(pCode *pci)
5556 {
5557   pCode *pc = pci;
5558
5559   while(pc) {
5560     if((pc->type == PC_OPCODE)
5561         || (pc->type == PC_WILD)
5562         || (pc->type == PC_ASMDIR)
5563         )
5564       return pc;
5565
5566 #ifdef PCODE_DEBUG
5567     fprintf(stderr,"pic16_findNextInstruction:  ");
5568     printpCode(stderr, pc);
5569 #endif
5570     pc = pc->next;
5571   }
5572
5573   //fprintf(stderr,"Couldn't find instruction\n");
5574   return NULL;
5575 }
5576
5577 /*-----------------------------------------------------------------*/
5578 /* pic16_findPrevInstruction - given a pCode, find the next instruction  */
5579 /*                       in the linked list                        */
5580 /*-----------------------------------------------------------------*/
5581 pCode * pic16_findPrevInstruction(pCode *pci)
5582 {
5583   pCode *pc = pci;
5584
5585   while(pc) {
5586
5587     if((pc->type == PC_OPCODE)
5588         || (pc->type == PC_WILD)
5589         || (pc->type == PC_ASMDIR)
5590         )
5591       return pc;
5592       
5593
5594 #ifdef PCODE_DEBUG
5595     fprintf(stderr,"pic16_findPrevInstruction:  ");
5596     printpCode(stderr, pc);
5597 #endif
5598     pc = pc->prev;
5599   }
5600
5601   //fprintf(stderr,"Couldn't find instruction\n");
5602   return NULL;
5603 }
5604
5605 #undef PCODE_DEBUG
5606
5607 #if 0
5608 /*-----------------------------------------------------------------*/
5609 /* findFunctionEnd - given a pCode find the end of the function    */
5610 /*                   that contains it                              */
5611 /*-----------------------------------------------------------------*/
5612 static pCode * findFunctionEnd(pCode *pc)
5613 {
5614
5615   while(pc) {
5616     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
5617       return pc;
5618
5619     pc = pc->next;
5620   }
5621
5622   fprintf(stderr,"Couldn't find function end\n");
5623   return NULL;
5624 }
5625 #endif
5626 #if 0
5627 /*-----------------------------------------------------------------*/
5628 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
5629 /*                instruction with which it is associated.         */
5630 /*-----------------------------------------------------------------*/
5631 static void AnalyzeLabel(pCode *pc)
5632 {
5633
5634   pic16_pCodeUnlink(pc);
5635
5636 }
5637 #endif
5638
5639 #if 0
5640 static void AnalyzeGOTO(pCode *pc)
5641 {
5642
5643   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5644
5645 }
5646
5647 static void AnalyzeSKIP(pCode *pc)
5648 {
5649
5650   pBranchLink(pc,pic16_findNextInstruction(pc->next));
5651   pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5652
5653 }
5654
5655 static void AnalyzeRETURN(pCode *pc)
5656 {
5657
5658   //  branch_link(pc,findFunctionEnd(pc->next));
5659
5660 }
5661
5662 #endif
5663
5664 /*-----------------------------------------------------------------*/
5665 /*-----------------------------------------------------------------*/
5666 regs * pic16_getRegFromInstruction(pCode *pc)
5667 {
5668
5669   if(!pc                   || 
5670      !isPCI(pc)            ||
5671      !PCI(pc)->pcop        ||
5672      PCI(pc)->num_ops == 0 ||
5673      (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5674     return NULL;
5675
5676 #if 0
5677   fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5678         dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5679 #endif
5680
5681   switch(PCI(pc)->pcop->type) {
5682   case PO_PRODL:
5683   case PO_PRODH:
5684
5685   case PO_INDF0:
5686   case PO_FSR0:
5687     return PCOR(PCI(pc)->pcop)->r;
5688
5689   case PO_BIT:
5690   case PO_GPR_TEMP:
5691 //      fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5692     return PCOR(PCI(pc)->pcop)->r;
5693
5694   case PO_IMMEDIATE:
5695 //    return pic16_dirregWithName(PCOI(PCI(pc)->pcop)->r->name);
5696
5697     if(PCOI(PCI(pc)->pcop)->r)
5698       return (PCOI(PCI(pc)->pcop)->r);
5699     else
5700       return NULL;
5701     
5702   case PO_GPR_BIT:
5703     return PCOR(PCI(pc)->pcop)->r;
5704
5705   case PO_GPR_REGISTER:
5706   case PO_DIR:
5707 //      fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5708     return PCOR(PCI(pc)->pcop)->r;
5709
5710   case PO_LITERAL:
5711     //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5712     break;
5713
5714   default:
5715 //      fprintf(stderr, "pic16_getRegFromInstruction - unknown reg type %d\n",PCI(pc)->pcop->type);
5716 //      genericPrint(stderr, pc);
5717 //      assert( 0 );
5718         break;
5719   }
5720
5721   return NULL;
5722 }
5723
5724 /*-------------------------------------------------------------------------------*/
5725 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5726 /*-------------------------------------------------------------------------------*/
5727 regs * pic16_getRegFromInstruction2(pCode *pc)
5728 {
5729
5730   if(!pc                   || 
5731      !isPCI(pc)            ||
5732      !PCI(pc)->pcop        ||
5733      PCI(pc)->num_ops == 0 ||
5734      (PCI(pc)->num_ops == 1))           // accept only 2 operand commands
5735     return NULL;
5736
5737
5738 #if 0
5739   fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5740         dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5741 #endif
5742
5743 /*
5744  * operands supported in MOVFF:
5745  *  PO_INF0/PO_FSR0
5746  *  PO_GPR_TEMP
5747  *  PO_IMMEDIATE
5748  *  PO_DIR
5749  *
5750  */
5751   switch(PCI(pc)->pcop->type) {
5752   case PO_PRODL:
5753   case PO_PRODH:
5754
5755   case PO_INDF0:
5756   case PO_FSR0:
5757     return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5758
5759     //    return typeRegWithIdx (PCOR(PCI(pc)->pcop)->rIdx, REG_SFR, 0);
5760
5761 //  case PO_BIT:
5762   case PO_GPR_TEMP:
5763     //fprintf(stderr, "pic16_getRegFromInstruction2 - bit or temp\n");
5764     return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5765
5766   case PO_IMMEDIATE:
5767 #if 0
5768 //    if(PCOI(PCI(pc)->pcop)->r)
5769 //      return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5770
5771     //fprintf(stderr, "pic16_getRegFromInstruction2 - immediate\n");
5772     return pic16_dirregWithName(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r->name);
5773 #endif
5774
5775     if(PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r)
5776       return (PCOI(PCOR2(PCI(pc)->pcop)->pcop2)->r);
5777     else
5778       return NULL;
5779
5780
5781   case PO_GPR_BIT:
5782         break;
5783 //    return PCOR2(PCI(pc)->pcop)->r;
5784
5785   case PO_GPR_REGISTER:
5786   case PO_DIR:
5787     //fprintf(stderr, "pic16_getRegFromInstruction2 - dir\n");
5788     return PCOR(PCOR2(PCI(pc)->pcop)->pcop2)->r;
5789
5790   case PO_LITERAL:
5791         break;
5792     //fprintf(stderr, "pic16_getRegFromInstruction2 - literal\n");
5793
5794   default:
5795     //fprintf(stderr, "pic16_getRegFromInstruction2 - unknown reg type %d\n",PCI(pc)->pcop->type);
5796     //genericPrint(stderr, pc);
5797     break;
5798   }
5799
5800   return NULL;
5801
5802 }
5803
5804 /*-----------------------------------------------------------------*/
5805 /*-----------------------------------------------------------------*/
5806
5807 static void AnalyzepBlock(pBlock *pb)
5808 {
5809   pCode *pc;
5810
5811   if(!pb)
5812     return;
5813
5814   /* Find all of the registers used in this pBlock 
5815    * by looking at each instruction and examining it's
5816    * operands
5817    */
5818   for(pc = pb->pcHead; pc; pc = pc->next) {
5819
5820     /* Is this an instruction with operands? */
5821     if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5822
5823       if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5824
5825         /* Loop through all of the registers declared so far in
5826            this block and see if we find this one there */
5827
5828         regs *r = setFirstItem(pb->tregisters);
5829
5830         while(r) {
5831           if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5832             PCOR(PCI(pc)->pcop)->r = r;
5833             break;
5834           }
5835           r = setNextItem(pb->tregisters);
5836         }
5837
5838         if(!r) {
5839           /* register wasn't found */
5840           //r = Safe_calloc(1, sizeof(regs));
5841           //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5842           //addSet(&pb->tregisters, r);
5843           addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5844           //PCOR(PCI(pc)->pcop)->r = r;
5845           //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5846         }/* else 
5847           fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5848          */
5849       }
5850       if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5851         if(PCOR(PCI(pc)->pcop)->r) {
5852           pic16_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
5853           DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5854         } else {
5855           if(PCI(pc)->pcop->name)
5856             fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5857           else
5858             fprintf(stderr,"ERROR: NULL register\n");
5859         }
5860       }
5861     }
5862
5863
5864   }
5865 }
5866
5867 /*-----------------------------------------------------------------*/
5868 /* */
5869 /*-----------------------------------------------------------------*/
5870 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5871
5872 static void InsertpFlow(pCode *pc, pCode **pflow)
5873 {
5874   if(*pflow)
5875     PCFL(*pflow)->end = pc;
5876
5877   if(!pc || !pc->next)
5878     return;
5879
5880   *pflow = pic16_newpCodeFlow();
5881   pic16_pCodeInsertAfter(pc, *pflow);
5882 }
5883
5884 /*-----------------------------------------------------------------*/
5885 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
5886 /*                         the flow blocks.                        */
5887 /*
5888  * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5889  * point the instruction flow changes. 
5890  */
5891 /*-----------------------------------------------------------------*/
5892 void pic16_BuildFlow(pBlock *pb)
5893 {
5894   pCode *pc;
5895   pCode *last_pci=NULL;
5896   pCode *pflow=NULL;
5897   int seq = 0;
5898
5899   if(!pb)
5900     return;
5901
5902   //fprintf (stderr,"build flow start seq %d  ",GpcFlowSeq);
5903   /* Insert a pCodeFlow object at the beginning of a pBlock */
5904
5905   InsertpFlow(pb->pcHead, &pflow);
5906
5907   //pflow = pic16_newpCodeFlow();    /* Create a new Flow object */
5908   //pflow->next = pb->pcHead;  /* Make the current head the next object */
5909   //pb->pcHead->prev = pflow;  /* let the current head point back to the flow object */
5910   //pb->pcHead = pflow;        /* Make the Flow object the head */
5911   //pflow->pb = pb;
5912
5913   for( pc = pic16_findNextInstruction(pb->pcHead);
5914        pc != NULL;
5915        pc=pic16_findNextInstruction(pc)) { 
5916
5917     pc->seq = seq++;
5918     PCI(pc)->pcflow = PCFL(pflow);
5919
5920     //fprintf(stderr," build: ");
5921     //pflow->print(stderr,pflow);
5922
5923     if( PCI(pc)->isSkip) {
5924
5925       /* The two instructions immediately following this one 
5926        * mark the beginning of a new flow segment */
5927
5928       while(pc && PCI(pc)->isSkip) {
5929
5930         PCI(pc)->pcflow = PCFL(pflow);
5931         pc->seq = seq-1;
5932         seq = 1;
5933
5934         InsertpFlow(pc, &pflow);
5935         pc=pic16_findNextInstruction(pc->next);
5936       }
5937
5938       seq = 0;
5939
5940       if(!pc)
5941         break;
5942
5943       PCI(pc)->pcflow = PCFL(pflow);
5944       pc->seq = 0;
5945       InsertpFlow(pc, &pflow);
5946
5947     } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next)))  {
5948
5949       InsertpFlow(pc, &pflow);
5950       seq = 0;
5951
5952     } else if (checkLabel(pc)) { 
5953
5954       /* This instruction marks the beginning of a
5955        * new flow segment */
5956
5957       pc->seq = 0;
5958       seq = 1;
5959
5960       /* If the previous pCode is not a flow object, then 
5961        * insert a new flow object. (This check prevents 
5962        * two consecutive flow objects from being insert in
5963        * the case where a skip instruction preceeds an
5964        * instruction containing a label.) */
5965
5966       if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5967         InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5968
5969       PCI(pc)->pcflow = PCFL(pflow);
5970       
5971     }
5972     last_pci = pc;
5973     pc = pc->next;
5974   }
5975
5976   //fprintf (stderr,",end seq %d",GpcFlowSeq);
5977   if(pflow)
5978     PCFL(pflow)->end = pb->pcTail;
5979 }
5980
5981 /*-------------------------------------------------------------------*/
5982 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
5983 /*                           the flow blocks.                        */
5984 /*
5985  * unBuildFlow removes pCodeFlow objects from a pCode chain
5986  */
5987 /*-----------------------------------------------------------------*/
5988 static void unBuildFlow(pBlock *pb)
5989 {
5990   pCode *pc,*pcnext;
5991
5992   if(!pb)
5993     return;
5994
5995   pc = pb->pcHead;
5996
5997   while(pc) {
5998     pcnext = pc->next;
5999
6000     if(isPCI(pc)) {
6001
6002       pc->seq = 0;
6003       if(PCI(pc)->pcflow) {
6004         //Safe_free(PCI(pc)->pcflow);
6005         PCI(pc)->pcflow = NULL;
6006       }
6007
6008     } else if(isPCFL(pc) )
6009       pc->destruct(pc);
6010
6011     pc = pcnext;
6012   }
6013
6014
6015 }
6016 #if 0
6017 /*-----------------------------------------------------------------*/
6018 /*-----------------------------------------------------------------*/
6019 static void dumpCond(int cond)
6020 {
6021
6022   static char *pcc_str[] = {
6023     //"PCC_NONE",
6024     "PCC_REGISTER",
6025     "PCC_C",
6026     "PCC_Z",
6027     "PCC_DC",
6028     "PCC_OV",
6029     "PCC_N",
6030     "PCC_W",
6031     "PCC_EXAMINE_PCOP",
6032     "PCC_LITERAL",
6033     "PCC_REL_ADDR"
6034   };
6035
6036   int ncond = sizeof(pcc_str) / sizeof(char *);
6037   int i,j;
6038
6039   fprintf(stderr, "0x%04X\n",cond);
6040
6041   for(i=0,j=1; i<ncond; i++, j<<=1)
6042     if(cond & j)
6043       fprintf(stderr, "  %s\n",pcc_str[i]);
6044
6045 }
6046 #endif
6047
6048 #if 0
6049 /*-----------------------------------------------------------------*/
6050 /*-----------------------------------------------------------------*/
6051 static void FlowStats(pCodeFlow *pcflow)
6052 {
6053
6054   pCode *pc;
6055
6056   if(!isPCFL(pcflow))
6057     return;
6058
6059   fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
6060
6061   pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE); 
6062
6063   if(!pc) {
6064     fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
6065     return;
6066   }
6067
6068
6069   fprintf(stderr, "  FlowStats inCond: ");
6070   dumpCond(pcflow->inCond);
6071   fprintf(stderr, "  FlowStats outCond: ");
6072   dumpCond(pcflow->outCond);
6073
6074 }
6075 #endif
6076 /*-----------------------------------------------------------------*
6077  * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
6078  *    if it affects the banking bits. 
6079  * 
6080  * return: -1 == Banking bits are unaffected by this pCode.
6081  *
6082  * return: > 0 == Banking bits are affected.
6083  *
6084  *  If the banking bits are affected, then the returned value describes
6085  * which bits are affected and how they're affected. The lower half
6086  * of the integer maps to the bits that are affected, the upper half
6087  * to whether they're set or cleared.
6088  *
6089  *-----------------------------------------------------------------*/
6090
6091 static int isBankInstruction(pCode *pc)
6092 {
6093   regs *reg;
6094   int bank = -1;
6095
6096   if(!isPCI(pc))
6097     return 0;
6098
6099   if( PCI(pc)->op == POC_MOVLB ||
6100       (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
6101     bank = PCOL(pc)->lit;
6102   }
6103
6104   return 1;
6105 }
6106
6107
6108 /*-----------------------------------------------------------------*/
6109 /*-----------------------------------------------------------------*/
6110 static void FillFlow(pCodeFlow *pcflow)
6111 {
6112
6113   pCode *pc;
6114   int cur_bank;
6115
6116   if(!isPCFL(pcflow))
6117     return;
6118
6119   //  fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
6120
6121   pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE); 
6122
6123   if(!pc) {
6124     //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
6125     return;
6126   }
6127
6128   cur_bank = -1;
6129
6130   do {
6131     isBankInstruction(pc);
6132     pc = pc->next;
6133   } while (pc && (pc != pcflow->end) && !isPCFL(pc));
6134
6135 /*
6136   if(!pc ) {
6137     fprintf(stderr, "  FillFlow - Bad end of flow\n");
6138   } else {
6139     fprintf(stderr, "  FillFlow - Ending flow with\n  ");
6140     pc->print(stderr,pc);
6141   }
6142
6143   fprintf(stderr, "  FillFlow inCond: ");
6144   dumpCond(pcflow->inCond);
6145   fprintf(stderr, "  FillFlow outCond: ");
6146   dumpCond(pcflow->outCond);
6147 */
6148 }
6149
6150 /*-----------------------------------------------------------------*/
6151 /*-----------------------------------------------------------------*/
6152 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
6153 {
6154   pCodeFlowLink *fromLink, *toLink;
6155
6156   if(!from || !to || !to->pcflow || !from->pcflow)
6157     return;
6158
6159   fromLink = pic16_newpCodeFlowLink(from->pcflow);
6160   toLink   = pic16_newpCodeFlowLink(to->pcflow);
6161
6162   addSetIfnotP(&(from->pcflow->to), toLink);   //to->pcflow);
6163   addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
6164
6165 }
6166
6167 /*-----------------------------------------------------------------*
6168  * void LinkFlow(pBlock *pb)
6169  *
6170  * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
6171  * non-branching segments. In LinkFlow, we determine the execution
6172  * order of these segments. For example, if one of the segments ends
6173  * with a skip, then we know that there are two possible flow segments
6174  * to which control may be passed.
6175  *-----------------------------------------------------------------*/
6176 static void LinkFlow(pBlock *pb)
6177 {
6178   pCode *pc=NULL;
6179   pCode *pcflow;
6180   pCode *pct;
6181
6182   //fprintf(stderr,"linkflow \n");
6183
6184   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
6185        pcflow != NULL;
6186        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6187
6188     if(!isPCFL(pcflow))
6189       fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
6190
6191     //fprintf(stderr," link: ");
6192     //pcflow->print(stderr,pcflow);
6193
6194     //FillFlow(PCFL(pcflow));
6195
6196     pc = PCFL(pcflow)->end;
6197
6198     //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
6199     if(isPCI_SKIP(pc)) {
6200       //fprintf(stderr, "ends with skip\n");
6201       //pc->print(stderr,pc);
6202       pct=pic16_findNextInstruction(pc->next);
6203       LinkFlow_pCode(PCI(pc),PCI(pct));
6204       pct=pic16_findNextInstruction(pct->next);
6205       LinkFlow_pCode(PCI(pc),PCI(pct));
6206       continue;
6207     }
6208
6209     if(isPCI_BRANCH(pc)) {
6210       pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6211
6212       //fprintf(stderr, "ends with branch\n  ");
6213       //pc->print(stderr,pc);
6214
6215       if(!(pcol && isPCOLAB(pcol))) {
6216         if((PCI(pc)->op != POC_RETLW)
6217                 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
6218         
6219                 /* continue if label is '$' which assembler knows how to parse */
6220                 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
6221
6222                 if(pic16_pcode_verbose) {
6223                         pc->print(stderr,pc);
6224                         fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
6225                 }
6226         }
6227         continue;
6228       }
6229
6230       if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
6231         LinkFlow_pCode(PCI(pc),PCI(pct));
6232       else
6233         fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
6234                 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
6235
6236 //      fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6237
6238       continue;
6239     }
6240
6241     if(isPCI(pc)) {
6242       //fprintf(stderr, "ends with non-branching instruction:\n");
6243       //pc->print(stderr,pc);
6244
6245       LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6246
6247       continue;
6248     }
6249
6250     if(pc) {
6251       //fprintf(stderr, "ends with unknown\n");
6252       //pc->print(stderr,pc);
6253       continue;
6254     }
6255
6256     //fprintf(stderr, "ends with nothing: ERROR\n");
6257     
6258   }
6259 }
6260 /*-----------------------------------------------------------------*/
6261 /*-----------------------------------------------------------------*/
6262
6263 /*-----------------------------------------------------------------*/
6264 /*-----------------------------------------------------------------*/
6265 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6266 {
6267
6268   if(!pc || !pcflow)
6269     return 0;
6270
6271   if((!isPCI(pc) && !isPCAD(pc)) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6272     return 0;
6273
6274   if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6275     return 1;
6276
6277   return 0;
6278 }
6279
6280
6281
6282
6283
6284 /*-----------------------------------------------------------------*/
6285 /* insertBankSwitch - inserts a bank switch statement in the       */
6286 /*                    assembly listing                             */
6287 /*                                                                 */
6288 /* position == 0: insert before                                    */
6289 /* position == 1: insert after pc                                  */
6290 /* position == 2: like 0 but previous was a skip instruction       */
6291 /*-----------------------------------------------------------------*/
6292 pCodeOp *pic16_popGetLabel(unsigned int key);
6293 extern int pic16_labelOffset;
6294
6295 static void insertBankSwitch(unsigned char position, pCode *pc)
6296 {
6297   pCode *new_pc;
6298
6299         if(!pc)
6300                 return;
6301
6302         /* emit BANKSEL [symbol] */
6303
6304
6305         new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6306         
6307 //      position = 0;           // position is always before (sanity check!)
6308
6309 #if 0
6310         fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6311         pc->print(stderr, pc);
6312 #endif
6313
6314         switch(position) {
6315                 case 1: {
6316                         /* insert the bank switch after this pc instruction */
6317                         pCode *pcnext = pic16_findNextInstruction(pc);
6318
6319                                 pic16_pCodeInsertAfter(pc, new_pc);
6320                                 if(pcnext)pc = pcnext;
6321                 }; break;
6322                 
6323                 case 0:
6324                         /* insert the bank switch BEFORE this pc instruction */
6325                         pic16_pCodeInsertAfter(pc->prev, new_pc);
6326                         break;
6327
6328                 case 2: {
6329                           symbol *tlbl;
6330                           pCode *pcnext, *pcprev, *npci, *ppc;
6331                           PIC_OPCODE ipci;
6332                           int ofs1=0, ofs2=0, len=0;
6333                           
6334                         /* just like 0, but previous was a skip instruction,
6335                          * so some care should be taken */
6336                           
6337                                 pic16_labelOffset += 10000;
6338                                 tlbl = newiTempLabel(NULL);
6339                                 
6340                                 /* invert skip instruction */
6341                                 pcprev = pic16_findPrevInstruction(pc->prev);
6342                                 ipci = PCI(pcprev)->inverted_op;
6343                                 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6344
6345 //                              fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6346
6347                                 /* copy info from old pCode */
6348                                 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6349                                 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6350                                 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6351                                 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6352                                 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6353                                 PCI(npci)->op = PCI(pcprev)->inverted_op;
6354                                 
6355                                 /* unlink old pCode */
6356                                 ppc = pcprev->prev;
6357                                 ppc->next = pcprev->next;
6358                                 pcprev->next->prev = ppc;
6359                                 pic16_pCodeInsertAfter(ppc, npci);
6360                                 
6361                                 /* extra instructions to handle invertion */
6362                                 pcnext = pic16_newpCode(POC_BRA, pic16_popGetLabel(tlbl->key));
6363                                 pic16_pCodeInsertAfter(npci, pcnext);
6364                                 pic16_pCodeInsertAfter(pc->prev, new_pc);
6365                                 
6366                                 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6367                                 pic16_pCodeInsertAfter(pc, pcnext);
6368                         }; break;
6369         }
6370         
6371
6372         /* Move the label, if there is one */
6373         if(PCI(pc)->label) {
6374 //              fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6375 //                      __FILE__, __LINE__, pc, new_pc);
6376                 PCAD(new_pc)->pci.label = PCI(pc)->label;
6377                 PCI(pc)->label = NULL;
6378         }
6379 }
6380
6381
6382 /*-----------------------------------------------------------------*/
6383 /*int compareBankFlow - compare the banking requirements between   */
6384 /*  flow objects. */
6385 /*-----------------------------------------------------------------*/
6386 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6387 {
6388
6389   if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6390     return 0;
6391
6392   if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6393     return 0;
6394
6395   if(pcflow->firstBank == -1)
6396     return 0;
6397
6398
6399   if(pcflowLink->pcflow->firstBank == -1) {
6400     pCodeFlowLink *pctl = setFirstItem( toORfrom ? 
6401                                         pcflowLink->pcflow->to : 
6402                                         pcflowLink->pcflow->from);
6403     return compareBankFlow(pcflow, pctl, toORfrom);
6404   }
6405
6406   if(toORfrom) {
6407     if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6408       return 0;
6409
6410     pcflowLink->bank_conflict++;
6411     pcflowLink->pcflow->FromConflicts++;
6412     pcflow->ToConflicts++;
6413   } else {
6414     
6415     if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6416       return 0;
6417
6418     pcflowLink->bank_conflict++;
6419     pcflowLink->pcflow->ToConflicts++;
6420     pcflow->FromConflicts++;
6421
6422   }
6423   /*
6424   fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6425           pcflowLink->pcflow->pc.seq,
6426           pcflowLink->pcflow->FromConflicts,
6427           pcflowLink->pcflow->ToConflicts);
6428   */
6429   return 1;
6430
6431 }
6432
6433 #if 0
6434 /*-----------------------------------------------------------------*/
6435 /*-----------------------------------------------------------------*/
6436 static void DumpFlow(pBlock *pb)
6437 {
6438   pCode *pc=NULL;
6439   pCode *pcflow;
6440   pCodeFlowLink *pcfl;
6441
6442
6443   fprintf(stderr,"Dump flow \n");
6444   pb->pcHead->print(stderr, pb->pcHead);
6445
6446   pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6447   pcflow->print(stderr,pcflow);
6448
6449   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
6450        pcflow != NULL;
6451        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6452
6453     if(!isPCFL(pcflow)) {
6454       fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6455       continue;
6456     }
6457     fprintf(stderr,"dumping: ");
6458     pcflow->print(stderr,pcflow);
6459     FlowStats(PCFL(pcflow));
6460
6461     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6462
6463       pc = PCODE(pcfl->pcflow);
6464
6465       fprintf(stderr, "    from seq %d:\n",pc->seq);
6466       if(!isPCFL(pc)) {
6467         fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6468         pc->print(stderr,pc);
6469       }
6470
6471     }
6472
6473     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6474
6475       pc = PCODE(pcfl->pcflow);
6476
6477       fprintf(stderr, "    to seq %d:\n",pc->seq);
6478       if(!isPCFL(pc)) {
6479         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6480         pc->print(stderr,pc);
6481       }
6482
6483     }
6484
6485   }
6486
6487 }
6488 #endif
6489 /*-----------------------------------------------------------------*/
6490 /*-----------------------------------------------------------------*/
6491 static int OptimizepBlock(pBlock *pb)
6492 {
6493   pCode *pc, *pcprev;
6494   int matches =0;
6495
6496   if(!pb || !peepOptimizing)
6497     return 0;
6498
6499   DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6500 /*
6501   for(pc = pb->pcHead; pc; pc = pc->next)
6502     matches += pic16_pCodePeepMatchRule(pc);
6503 */
6504
6505   pc = pic16_findNextInstruction(pb->pcHead);
6506   if(!pc)
6507     return 0;
6508
6509   pcprev = pc->prev;
6510   do {
6511
6512
6513     if(pic16_pCodePeepMatchRule(pc)) {
6514
6515       matches++;
6516
6517       if(pcprev)
6518         pc = pic16_findNextInstruction(pcprev->next);
6519       else 
6520         pc = pic16_findNextInstruction(pb->pcHead);
6521     } else
6522       pc = pic16_findNextInstruction(pc->next);
6523   } while(pc);
6524
6525   if(matches)
6526     DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6527   return matches;
6528
6529 }
6530
6531 /*-----------------------------------------------------------------*/
6532 /*-----------------------------------------------------------------*/
6533 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6534 {
6535   pCode *pc;
6536
6537   for(pc = pcs; pc; pc = pc->next) {
6538
6539     if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) && 
6540        (PCI(pc)->pcop) && 
6541        (PCI(pc)->pcop->type == PO_LABEL) &&
6542        (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6543       return pc;
6544   }
6545  
6546
6547   return NULL;
6548 }
6549
6550 /*-----------------------------------------------------------------*/
6551 /*-----------------------------------------------------------------*/
6552 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6553 {
6554
6555   char *s=NULL;
6556
6557   if(isPCI(pc) && 
6558      (PCI(pc)->pcop) && 
6559      (PCI(pc)->pcop->type == PO_LABEL)) {
6560
6561     pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6562
6563 //      fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6564 //    if(pcol->pcop.name)
6565 //      Safe_free(pcol->pcop.name);
6566
6567     /* If the key is negative, then we (probably) have a label to
6568      * a function and the name is already defined */
6569        
6570     if(pcl->key>0)
6571       sprintf(s=buffer,"_%05d_DS_",pcl->key);
6572     else 
6573       s = pcl->label;
6574
6575     //sprintf(buffer,"_%05d_DS_",pcl->key);
6576     if(!s) {
6577       fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6578     }
6579     pcol->pcop.name = Safe_strdup(s);
6580     pcol->key = pcl->key;
6581     //pc->print(stderr,pc);
6582
6583   }
6584
6585
6586 }
6587
6588 /*-----------------------------------------------------------------*/
6589 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
6590 /*                            pCode chain if they're not used.     */
6591 /*-----------------------------------------------------------------*/
6592 static void pBlockRemoveUnusedLabels(pBlock *pb)
6593 {
6594   pCode *pc; pCodeLabel *pcl;
6595
6596   if(!pb)
6597     return;
6598
6599   for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6600
6601     pBranch *pbr = PCI(pc)->label;
6602     if(pbr && pbr->next) {
6603       pCode *pcd = pb->pcHead;
6604
6605 //      fprintf(stderr, "multiple labels\n");
6606 //      pc->print(stderr,pc);
6607
6608       pbr = pbr->next;
6609       while(pbr) {
6610
6611         while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6612           //fprintf(stderr,"Used by:\n");
6613           //pcd->print(stderr,pcd);
6614
6615           exchangeLabels(PCL(pbr->pc),pcd);
6616
6617           pcd = pcd->next;
6618         }
6619         pbr = pbr->next;
6620       }
6621     }
6622   }
6623
6624   for(pc = pb->pcHead; pc; pc = pc->next) {
6625
6626     if(isPCL(pc)) // pc->type == PC_LABEL)
6627       pcl = PCL(pc);
6628     else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6629       pcl = PCL(PCI(pc)->label->pc);
6630     else continue;
6631
6632 //      fprintf(stderr," found  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6633
6634     /* This pCode is a label, so search the pBlock to see if anyone
6635      * refers to it */
6636
6637     if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6638         && (!pcl->force)) {
6639     //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6640       /* Couldn't find an instruction that refers to this label
6641        * So, unlink the pCode label from it's pCode chain
6642        * and destroy the label */
6643 //      fprintf(stderr," removed  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6644
6645       DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6646       if(pc->type == PC_LABEL) {
6647         pic16_unlinkpCode(pc);
6648         pCodeLabelDestruct(pc);
6649       } else {
6650         unlinkpCodeFromBranch(pc, PCODE(pcl));
6651         /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6652           Safe_free(pc->label);
6653         }*/
6654       }
6655
6656     }
6657   }
6658
6659 }
6660
6661
6662 /*-----------------------------------------------------------------*/
6663 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode      */
6664 /*                     chain and put them into pBranches that are  */
6665 /*                     associated with the appropriate pCode       */
6666 /*                     instructions.                               */
6667 /*-----------------------------------------------------------------*/
6668 void pic16_pBlockMergeLabels(pBlock *pb)
6669 {
6670   pBranch *pbr;
6671   pCode *pc, *pcnext=NULL;
6672
6673   if(!pb)
6674     return;
6675
6676   /* First, Try to remove any unused labels */
6677   //pBlockRemoveUnusedLabels(pb);
6678
6679   /* Now loop through the pBlock and merge the labels with the opcodes */
6680
6681   pc = pb->pcHead;
6682   //  for(pc = pb->pcHead; pc; pc = pc->next) {
6683
6684   while(pc) {
6685     pCode *pcn = pc->next;
6686
6687     if(pc->type == PC_LABEL) {
6688
6689 //      fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6690 //      fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6691
6692       if((pcnext = pic16_findNextInstruction(pc) )) {
6693
6694 //              pcnext->print(stderr, pcnext);
6695
6696         // Unlink the pCode label from it's pCode chain
6697         pic16_unlinkpCode(pc);
6698         
6699 //      fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6700         // And link it into the instruction's pBranch labels. (Note, since
6701         // it's possible to have multiple labels associated with one instruction
6702         // we must provide a means to accomodate the additional labels. Thus
6703         // the labels are placed into the singly-linked list "label" as 
6704         // opposed to being a single member of the pCodeInstruction.)
6705
6706         //_ALLOC(pbr,sizeof(pBranch));
6707 #if 1
6708         pbr = Safe_calloc(1,sizeof(pBranch));
6709         pbr->pc = pc;
6710         pbr->next = NULL;
6711
6712         PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6713 #endif
6714       } else {
6715         if(pic16_pcode_verbose)
6716         fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6717       }
6718     } else if(pc->type == PC_CSOURCE) {
6719
6720       /* merge the source line symbolic info into the next instruction */
6721       if((pcnext = pic16_findNextInstruction(pc) )) {
6722
6723         // Unlink the pCode label from it's pCode chain
6724         pic16_unlinkpCode(pc);
6725         PCI(pcnext)->cline = PCCS(pc);
6726         //fprintf(stderr, "merging CSRC\n");
6727         //genericPrint(stderr,pcnext);
6728       }
6729
6730     }
6731     pc = pcn;
6732   }
6733   pBlockRemoveUnusedLabels(pb);
6734
6735 }
6736
6737 /*-----------------------------------------------------------------*/
6738 /*-----------------------------------------------------------------*/
6739 static int OptimizepCode(char dbName)
6740 {
6741 #define MAX_PASSES 4
6742
6743   int matches = 0;
6744   int passes = 0;
6745   pBlock *pb;
6746
6747   if(!the_pFile)
6748     return 0;
6749
6750   DFPRINTF((stderr," Optimizing pCode\n"));
6751
6752   do {
6753     matches = 0;
6754     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6755       if('*' == dbName || getpBlock_dbName(pb) == dbName)
6756         matches += OptimizepBlock(pb);
6757     }
6758   }
6759   while(matches && ++passes < MAX_PASSES);
6760
6761   return matches;
6762 }
6763
6764
6765
6766 const char *pic16_pCodeOpType(pCodeOp *pcop);
6767 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6768
6769
6770 /*-----------------------------------------------------------------*/
6771 /* pic16_popCopyGPR2Bit - copy a pcode operator                          */
6772 /*-----------------------------------------------------------------*/
6773
6774 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6775 {
6776   pCodeOp *pcop=NULL;
6777
6778 //  fprintf(stderr, "%s:%d pc type: %s\tname: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc), pc->name);
6779
6780   if(pc->name) {
6781         pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6782   } else {
6783     if(PCOR(pc)->r)pcop = pic16_newpCodeOpBit(PCOR(pc)->r->name, bitval, 0, pc->type);
6784   }
6785
6786   assert(pcop != NULL);
6787
6788   if( !( (pcop->type == PO_LABEL) ||
6789          (pcop->type == PO_LITERAL) ||
6790          (pcop->type == PO_STR) ))
6791     PCOR(pcop)->r = PCOR(pc)->r;  /* This is dangerous... */
6792     PCOR(pcop)->r->wasUsed = 1;
6793     PCOR(pcop)->instance = PCOR(pc)->instance;
6794
6795   return pcop;
6796 }
6797
6798
6799 /*----------------------------------------------------------------------*
6800  * pic16_areRegsSame - check to see if the names of two registers match *
6801  *----------------------------------------------------------------------*/
6802 int pic16_areRegsSame(regs *r1, regs *r2)
6803 {
6804         if(!strcmp(r1->name, r2->name))return 1;
6805
6806   return 0;
6807 }
6808
6809
6810 /*-----------------------------------------------------------------*/
6811 /*-----------------------------------------------------------------*/
6812 static void pic16_FixRegisterBanking(pBlock *pb)
6813 {
6814   pCode *pc=NULL;
6815   pCode *pcprev=NULL;
6816   regs *reg, *prevreg;
6817   unsigned char flag=0;
6818   
6819         if(!pb)
6820                 return;
6821
6822         pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6823         if(!pc)return;
6824
6825         /* loop through all of the flow blocks with in one pblock */
6826
6827 //      fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6828
6829         prevreg = NULL;
6830         do {
6831                 /* at this point, pc should point to a PC_FLOW object */
6832                 /* for each flow block, determine the register banking 
6833                  * requirements */
6834
6835                 
6836                 /* if label, then might come from other point, force banksel */
6837                 if(isPCL(pc))prevreg = NULL;
6838                 
6839                 if(!isPCI(pc))goto loop;
6840
6841                 if(PCI(pc)->label)prevreg = NULL;
6842
6843                 if(PCI(pc)->is2MemOp)goto loop;
6844
6845                 /* if goto, then force banksel */
6846 //              if(PCI(pc)->op == POC_GOTO)prevreg = NULL;
6847        
6848                 reg = pic16_getRegFromInstruction(pc);
6849
6850 #if 0
6851                 pc->print(stderr, pc);
6852                 fprintf(stderr, "reg = %p\n", reg);
6853
6854                 if(reg) {
6855                         fprintf(stderr, "%s:%d:  %s  %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6856                         fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6857                                 reg->address,reg->isBitField, reg->isFixed);
6858                 }
6859 #endif
6860
6861                 /* now make some tests to make sure that instruction needs bank switch */
6862
6863                 /* if no register exists, and if not a bit opcode goto loop */
6864                 if(!reg) {
6865                         if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6866                 }
6867                  
6868                 if(isPCI_SKIP(pc)) {
6869 //                      fprintf(stderr, "instruction is SKIP instruction\n");
6870 //                prevreg = NULL;
6871                 }
6872                 if(reg && isACCESS_BANK(reg))goto loop;
6873
6874                 if(!isBankInstruction(pc))goto loop;
6875
6876                 if(isPCI_LIT(pc))goto loop;
6877          
6878                 if(PCI(pc)->op == POC_CALL)goto loop;
6879
6880                 /* Examine the instruction before this one to make sure it is
6881                  * not a skip type instruction */
6882                 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6883
6884                 flag = 0;               /* add before this instruction */
6885                 
6886                 /* if previous instruction is a skip one, then set flag
6887                  * to 2 and call insertBankSwitch */
6888                 if(pcprev && isPCI_SKIP(pcprev)) {
6889                   flag=2;       //goto loop
6890 //                prevreg = NULL;
6891                 }
6892                  
6893                 if(pic16_options.opt_banksel>0) {
6894                   char op1[128], op2[128];
6895                   
6896                     if(prevreg) {
6897                       strcpy(op1, pic16_get_op_from_instruction(PCI(pc)));
6898                       strcpy(op2, pic16_get_op_from_instruction(PCI(pcprev)));
6899                       if(!strcmp(op1, op2))goto loop;
6900                     }
6901                 }
6902                 prevreg = reg;
6903                 insertBankSwitch(flag, pc);
6904
6905 //              fprintf(stderr, "BANK SWITCH inserted\n");
6906                 
6907 loop:
6908                 pcprev = pc;
6909                 pc = pc->next;
6910         } while (pc);
6911 }
6912
6913 /** ADDITIONS BY RAPHAEL NEIDER, 2004-11-16: GOTO OPTIMIZATIONS **/
6914
6915 /* Returns the (maximum of the) number of bytes used by the specified pCode. */
6916 int instrSize (pCode *pc)
6917 {
6918   if (!pc) return 0;
6919
6920   if (isPCAD(pc)) {
6921     if (!PCAD(pc)->directive || strlen (PCAD(pc)->directive) < 3) return 0;
6922     return 4; // assumes only regular instructions using <= 4 bytes
6923   }
6924
6925   if (isPCI(pc)) return PCI(pc)->isize;
6926
6927   return 0;
6928 }
6929
6930 /* Returns 1 if pc is referenced by the given label (either
6931  * pc is the label itself or is an instruction with an attached
6932  * label).
6933  * Returns 0 if pc is not preceeded by the specified label.
6934  */
6935 int isLabel (pCode *pc, char *label)
6936 {
6937   if (!pc) return 0;
6938
6939   // label attached to the pCode?  
6940   if (isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO) {
6941     pBranch *lab = NULL;
6942     lab = PCI(pc)->label;
6943
6944     while (lab) {
6945       if (isPCL(lab->pc) && strcmp(PCL(lab->pc)->label, label) == 0) {
6946         return 1;
6947       }
6948       lab = lab->next;
6949     } // while
6950   } // if
6951
6952   // is inline assembly label?
6953   if (isPCAD(pc) && PCAD(pc)->directive == NULL && PCAD(pc)->arg) {
6954     // do not compare trailing ':'
6955     if (strncmp (PCAD(pc)->arg, label, strlen (label)) == 0) {
6956       return 1;
6957     }
6958   } // if
6959   
6960   // is pCodeLabel?
6961   if (isPCL(pc)) {
6962       if (strcmp(PCL(pc)->label,label) == 0) {
6963       return 1;
6964     }
6965   } // if
6966   
6967   // no label/no label attached/wrong label(s)
6968   return 0;
6969 }
6970
6971 /* Returns the distance to the given label in terms of words.
6972  * Labels are searched only within -max .. max words from pc.
6973  * Returns max if the label could not be found or
6974  * its distance from pc in (-max..+max).
6975  */
6976 int findpCodeLabel (pCode *pc, char *label, int max, pCode **target) {
6977   int dist = instrSize(pc);
6978   pCode *curr = pc;
6979
6980   // search backwards
6981   while (dist < max && curr && !isLabel (curr, label)) {
6982     curr = curr->prev;
6983     dist += instrSize(curr); // sizeof (instruction)
6984   } // while
6985   if (curr && dist < max) {
6986     if (target != NULL) *target = curr;
6987     return -dist;
6988   }
6989
6990   dist = 0;
6991   curr = pic16_findNextInstruction (pc->next);
6992   //search forwards
6993   while (dist < max && curr && !isLabel (curr, label)) {
6994     dist += instrSize(curr); // sizeof (instruction)
6995     curr = curr->next;
6996   } // while
6997   if (curr && dist < max) {
6998     if (target != NULL) *target = curr;
6999     return dist;
7000   }
7001
7002   if (target != NULL) *target = NULL;
7003   return max;
7004 }
7005
7006 /* Returns -1 if pc does NOT denote an instruction like
7007  * BTFS[SC] STATUS,i
7008  * Otherwise we return 
7009  *   (a) 0x10 + i for BTFSS
7010  *   (b) 0x00 + i for BTFSC
7011  */
7012 int isSkipOnStatus (pCode *pc)
7013 {
7014   int res = -1;
7015   pCodeOp *pcop;
7016   if (!pc || !isPCI(pc)) return -1;
7017   if (PCI(pc)->op == POC_BTFSS) res = 0x10;
7018   else if (PCI(pc)->op == POC_BTFSC) res = 0x00;
7019   else return -1;
7020
7021   pcop = PCI(pc)->pcop;
7022
7023   if (pcop->type == PO_STATUS || (pcop->type == PO_GPR_BIT && strcmp(pcop->name, "STATUS") == 0)) {
7024     return res + ((pCodeOpRegBit *)pcop)->bit;
7025   }
7026
7027   return -1;
7028 }
7029
7030 /* Returns 1 if pc is one of BC, BZ, BOV, BN, BNC, BNZ, BNOV or BNN,
7031  * returns 0 otherwise. */
7032 int isConditionalBranch (pCode *pc)
7033 {
7034   if (!pc || !isPCI_BRANCH(pc)) return 0;
7035
7036   switch (PCI(pc)->op) {
7037   case POC_BC:
7038   case POC_BZ:
7039   case POC_BOV:
7040   case POC_BN:
7041   case POC_BNC:
7042   case POC_BNZ:
7043   case POC_BNOV:
7044   case POC_BNN:
7045     return 1;
7046
7047   default:
7048     break;
7049   } // switch
7050
7051   return 0;
7052 }
7053
7054 /* Returns 1 if pc has a label attached to it.
7055  * This can be either a label stored in the pCode itself (.label)
7056  * or a label making up its own pCode preceding this pc.
7057  * Returns 0 if pc cannot be reached directly via a label.
7058  */
7059 int hasNoLabel (pCode *pc)
7060 {
7061   pCode *prev;
7062   if (!pc) return 1;
7063
7064   // are there any label pCodes between pc and the previous instruction?
7065   prev = pic16_findPrevInstruction (pc->prev);
7066   while (pc && pc != prev) {
7067     // pCode with attached label?
7068     if ((isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO)
7069         && PCI(pc)->label) {
7070       return 0;
7071     }
7072     // is inline assembly label?
7073     if (isPCAD(pc) && PCAD(pc)->directive == NULL) return 0;
7074     if (isPCW(pc) && PCW(pc)->label) return 0;
7075
7076     // pCodeLabel?
7077     if (isPCL(pc)) return 0;
7078
7079     pc = pc->prev;
7080   } // if
7081
7082   // no label found
7083   return 1;
7084 }
7085
7086 /* Replaces the old pCode with the new one, moving the labels,
7087  * C source line and probably flow information to the new pCode.
7088  */
7089 void pic16_pCodeReplace (pCode *oldPC, pCode *newPC) {
7090   if (!oldPC || !newPC || !isPCI(oldPC) || !isPCI(newPC))
7091     return;
7092
7093   /* first move all labels from old to new */
7094   PCI(newPC)->label = pic16_pBranchAppend (PCI(oldPC)->label, PCI(newPC)->label);
7095   PCI(oldPC)->label = NULL;
7096   
7097   /* move C source line (if possible) */
7098   if (PCI(oldPC)->cline && !PCI(newPC)->cline)
7099     PCI(newPC)->cline = PCI(oldPC)->cline;
7100
7101   /* insert new pCode into pBlock */
7102   pic16_pCodeInsertAfter (oldPC, newPC);
7103   pic16_unlinkpCode (oldPC);
7104   
7105   /* TODO: update flow (newPC->from, newPC->to) */
7106   PCI(newPC)->pcflow = PCI(oldPC)->pcflow;
7107
7108   /* destruct replaced pCode */
7109   oldPC->destruct (oldPC);
7110 }
7111
7112 /* Returns the inverted conditional branch (if any) or NULL.
7113  * pcop must be set to the new jump target.
7114  */
7115 pCode *getNegatedBcc (pCode *bcc, pCodeOp *pcop)
7116 {
7117   pCode *newBcc;
7118
7119   if (!bcc || !isPCI(bcc)) return NULL;
7120
7121   switch (PCI(bcc)->op) {
7122   case POC_BC:   newBcc = pic16_newpCode (POC_BNC , pcop); break;
7123   case POC_BZ:   newBcc = pic16_newpCode (POC_BNZ , pcop); break;
7124   case POC_BOV:  newBcc = pic16_newpCode (POC_BNOV, pcop); break;
7125   case POC_BN:   newBcc = pic16_newpCode (POC_BNN , pcop); break;
7126   case POC_BNC:  newBcc = pic16_newpCode (POC_BC  , pcop); break;
7127   case POC_BNZ:  newBcc = pic16_newpCode (POC_BZ  , pcop); break;
7128   case POC_BNOV: newBcc = pic16_newpCode (POC_BOV , pcop); break;
7129   case POC_BNN:  newBcc = pic16_newpCode (POC_BN  , pcop); break;
7130   default:
7131     newBcc = NULL;
7132   }
7133   return newBcc;
7134 }
7135
7136 #define MAX_DIST_GOTO         0x7FFFFFFF
7137 #define MAX_DIST_BRA                1020        // maximum offset (in bytes) possible with BRA
7138 #define MAX_DIST_BCC                 120        // maximum offset (in bytes) possible with Bcc
7139 #define MAX_JUMPCHAIN_DEPTH           16        // number of GOTOs to follow in resolveJumpChain() (to prevent endless loops)
7140 #define IS_GOTO(arg) ((arg) && isPCI(arg) && (PCI(arg)->op == POC_GOTO || PCI(arg)->op == POC_BRA))
7141
7142 /* Follows GOTO/BRA instructions to their target instructions, stores the
7143  * final destination (not a GOTO or BRA instruction) in target and returns
7144  * the distance from the original pc to *target.
7145  */
7146 int resolveJumpChain (pCode *pc, pCode **target, pCodeOp **pcop) {
7147         pCode *curr = pc;
7148         pCode *last = NULL;
7149         pCodeOp *lastPCOP = NULL;
7150         int dist = 0;
7151         int depth = 0;
7152
7153         //fprintf (stderr, "%s:%d: -=-", __FUNCTION__, __LINE__);
7154
7155         /* only follow unconditional branches, except for the initial pCode (which may be a conditional branch) */
7156         while (curr && (last != curr) && (depth++ < MAX_JUMPCHAIN_DEPTH) && isPCI(curr)
7157                         && (PCI(curr)->op == POC_GOTO || PCI(curr)->op == POC_BRA || (curr == pc && isConditionalBranch(curr)))) {
7158                 last = curr;
7159                 lastPCOP = PCI(curr)->pcop;
7160                 dist = findpCodeLabel (pc, PCI(curr)->pcop->name, MAX_DIST_GOTO, &curr);
7161                 //fprintf (stderr, "last:%p, curr:%p, label:%s\n", last, curr, PCI(last)->pcop->name);
7162         } // while
7163
7164         if (target) *target = last;
7165         if (pcop) *pcop = lastPCOP;
7166         return dist;
7167 }
7168
7169 /* Returns pc if it is not a OPT_JUMPTABLE_BEGIN INFO pCode.
7170  * Otherwise the first pCode after the jumptable (after
7171  * the OPT_JUMPTABLE_END tag) is returned.
7172  */
7173 pCode *skipJumptables (pCode *pc, int *isJumptable)
7174 {
7175   *isJumptable = 0;
7176   if (!pc) return NULL;
7177   
7178   while (pc->type == PC_INFO && PCINF(pc)->type == INF_OPTIMIZATION && PCOO(PCINF(pc)->oper1)->type == OPT_JUMPTABLE_BEGIN) {
7179     *isJumptable = 1;
7180     //fprintf (stderr, "SKIPPING jumptable\n");
7181     do {
7182       //pc->print(stderr, pc);
7183       pc = pc->next;
7184     } while (pc && (pc->type != PC_INFO || PCINF(pc)->type != INF_OPTIMIZATION
7185                     || PCOO(PCINF(pc)->oper1)->type != OPT_JUMPTABLE_END));
7186     //fprintf (stderr, "<<JUMPTAB:\n");
7187     // skip OPT_END as well
7188     if (pc) pc = pc->next;
7189   } // while
7190
7191   return pc;
7192 }
7193
7194 pCode *pic16_findNextInstructionSkipJumptables (pCode *pc, int *isJumptable)
7195 {
7196   int isJumptab;
7197   *isJumptable = 0;
7198   while (pc && !isPCI(pc) && !isPCAD(pc) && !isPCW(pc)) {
7199     // set pc to the first pCode after a jumptable, leave pc untouched otherwise
7200     pc = skipJumptables (pc, &isJumptab);
7201     if (isJumptab) {
7202         // pc is the first pCode after the jumptable
7203         *isJumptable = 1;
7204     } else {
7205         // pc has not been changed by skipJumptables()
7206         pc = pc->next;
7207     }
7208   } // while
7209   
7210   return pc;
7211 }
7212
7213 /* Turn GOTOs into BRAs if distance between GOTO and label
7214  * is less than 1024 bytes.
7215  *
7216  * This method is especially useful if GOTOs after BTFS[SC]
7217  * can be turned into BRAs as GOTO would cost another NOP
7218  * if skipped.
7219  */
7220 void pic16_OptimizeJumps ()
7221 {
7222   pCode *pc;
7223   pCode *pc_prev = NULL;
7224   pCode *pc_next = NULL;
7225   pBlock *pb;
7226   pCode *target;
7227   int change, iteration, isJumptab;
7228   int isHandled = 0;
7229   char *label;
7230   int opt=0, toofar=0, opt_cond = 0, cond_toofar=0, opt_reorder = 0, opt_gotonext = 0, opt_gotochain = 0;
7231   
7232   if (!the_pFile) return;
7233   
7234   //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__);
7235   
7236   for (pb = the_pFile->pbHead; pb != NULL; pb = pb->next) {
7237     int matchedInvertRule = 1;
7238     iteration = 1;
7239     do {
7240       //fprintf (stderr, "%s:%d: iterating over pBlock %p\n", __FUNCTION__, __LINE__, pb);
7241       change = 0;
7242       pc = pic16_findNextInstruction (pb->pcHead);
7243     
7244       while (pc) {
7245         pc_next = pic16_findNextInstructionSkipJumptables (pc->next, &isJumptab);
7246         if (isJumptab) {
7247                 // skip jumptable, i.e. start over with no pc_prev!     
7248                 pc_prev = NULL;
7249                 pc = pc_next;
7250                 continue;
7251         } // if
7252
7253         /* (1) resolve chained jumps
7254          * Do not perform this until pattern (4) is no longer present! Otherwise we will
7255          * (a) leave dead code in and
7256          * (b) skip over the dead code with an (unneccessary) jump.
7257          */
7258         if (!matchedInvertRule && (IS_GOTO(pc) || isConditionalBranch(pc))) {
7259           pCodeOp *lastTargetOp = NULL;
7260           int newDist = resolveJumpChain (pc, &target, &lastTargetOp);
7261           int maxDist = MAX_DIST_BCC;
7262           if (PCI(pc)->op == POC_BRA) maxDist = MAX_DIST_BRA;
7263           if (PCI(pc)->op == POC_GOTO) maxDist = MAX_DIST_GOTO;
7264           
7265           /* be careful NOT to make the jump instruction longer (might break previously shortened jumps!) */
7266           if (lastTargetOp && newDist <= maxDist && lastTargetOp != PCI(pc)->pcop
7267               && strcmp (lastTargetOp->name, PCI(pc)->pcop->name) != 0) {
7268             //fprintf (stderr, "(1) ");pc->print(stderr, pc); fprintf (stderr, " --> %s\n", lastTargetOp->name);
7269             if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(1) jump chain resolved")); }
7270             PCI(pc)->pcop->name = lastTargetOp->name;
7271             change++;
7272             opt_gotochain++;
7273           } // if
7274         } // if
7275
7276
7277         if (IS_GOTO(pc)) {
7278           int dist;
7279           int condBraType = isSkipOnStatus(pc_prev);
7280           label = PCI(pc)->pcop->name;
7281           dist = findpCodeLabel(pc, label, MAX_DIST_BRA, &target);
7282           if (dist < 0) dist = -dist;
7283           //fprintf (stderr, "distance: %d (", dist); pc->print(stderr, pc);fprintf (stderr, ")\n");
7284           isHandled = 0;
7285           
7286           
7287           /* (2) remove "GOTO label; label:" */
7288           if (isLabel (pc_next, label)) {
7289             //fprintf (stderr, "(2) GOTO next instruction: ");pc->print(stderr, pc);fprintf (stderr, " --> ");pc_next->print(stderr, pc_next); fprintf(stderr, "\n");
7290             // first remove all preceeding SKIP instructions
7291             while (pc_prev && isPCI_SKIP(pc_prev)) {
7292               // attach labels on this instruction to pc_next
7293               //fprintf (stderr, "(2) preceeding SKIP removed: ");pc_prev->print(stderr, pc_prev);fprintf(stderr, "\n");
7294               PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc_prev)->label, PCI(pc_next)->label);
7295               PCI(pc_prev)->label = NULL;
7296               if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(2) SKIP removed")); }
7297               pic16_unlinkpCode (pc_prev);
7298               pc_prev = pic16_findPrevInstruction (pc);
7299             } // while
7300             // now remove the redundant goto itself
7301             PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc)->label, PCI(pc_next)->label);
7302             if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc, pic16_newpCodeCharP("(2) GOTO next instruction removed")); }
7303             pic16_unlinkpCode (pc);
7304             pc = pic16_findPrevInstruction(pc_next->prev);
7305             isHandled = 1; // do not perform further optimizations
7306             opt_gotonext++;
7307             change++;
7308           } // if
7309           
7310           
7311           /* (3) turn BTFSx STATUS,i; GOTO label into Bcc label if possible */
7312           if (!isHandled && condBraType != -1 && hasNoLabel(pc)) {
7313             if (dist < MAX_DIST_BCC) {
7314               pCode *bcc = NULL;
7315               switch (condBraType) {
7316               case 0x00: bcc = pic16_newpCode (POC_BC, PCI(pc)->pcop);break;
7317                 // no BDC on DIGIT CARRY available
7318               case 0x02: bcc = pic16_newpCode (POC_BZ, PCI(pc)->pcop);break;
7319               case 0x03: bcc = pic16_newpCode (POC_BOV, PCI(pc)->pcop);break;
7320               case 0x04: bcc = pic16_newpCode (POC_BN, PCI(pc)->pcop);break;
7321               case 0x10: bcc = pic16_newpCode (POC_BNC, PCI(pc)->pcop);break;
7322                 // no BNDC on DIGIT CARRY available
7323               case 0x12: bcc = pic16_newpCode (POC_BNZ, PCI(pc)->pcop);break;
7324               case 0x13: bcc = pic16_newpCode (POC_BNOV, PCI(pc)->pcop);break;
7325               case 0x14: bcc = pic16_newpCode (POC_BNN, PCI(pc)->pcop);break;
7326               default:
7327                 // no replacement possible
7328                 bcc = NULL;
7329                 break;
7330               } // switch
7331               if (bcc) {
7332                 // ATTENTION: keep labels attached to BTFSx!
7333                 // HINT: GOTO is label free (checked above)
7334                 //fprintf (stderr, "%s:%d: (3) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(bcc)->mnemonic, label);
7335                 isHandled = 1; // do not perform further optimizations
7336                 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(3) conditional branch introduced")); }
7337                 pic16_pCodeReplace (pc_prev, bcc);
7338                 pc->destruct(pc);
7339                 pc = bcc;
7340                 opt_cond++;
7341                 change++;
7342               } // if
7343             } else {
7344               //fprintf (stderr, "(%d, too far for Bcc)\n", dist);
7345               cond_toofar++;
7346             } // if
7347           } // if
7348
7349           if (!isHandled) {
7350             // (4) eliminate the following (common) tripel:
7351             //           <pred.>;
7352             //  labels1: Bcc label2;
7353             //           GOTO somewhere;    ; <-- instruction referenced by pc
7354             //  label2:  <cont.>
7355             // and replace it by
7356             //  labels1: B#(cc) somewhere;  ; #(cc) is the negated condition cc
7357             //  label2:  <cont.>
7358             // ATTENTION: all labels pointing to "Bcc label2" must be attached
7359             //            to <cont.> instead
7360             // ATTENTION: This optimization is only valid if <pred.> is
7361             //            not a skip operation!
7362             // ATTENTION: somewhere must be within MAX_DIST_BCC bytes!
7363             // ATTENTION: no label may be attached to the GOTO instruction!
7364             if (isConditionalBranch(pc_prev)
7365                 && (!isPCI_SKIP(pic16_findPrevInstruction(pc_prev->prev)))
7366                 && (dist < MAX_DIST_BCC)
7367                 && isLabel(pc_next,PCI(pc_prev)->pcop->name)
7368                 && hasNoLabel(pc)) {
7369               pCode *newBcc = getNegatedBcc (pc_prev, PCI(pc)->pcop);
7370             
7371               if (newBcc) {
7372                 //fprintf (stderr, "%s:%d: (4) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBcc)->mnemonic, label);
7373                 isHandled = 1; // do not perform further optimizations
7374                 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(4) conditional skipping branch inverted")); }
7375                 pic16_pCodeReplace (pc_prev, newBcc);
7376                 pc->destruct(pc);
7377                 pc = newBcc;
7378                 opt_reorder++;
7379                 change++;
7380                 matchedInvertRule++;
7381               }
7382             }
7383           }
7384           
7385           /* (5) now just turn GOTO into BRA */ 
7386           if (!isHandled && (PCI(pc)->op == POC_GOTO)) {
7387             if (dist < MAX_DIST_BRA) {
7388               pCode *newBra = pic16_newpCode (POC_BRA, PCI(pc)->pcop);
7389               //fprintf (stderr, "%s:%d: (5) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBra)->mnemonic, label);
7390               if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc->prev, pic16_newpCodeCharP("(5) GOTO replaced by BRA")); }
7391               pic16_pCodeReplace (pc, newBra);
7392               pc = newBra;
7393               opt++;
7394               change++;
7395             } else {
7396               //fprintf (stderr, "(%d, too far for BRA)\n", dist);
7397               toofar++;
7398             }
7399           } // if (!isHandled)
7400         } // if
7401
7402         pc_prev = pc;
7403         pc = pc_next;
7404       } // while (pc)
7405       
7406       pBlockRemoveUnusedLabels (pb);
7407       
7408       // This line enables goto chain resolution!
7409       if (matchedInvertRule > 1) matchedInvertRule = 1; else matchedInvertRule = 0;
7410
7411       iteration++;
7412     } while (change); /* fixpoint iteration per pBlock */
7413   } // for (pb)
7414   
7415   // emit some statistics concerning goto-optimization
7416 #if 0
7417   if (pic16_debug_verbose || pic16_pcode_verbose) {
7418     fprintf (stderr, "optimize-goto:\n"
7419              "\t%5d GOTO->BRA; (%d GOTOs too far)\n"
7420              "\t%5d BTFSx, GOTO->Bcc (%d too far)\n"
7421              "\t%5d conditional \"skipping\" jumps inverted\n"
7422              "\t%5d GOTOs to next instruction removed\n"
7423              "\t%5d chained GOTOs resolved\n",
7424              opt, toofar, opt_cond, cond_toofar, opt_reorder, opt_gotonext, opt_gotochain);
7425   } // if
7426 #endif
7427   //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__);
7428 }
7429
7430 #undef IS_GOTO
7431 #undef MAX_JUMPCHAIN_DEPTH
7432 #undef MAX_DIST_GOTO
7433 #undef MAX_DIST_BRA
7434 #undef MAX_DIST_BCC
7435
7436 /** END OF RAPHAEL NEIDER'S ADDITIONS **/
7437
7438 static void pBlockDestruct(pBlock *pb)
7439 {
7440
7441   if(!pb)
7442     return;
7443
7444
7445 //  Safe_free(pb);
7446
7447 }
7448
7449 /*-----------------------------------------------------------------*/
7450 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
7451 /*                                  name dbName and combine them   */
7452 /*                                  into one block                 */
7453 /*-----------------------------------------------------------------*/
7454 static void mergepBlocks(char dbName)
7455 {
7456
7457   pBlock *pb, *pbmerged = NULL,*pbn;
7458
7459   pb = the_pFile->pbHead;
7460
7461   //fprintf(stderr," merging blocks named %c\n",dbName);
7462   while(pb) {
7463
7464     pbn = pb->next;
7465     //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
7466     if( getpBlock_dbName(pb) == dbName) {
7467
7468       //fprintf(stderr," merged block %c\n",dbName);
7469
7470       if(!pbmerged) {
7471         pbmerged = pb;
7472       } else {
7473         pic16_addpCode2pBlock(pbmerged, pb->pcHead);
7474         /* pic16_addpCode2pBlock doesn't handle the tail: */
7475         pbmerged->pcTail = pb->pcTail;
7476
7477         pb->prev->next = pbn;
7478         if(pbn) 
7479           pbn->prev = pb->prev;
7480
7481
7482         pBlockDestruct(pb);
7483       }
7484       //pic16_printpBlock(stderr, pbmerged);
7485     } 
7486     pb = pbn;
7487   }
7488
7489 }
7490
7491 /*-----------------------------------------------------------------*/
7492 /* AnalyzeFlow - Examine the flow of the code and optimize         */
7493 /*                                                                 */
7494 /* level 0 == minimal optimization                                 */
7495 /*   optimize registers that are used only by two instructions     */
7496 /* level 1 == maximal optimization                                 */
7497 /*   optimize by looking at pairs of instructions that use the     */
7498 /*   register.                                                     */
7499 /*-----------------------------------------------------------------*/
7500
7501 static void AnalyzeFlow(int level)
7502 {
7503   static int times_called=0;
7504   pBlock *pb;
7505
7506         if(!the_pFile) {
7507
7508                 /* remove unused allocated registers before exiting */
7509                 pic16_RemoveUnusedRegisters();
7510         
7511           return;
7512         }
7513
7514
7515   /* if this is not the first time this function has been called,
7516      then clean up old flow information */
7517         if(times_called++) {
7518                 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7519                         unBuildFlow(pb);
7520
7521                 pic16_RegsUnMapLiveRanges();
7522         }
7523
7524         GpcFlowSeq = 1;
7525
7526   /* Phase 2 - Flow Analysis - Register Banking
7527    *
7528    * In this phase, the individual flow blocks are examined
7529    * and register banking is fixed.
7530    */
7531
7532 #if 0
7533         for(pb = the_pFile->pbHead; pb; pb = pb->next)
7534                 pic16_FixRegisterBanking(pb);
7535 #endif
7536
7537   /* Phase 2 - Flow Analysis
7538    *
7539    * In this phase, the pCode is partition into pCodeFlow 
7540    * blocks. The flow blocks mark the points where a continuous
7541    * stream of instructions changes flow (e.g. because of
7542    * a call or goto or whatever).
7543    */
7544
7545         for(pb = the_pFile->pbHead; pb; pb = pb->next)
7546                 pic16_BuildFlow(pb);
7547
7548
7549   /* Phase 2 - Flow Analysis - linking flow blocks
7550    *
7551    * In this phase, the individual flow blocks are examined
7552    * to determine their order of excution.
7553    */
7554
7555         for(pb = the_pFile->pbHead; pb; pb = pb->next)
7556                 LinkFlow(pb);
7557
7558   /* Phase 3 - Flow Analysis - Flow Tree
7559    *
7560    * In this phase, the individual flow blocks are examined
7561    * to determine their order of execution.
7562    */
7563
7564         for(pb = the_pFile->pbHead; pb; pb = pb->next)
7565                 pic16_BuildFlowTree(pb);
7566
7567
7568   /* Phase x - Flow Analysis - Used Banks
7569    *
7570    * In this phase, the individual flow blocks are examined
7571    * to determine the Register Banks they use
7572    */
7573
7574 #if 0
7575         for(pb = the_pFile->pbHead; pb; pb = pb->next)
7576                 FixBankFlow(pb);
7577 #endif
7578
7579
7580         for(pb = the_pFile->pbHead; pb; pb = pb->next)
7581                 pic16_pCodeRegMapLiveRanges(pb);
7582
7583         pic16_RemoveUnusedRegisters();
7584
7585   //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
7586         pic16_pCodeRegOptimizeRegUsage(level);
7587
7588
7589         if(!options.nopeep)
7590                 OptimizepCode('*');
7591
7592
7593 #if 0
7594         for(pb = the_pFile->pbHead; pb; pb = pb->next)
7595                 DumpFlow(pb);
7596 #endif
7597
7598   /* debug stuff */ 
7599         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7600           pCode *pcflow;
7601                 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
7602                         (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7603                         pcflow = pcflow->next) {
7604
7605                         FillFlow(PCFL(pcflow));
7606                 }
7607         }
7608
7609 #if 0
7610         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7611           pCode *pcflow;
7612
7613                 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
7614                         (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7615                         pcflow = pcflow->next) {
7616
7617                         FlowStats(PCFL(pcflow));
7618                 }
7619         }
7620 #endif
7621 }
7622
7623 /* VR -- no need to analyze banking in flow, but left here :
7624  *      1. because it may be used in the future for other purposes
7625  *      2. because if omitted we'll miss some optimization done here
7626  *
7627  * Perhaps I should rename it to something else
7628  */
7629
7630 /*-----------------------------------------------------------------*/
7631 /* pic16_AnalyzeBanking - Called after the memory addresses have been    */
7632 /*                  assigned to the registers.                     */
7633 /*                                                                 */
7634 /*-----------------------------------------------------------------*/
7635
7636 void pic16_AnalyzeBanking(void)
7637 {
7638   pBlock  *pb;
7639
7640
7641         /* Phase x - Flow Analysis - Used Banks
7642          *
7643          * In this phase, the individual flow blocks are examined
7644          * to determine the Register Banks they use
7645          */
7646
7647         AnalyzeFlow(0);
7648         AnalyzeFlow(1);
7649
7650         if(!the_pFile)return;
7651
7652         if(!pic16_options.no_banksel) {
7653                 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7654 //                      fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
7655                         pic16_FixRegisterBanking(pb);
7656                 }
7657         }
7658
7659 }
7660
7661 /*-----------------------------------------------------------------*/
7662 /* buildCallTree - Look at the flow and extract all of the calls.  */
7663 /*-----------------------------------------------------------------*/
7664 static set *register_usage(pBlock *pb);
7665
7666 static void buildCallTree(void    )
7667 {
7668   pBranch *pbr;
7669   pBlock  *pb;
7670   pCode   *pc;
7671   regs *r;
7672   
7673   if(!the_pFile)
7674     return;
7675
7676
7677
7678   /* Now build the call tree.
7679      First we examine all of the pCodes for functions.
7680      Keep in mind that the function boundaries coincide
7681      with pBlock boundaries. 
7682
7683      The algorithm goes something like this:
7684      We have two nested loops. The outer loop iterates
7685      through all of the pBlocks/functions. The inner
7686      loop iterates through all of the pCodes for
7687      a given pBlock. When we begin iterating through
7688      a pBlock, the variable pc_fstart, pCode of the start
7689      of a function, is cleared. We then search for pCodes
7690      of type PC_FUNCTION. When one is encountered, we
7691      initialize pc_fstart to this and at the same time
7692      associate a new pBranch object that signifies a 
7693      branch entry. If a return is found, then this signifies
7694      a function exit point. We'll link the pCodes of these
7695      returns to the matching pc_fstart.
7696
7697      When we're done, a doubly linked list of pBranches
7698      will exist. The head of this list is stored in
7699      `the_pFile', which is the meta structure for all
7700      of the pCode. Look at the pic16_printCallTree function
7701      on how the pBranches are linked together.
7702
7703    */
7704   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7705     pCode *pc_fstart=NULL;
7706     for(pc = pb->pcHead; pc; pc = pc->next) {
7707
7708         if(isPCI(pc) && pc_fstart) {
7709                 if(PCI(pc)->is2MemOp) {
7710                         r = pic16_getRegFromInstruction2(pc);
7711                         if(r && !strcmp(r->name, "POSTDEC1"))
7712                                 PCF(pc_fstart)->stackusage++;
7713                 } else {
7714                         r = pic16_getRegFromInstruction(pc);
7715                         if(r && !strcmp(r->name, "PREINC1"))
7716                                 PCF(pc_fstart)->stackusage--;
7717                 }
7718         }
7719
7720       if(isPCF(pc)) {
7721         if (PCF(pc)->fname) {
7722
7723           if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
7724             //fprintf(stderr," found main \n");
7725             pb->cmemmap = NULL;  /* FIXME do we need to free ? */
7726             pb->dbName = 'M';
7727           }
7728
7729           pbr = Safe_calloc(1,sizeof(pBranch));
7730           pbr->pc = pc_fstart = pc;
7731           pbr->next = NULL;
7732
7733           the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
7734
7735           // Here's a better way of doing the same:
7736           addSet(&pb->function_entries, pc);
7737
7738         } else {
7739           // Found an exit point in a function, e.g. return
7740           // (Note, there may be more than one return per function)
7741           if(pc_fstart)
7742             pBranchLink(PCF(pc_fstart), PCF(pc));
7743
7744           addSet(&pb->function_exits, pc);
7745         }
7746       } else if(isCALL(pc)) {
7747         addSet(&pb->function_calls,pc);
7748       }
7749     }
7750   }
7751
7752
7753 #if 0
7754   /* This is not needed because currently all register used
7755    * by a function are stored in stack -- VR */
7756    
7757   /* Re-allocate the registers so that there are no collisions
7758    * between local variables when one function call another */
7759
7760   // this is weird...
7761   //  pic16_deallocateAllRegs();
7762
7763   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7764     if(!pb->visited)
7765       register_usage(pb);
7766   }
7767 #endif
7768
7769 }
7770
7771 /*-----------------------------------------------------------------*/
7772 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
7773 /*                all of the logical connections.                  */
7774 /*                                                                 */
7775 /* Essentially what's done here is that the pCode flow is          */
7776 /* determined.                                                     */
7777 /*-----------------------------------------------------------------*/
7778
7779 void pic16_AnalyzepCode(char dbName)
7780 {
7781   pBlock *pb;
7782   int i,changes;
7783
7784   if(!the_pFile)
7785     return;
7786
7787   mergepBlocks('D');
7788
7789
7790   /* Phase 1 - Register allocation and peep hole optimization
7791    *
7792    * The first part of the analysis is to determine the registers
7793    * that are used in the pCode. Once that is done, the peep rules
7794    * are applied to the code. We continue to loop until no more
7795    * peep rule optimizations are found (or until we exceed the
7796    * MAX_PASSES threshold). 
7797    *
7798    * When done, the required registers will be determined.
7799    *
7800    */
7801   i = 0;
7802   do {
7803
7804     DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7805     //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7806
7807     /* First, merge the labels with the instructions */
7808     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7809       if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7810
7811         DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7812         //fprintf(stderr," analyze and merging block %c\n",dbName);
7813         pic16_pBlockMergeLabels(pb);
7814         AnalyzepBlock(pb);
7815       } else {
7816         DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7817       }
7818     }
7819
7820         if(!options.nopeep)
7821                 changes = OptimizepCode(dbName);
7822         else changes = 0;
7823
7824   } while(changes && (i++ < MAX_PASSES));
7825
7826   
7827   buildCallTree();
7828 }
7829
7830
7831 /* convert a series of movff's of local regs to stack, with a single call to
7832  * a support functions which does the same thing via loop */
7833 static void pic16_convertLocalRegs2Support(pCode *pcstart, pCode *pcend, int count, regs *r, int entry)
7834 {
7835   pBranch *pbr;
7836   pCode *pc, *pct;
7837   char *fname[]={"__lr_store", "__lr_restore"};
7838
7839 //    pc = pic16_newpCode(POC_CALL, pic16_popGetFromString( (entry?fname[0]:fname[1]) ));
7840
7841     pct = pic16_findNextInstruction(pcstart->next);
7842     do {
7843       pc = pct;
7844       pct = pc->next;   //pic16_findNextInstruction(pc->next);
7845 //      pc->print(stderr, pc);
7846       if(isPCI(pc) && PCI(pc)->label) {
7847         pbr = PCI(pc)->label;
7848         while(pbr && pbr->pc) {
7849           PCI(pcstart)->label = pic16_pBranchAppend(PCI(pcstart)->label, pbr);
7850           pbr = pbr->next;
7851         }
7852
7853 //        pc->print(stderr, pc);
7854         /* unlink pCode */
7855         pc->prev->next = pct;
7856         pct->prev = pc->prev;
7857 //        pc->next = NULL;
7858 //        pc->prev = NULL;
7859       }
7860     } while ((pc) && (pc != pcend));
7861
7862     /* unlink movff instructions */
7863     pcstart->next = pcend;
7864     pcend->prev = pcstart;
7865
7866     pc = pcstart;
7867 //    if(!entry) {
7868 //      pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
7869 //              pic16_popCopyReg(&pic16_pc_fsr0l), pic16_popCopyReg(pic16_framepnt_lo)))); pc = pct;
7870 //    }
7871                 
7872     pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetWithString(r->name)))); pc = pct;
7873     pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_MOVLW, pic16_popGetLit( count ))); pc = pct;
7874     pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_CALL, pic16_popGetWithString( fname[ (entry==1?0:1) ] ))); pc = pct;
7875
7876 //    if(!entry) {
7877 //      pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
7878 //              pic16_popCopyReg(pic16_framepnt_lo), pic16_popCopyReg(&pic16_pc_fsr0l)))); pc = pct;
7879 //    }
7880
7881     
7882     {
7883       symbol *sym;
7884
7885         sym = newSymbol( fname[ entry?0:1 ], 0 );
7886         strcpy(sym->rname, fname[ entry?0:1 ]);
7887         checkAddSym(&externs, sym);
7888         
7889 //        fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fname[ entry?0:1 ]);
7890     }
7891
7892 }
7893
7894 /*-----------------------------------------------------------------*/
7895 /* OptimizeLocalRegs - turn sequence of MOVFF instructions for     */
7896 /*    local registers to a support function call                   */
7897 /*-----------------------------------------------------------------*/
7898 void pic16_OptimizeLocalRegs(void)
7899 {
7900   pBlock  *pb;
7901   pCode   *pc;
7902   pCodeInfo *pci;
7903   pCodeOpLocalReg *pclr;
7904   int regCount=0;
7905   int inRegCount=0;
7906   regs *r, *lastr=NULL, *firstr=NULL;
7907   pCode *pcstart=NULL, *pcend=NULL;
7908   int inEntry=0;
7909   char *curFunc=NULL;
7910
7911         /* Overview:
7912          *   local_regs begin mark
7913          *      MOVFF r0x01, POSTDEC1
7914          *      MOVFF r0x02, POSTDEC1
7915          *      ...
7916          *      ...
7917          *      MOVFF r0x0n, POSTDEC1
7918          *   local_regs end mark
7919          *
7920          * convert the above to the below:
7921          *      MOVLW   starting_register_index
7922          *      MOVWF   PRODL
7923          *      MOVLW   register_count
7924          *      call    __save_registers_in_stack
7925          */
7926
7927     if(!the_pFile)
7928       return;
7929
7930     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7931       inRegCount = regCount = 0;
7932       firstr = lastr = NULL;
7933       for(pc = pb->pcHead; pc; pc = pc->next) {
7934
7935         /* hold current function name */
7936         if(pc && isPCF(pc))curFunc = PCF(pc)->fname;
7937         
7938         if(pc && (pc->type == PC_INFO)) {
7939           pci = PCINF(pc);
7940
7941           if(pci->type == INF_LOCALREGS) {
7942             pclr = PCOLR(pci->oper1);
7943             
7944             if((pclr->type == LR_ENTRY_BEGIN)
7945               || (pclr->type == LR_ENTRY_END))inEntry = 1;
7946             else inEntry = 0;
7947             
7948             switch(pclr->type) {
7949               case LR_ENTRY_BEGIN:
7950               case LR_EXIT_BEGIN:
7951                         inRegCount = 1; regCount = 0;
7952                         pcstart = pc;   //pic16_findNextInstruction(pc->next);
7953                         firstr = lastr = NULL;
7954                         break;
7955               
7956               case LR_ENTRY_END:
7957               case LR_EXIT_END:
7958                         inRegCount = -1;
7959                         pcend = pc;     //pic16_findPrevInstruction(pc->prev);
7960
7961 #if 1
7962                         if(curFunc && inWparamList(curFunc+1)) {
7963                           fprintf(stderr, "sdcc: %s: warning: disabling lr-support for functionn %s\n",
7964                                         filename, curFunc);
7965                         } else {
7966                           if(regCount>2) {
7967                             pic16_convertLocalRegs2Support(pcstart, pcend, regCount,
7968                               firstr, inEntry);
7969                           }
7970                         }
7971 #endif
7972                         firstr = lastr = NULL;
7973                         break;
7974             }
7975             
7976             if(inRegCount == -1) {
7977 //              fprintf(stderr, "%s:%d registers used [%s] %d\n", __FILE__, __LINE__, inEntry?"entry":"exit", regCount);
7978               regCount = 0;
7979               inRegCount = 0;
7980             }
7981           }
7982         } else {
7983           if(isPCI(pc) && (PCI(pc)->op == POC_MOVFF) && (inRegCount == 1)) {
7984             if(inEntry)
7985               r = pic16_getRegFromInstruction(pc);
7986             else
7987               r = pic16_getRegFromInstruction2(pc);
7988             if(r && (r->type == REG_GPR) && (r->pc_type == PO_GPR_TEMP)) {
7989               if(!firstr)firstr = r;
7990               regCount++;
7991 //              fprintf(stderr, "%s:%d\t%s\t%i\t%d/%d\n", __FILE__, __LINE__, r->name, r->rIdx);
7992             }
7993           }
7994         }
7995       }
7996     }
7997 }
7998               
7999             
8000
8001
8002
8003 /*-----------------------------------------------------------------*/
8004 /* ispCodeFunction - returns true if *pc is the pCode of a         */
8005 /*                   function                                      */
8006 /*-----------------------------------------------------------------*/
8007 static bool ispCodeFunction(pCode *pc)
8008 {
8009
8010   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
8011     return 1;
8012
8013   return 0;
8014 }
8015
8016 /*-----------------------------------------------------------------*/
8017 /* findFunction - Search for a function by name (given the name)   */
8018 /*                in the set of all functions that are in a pBlock */
8019 /* (note - I expect this to change because I'm planning to limit   */
8020 /*  pBlock's to just one function declaration                      */
8021 /*-----------------------------------------------------------------*/
8022 static pCode *findFunction(char *fname)
8023 {
8024   pBlock *pb;
8025   pCode *pc;
8026   if(!fname)
8027     return NULL;
8028
8029   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8030
8031     pc = setFirstItem(pb->function_entries);
8032     while(pc) {
8033     
8034       if((pc->type == PC_FUNCTION) &&
8035          (PCF(pc)->fname) && 
8036          (strcmp(fname, PCF(pc)->fname)==0))
8037         return pc;
8038
8039       pc = setNextItem(pb->function_entries);
8040
8041     }
8042
8043   }
8044   return NULL;
8045 }
8046
8047 static void MarkUsedRegisters(set *regset)
8048 {
8049
8050   regs *r1,*r2;
8051
8052   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
8053 //      fprintf(stderr, "marking register = %s\t", r1->name);
8054     r2 = pic16_regWithIdx(r1->rIdx);
8055 //      fprintf(stderr, "to register = %s\n", r2->name);
8056     r2->isFree = 0;
8057     r2->wasUsed = 1;
8058   }
8059 }
8060
8061 static void pBlockStats(FILE *of, pBlock *pb)
8062 {
8063
8064   pCode *pc;
8065   regs  *r;
8066
8067         if(!pic16_pcode_verbose)return;
8068         
8069   fprintf(of,";***\n;  pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
8070
8071   // for now just print the first element of each set
8072   pc = setFirstItem(pb->function_entries);
8073   if(pc) {
8074     fprintf(of,";entry:  ");
8075     pc->print(of,pc);
8076   }
8077   pc = setFirstItem(pb->function_exits);
8078   if(pc) {
8079     fprintf(of,";has an exit\n");
8080     //pc->print(of,pc);
8081   }
8082
8083   pc = setFirstItem(pb->function_calls);
8084   if(pc) {
8085     fprintf(of,";functions called:\n");
8086
8087     while(pc) {
8088       if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8089         fprintf(of,";   %s\n",pic16_get_op_from_instruction(PCI(pc)));
8090       }
8091       pc = setNextItem(pb->function_calls);
8092     }
8093   }
8094
8095   r = setFirstItem(pb->tregisters);
8096   if(r) {
8097     int n = elementsInSet(pb->tregisters);
8098
8099     fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
8100
8101     while (r) {
8102       fprintf(of,";   %s\n",r->name);
8103       r = setNextItem(pb->tregisters);
8104     }
8105   }
8106   
8107   fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
8108 }
8109
8110 /*-----------------------------------------------------------------*/
8111 /*-----------------------------------------------------------------*/
8112 #if 0
8113 static void sequencepCode(void)
8114 {
8115   pBlock *pb;
8116   pCode *pc;
8117
8118
8119   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8120
8121     pb->seq = GpCodeSequenceNumber+1;
8122
8123     for( pc = pb->pcHead; pc; pc = pc->next)
8124       pc->seq = ++GpCodeSequenceNumber;
8125   }
8126
8127 }
8128 #endif
8129
8130 /*-----------------------------------------------------------------*/
8131 /*-----------------------------------------------------------------*/
8132 static set *register_usage(pBlock *pb)
8133 {
8134   pCode *pc,*pcn;
8135   set *registers=NULL;
8136   set *registersInCallPath = NULL;
8137
8138   /* check recursion */
8139
8140   pc = setFirstItem(pb->function_entries);
8141
8142   if(!pc)
8143     return registers;
8144
8145   pb->visited = 1;
8146
8147   if(pc->type != PC_FUNCTION)
8148     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
8149
8150   pc = setFirstItem(pb->function_calls);
8151   for( ; pc; pc = setNextItem(pb->function_calls)) {
8152
8153     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8154       char *dest = pic16_get_op_from_instruction(PCI(pc));
8155
8156       pcn = findFunction(dest);
8157       if(pcn) 
8158         registersInCallPath = register_usage(pcn->pb);
8159     } else
8160       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8161
8162   }
8163
8164 #ifdef PCODE_DEBUG
8165   pBlockStats(stderr,pb);  // debug
8166 #endif
8167
8168   // Mark the registers in this block as used.
8169
8170   MarkUsedRegisters(pb->tregisters);
8171   if(registersInCallPath) {
8172     /* registers were used in the functions this pBlock has called */
8173     /* so now, we need to see if these collide with the ones we are */
8174     /* using here */
8175
8176     regs *r1,*r2, *newreg;
8177
8178     DFPRINTF((stderr,"comparing registers\n"));
8179
8180     r1 = setFirstItem(registersInCallPath);
8181     while(r1) {
8182
8183       r2 = setFirstItem(pb->tregisters);
8184
8185       while(r2 && (r1->type != REG_STK)) {
8186
8187         if(r2->rIdx == r1->rIdx) {
8188           newreg = pic16_findFreeReg(REG_GPR);
8189
8190
8191           if(!newreg) {
8192             DFPRINTF((stderr,"Bummer, no more registers.\n"));
8193             exit(1);
8194           }
8195
8196           DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
8197                   r1->rIdx, newreg->rIdx));
8198           r2->rIdx = newreg->rIdx;
8199           //if(r2->name) Safe_free(r2->name);
8200           if(newreg->name)
8201             r2->name = Safe_strdup(newreg->name);
8202           else
8203             r2->name = NULL;
8204           newreg->isFree = 0;
8205           newreg->wasUsed = 1;
8206         }
8207         r2 = setNextItem(pb->tregisters);
8208       }
8209
8210       r1 = setNextItem(registersInCallPath);
8211     }
8212
8213     /* Collisions have been resolved. Now free the registers in the call path */
8214     r1 = setFirstItem(registersInCallPath);
8215     while(r1) {
8216       if(r1->type != REG_STK) {
8217         newreg = pic16_regWithIdx(r1->rIdx);
8218         newreg->isFree = 1;
8219       }
8220       r1 = setNextItem(registersInCallPath);
8221     }
8222
8223   }// else
8224   //    MarkUsedRegisters(pb->registers);
8225
8226   registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
8227 #ifdef PCODE_DEBUG
8228   if(registers) 
8229     DFPRINTF((stderr,"returning regs\n"));
8230   else
8231     DFPRINTF((stderr,"not returning regs\n"));
8232
8233   DFPRINTF((stderr,"pBlock after register optim.\n"));
8234   pBlockStats(stderr,pb);  // debug
8235 #endif
8236
8237   return registers;
8238 }
8239
8240 /*-----------------------------------------------------------------*/
8241 /* pct2 - writes the call tree to a file                           */
8242 /*                                                                 */
8243 /*-----------------------------------------------------------------*/
8244 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
8245 {
8246   pCode *pc,*pcn;
8247   int i;
8248   //  set *registersInCallPath = NULL;
8249
8250   if(!of)
8251     return;
8252
8253   if(indent > 10) {
8254         fprintf(of, "recursive function\n");
8255     return; //recursion ?
8256   }
8257
8258   pc = setFirstItem(pb->function_entries);
8259
8260   if(!pc)
8261     return;
8262
8263   pb->visited = 0;
8264
8265   for(i=0;i<indent;i++)   // Indentation
8266         fputs("+   ", of);
8267   fputs("+- ", of);
8268
8269   if(pc->type == PC_FUNCTION) {
8270     usedstack += PCF(pc)->stackusage;
8271     fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
8272   } else return;  // ???
8273
8274
8275   pc = setFirstItem(pb->function_calls);
8276   for( ; pc; pc = setNextItem(pb->function_calls)) {
8277
8278     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8279       char *dest = pic16_get_op_from_instruction(PCI(pc));
8280
8281       pcn = findFunction(dest);
8282       if(pcn) 
8283         pct2(of,pcn->pb,indent+1, usedstack);   // + PCF(pcn)->stackusage);
8284     } else
8285       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8286
8287   }
8288
8289
8290 }
8291
8292
8293 /*-----------------------------------------------------------------*/
8294 /* pic16_printCallTree - writes the call tree to a file                  */
8295 /*                                                                 */
8296 /*-----------------------------------------------------------------*/
8297
8298 void pic16_printCallTree(FILE *of)
8299 {
8300   pBranch *pbr;
8301   pBlock  *pb;
8302   pCode   *pc;
8303
8304   if(!the_pFile)
8305     return;
8306
8307   if(!of)
8308     of = stderr;
8309
8310   fprintf(of, "\npBlock statistics\n");
8311   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
8312     pBlockStats(of,pb);
8313
8314
8315   fprintf(of,"Call Tree\n");
8316   pbr = the_pFile->functions;
8317   while(pbr) {
8318     if(pbr->pc) {
8319       pc = pbr->pc;
8320       if(!ispCodeFunction(pc))
8321         fprintf(of,"bug in call tree");
8322
8323
8324       fprintf(of,"Function: %s\n", PCF(pc)->fname);
8325
8326       while(pc->next && !ispCodeFunction(pc->next)) {
8327         pc = pc->next;
8328         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
8329           fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
8330       }
8331     }
8332
8333     pbr = pbr->next;
8334   }
8335
8336
8337   fprintf(of,"\n**************\n\na better call tree\n");
8338   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8339 //    if(pb->visited)
8340       pct2(of,pb,0,0);
8341   }
8342
8343   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8344     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
8345   }
8346 }
8347
8348
8349
8350 /*-----------------------------------------------------------------*/
8351 /*                                                                 */
8352 /*-----------------------------------------------------------------*/
8353
8354 static void InlineFunction(pBlock *pb)
8355 {
8356   pCode *pc;
8357   pCode *pc_call;
8358
8359   if(!pb)
8360     return;
8361
8362   pc = setFirstItem(pb->function_calls);
8363
8364   for( ; pc; pc = setNextItem(pb->function_calls)) {
8365
8366     if(isCALL(pc)) {
8367       pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
8368       pCode *pct;
8369       pCode *pce;
8370
8371       pBranch *pbr;
8372
8373       if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) {               /* change 0 to 1 to enable inlining */
8374         
8375         //fprintf(stderr,"Cool can inline:\n");
8376         //pcn->print(stderr,pcn);
8377
8378         //fprintf(stderr,"recursive call Inline\n");
8379         InlineFunction(pcn->pb);
8380         //fprintf(stderr,"return from recursive call Inline\n");
8381
8382         /*
8383           At this point, *pc points to a CALL mnemonic, and
8384           *pcn points to the function that is being called.
8385
8386           To in-line this call, we need to remove the CALL
8387           and RETURN(s), and link the function pCode in with
8388           the CALLee pCode.
8389
8390         */
8391
8392
8393         /* Remove the CALL */
8394         pc_call = pc;
8395         pc = pc->prev;
8396
8397         /* remove callee pBlock from the pBlock linked list */
8398         removepBlock(pcn->pb);
8399
8400         pce = pcn;
8401         while(pce) {
8402           pce->pb = pb;
8403           pce = pce->next;
8404         }
8405
8406         /* Remove the Function pCode */
8407         pct = pic16_findNextInstruction(pcn->next);
8408
8409         /* Link the function with the callee */
8410         pc->next = pcn->next;
8411         pcn->next->prev = pc;
8412         
8413         /* Convert the function name into a label */
8414
8415         pbr = Safe_calloc(1,sizeof(pBranch));
8416         pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
8417         pbr->next = NULL;
8418         PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
8419         PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
8420
8421         /* turn all of the return's except the last into goto's */
8422         /* check case for 2 instruction pBlocks */
8423         pce = pic16_findNextInstruction(pcn->next);
8424         while(pce) {
8425           pCode *pce_next = pic16_findNextInstruction(pce->next);
8426
8427           if(pce_next == NULL) {
8428             /* found the last return */
8429             pCode *pc_call_next =  pic16_findNextInstruction(pc_call->next);
8430
8431             //fprintf(stderr,"found last return\n");
8432             //pce->print(stderr,pce);
8433             pce->prev->next = pc_call->next;
8434             pc_call->next->prev = pce->prev;
8435             PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
8436                                                       PCI(pce)->label);
8437           }
8438
8439           pce = pce_next;
8440         }
8441
8442
8443       }
8444     } else
8445       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8446
8447   }
8448
8449 }
8450
8451 /*-----------------------------------------------------------------*/
8452 /*                                                                 */
8453 /*-----------------------------------------------------------------*/
8454
8455 void pic16_InlinepCode(void)
8456 {
8457
8458   pBlock  *pb;
8459   pCode   *pc;
8460
8461   if(!the_pFile)
8462     return;
8463
8464   if(!functionInlining)
8465     return;
8466
8467   /* Loop through all of the function definitions and count the
8468    * number of times each one is called */
8469   //fprintf(stderr,"inlining %d\n",__LINE__);
8470
8471   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8472
8473     pc = setFirstItem(pb->function_calls);
8474
8475     for( ; pc; pc = setNextItem(pb->function_calls)) {
8476
8477       if(isCALL(pc)) {
8478         pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
8479         if(pcn && isPCF(pcn)) {
8480           PCF(pcn)->ncalled++;
8481         }
8482       } else
8483         fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8484
8485     }
8486   }
8487
8488   //fprintf(stderr,"inlining %d\n",__LINE__);
8489
8490   /* Now, Loop through the function definitions again, but this
8491    * time inline those functions that have only been called once. */
8492   
8493   InlineFunction(the_pFile->pbHead);
8494   //fprintf(stderr,"inlining %d\n",__LINE__);
8495
8496   for(pb = the_pFile->pbHead; pb; pb = pb->next)
8497     unBuildFlow(pb);
8498
8499 }
8500
8501 char *pic_optype_names[]={
8502         "PO_NONE",         // No operand e.g. NOP
8503         "PO_W",              // The working register (as a destination)
8504         "PO_WREG",           // The working register (as a file register)
8505         "PO_STATUS",         // The 'STATUS' register
8506         "PO_BSR",            // The 'BSR' register
8507         "PO_FSR0",           // The "file select register" (in PIC18 family it's one 
8508                              // of three)
8509         "PO_INDF0",          // The Indirect register
8510         "PO_INTCON",         // Interrupt Control register
8511         "PO_GPR_REGISTER",   // A general purpose register
8512         "PO_GPR_BIT",        // A bit of a general purpose register
8513         "PO_GPR_TEMP",       // A general purpose temporary register
8514         "PO_SFR_REGISTER",   // A special function register (e.g. PORTA)
8515         "PO_PCL",            // Program counter Low register
8516         "PO_PCLATH",         // Program counter Latch high register
8517         "PO_PCLATU",         // Program counter Latch upper register
8518         "PO_PRODL",          // Product Register Low
8519         "PO_PRODH",          // Product Register High
8520         "PO_LITERAL",        // A constant
8521         "PO_REL_ADDR",       // A relative address
8522         "PO_IMMEDIATE",      //  (8051 legacy)
8523         "PO_DIR",            // Direct memory (8051 legacy)
8524         "PO_CRY",            // bit memory (8051 legacy)
8525         "PO_BIT",            // bit operand.
8526         "PO_STR",            //  (8051 legacy)
8527         "PO_LABEL",
8528         "PO_WILD"            // Wild card operand in peep optimizer
8529 };
8530
8531
8532 char *dumpPicOptype(PIC_OPTYPE type)
8533 {
8534         return (pic_optype_names[ type ]);
8535 }
8536
8537
8538 /*** BEGIN of stuff belonging to the BANKSEL optimization ***/
8539 #include "graph.h"
8540
8541 #define MAX_COMMON_BANK_SIZE    32
8542 #define FIRST_PSEUDO_BANK_NR  1000
8543
8544 hTab *sym2bank = NULL; // <OPERAND NAME> --> <PSEUDO BANK NR>
8545 hTab *bank2sym = NULL; // <PSEUDO BANK NR> --> <OPERAND NAME>
8546 hTab *coerce = NULL;   // <PSEUDO BANK NR> --> <&PSEUDOBANK>
8547 Graph *adj = NULL;
8548
8549 typedef enum { INVALID_BANK = -1, UNKNOWN_BANK = -2, FIXED_BANK = -3 } pseudoBankNr;
8550
8551 typedef struct {
8552   pseudoBankNr bank;  // number assigned to this pseudoBank
8553   unsigned int size;  // number of operands assigned to this bank
8554   unsigned int ref;   // number of symbols referring to this pseudoBank (for garbage collection)
8555 } pseudoBank;
8556
8557 /*----------------------------------------------------------------------*/
8558 /* hashSymbol - hash function used to map SYMBOLs (or operands) to ints */
8559 /*----------------------------------------------------------------------*/
8560 unsigned int hashSymbol (const char *str)
8561 {
8562   unsigned int res = 0;
8563   if (!str) return 0;
8564
8565   while (*str) {
8566     res ^= (*str);
8567     res = (res << 4) | (res >> (8 * sizeof(unsigned int) - 4));
8568     str++;
8569   } // while
8570
8571   return res;
8572 }
8573
8574 /*-----------------------------------------------------------------------*/
8575 /* compareSymbol - return 1 iff sym1 equals sym2                         */
8576 /*-----------------------------------------------------------------------*/
8577 int compareSymbol (const void *sym1, const void *sym2)
8578 {
8579   char *s1 = (char*) sym1;
8580   char *s2 = (char*) sym2;
8581   
8582   return (strcmp (s1,s2) == 0);
8583 }
8584
8585 /*-----------------------------------------------------------------------*/
8586 /* comparePre - return 1 iff p1 == p2                                    */
8587 /*-----------------------------------------------------------------------*/
8588 int comparePtr (const void *p1, const void *p2)
8589 {
8590   return (p1 == p2);
8591 }
8592
8593 /*----------------------------------------------------------*/
8594 /* getSymbolFromOperand - return a pointer to the symbol in */
8595 /*                        the given operand and its length  */
8596 /*----------------------------------------------------------*/
8597 char *getSymbolFromOperand (char *op, unsigned int *len)
8598 {
8599   char *sym, *curr;
8600   *len = 0;
8601
8602   if (!op) return NULL;
8603
8604   // we recognize two forms of operands: SYMBOL and (SYMBOL + offset)
8605   sym = op;
8606   if (*sym == '(') sym++;
8607
8608   curr = sym;
8609   while (((*curr >= 'A') && (*curr <= 'Z'))
8610          || ((*curr >= 'a') && (*curr <= 'z'))
8611          || ((curr != sym) && (*curr >= '0') && (*curr <= '9'))
8612          || (*curr == '_')) {
8613     // find end of symbol [A-Za-z_]?[A-Za-z0-9]*
8614     curr++;
8615     (*len)++;
8616   } // while
8617
8618   return sym;
8619 }
8620
8621 /*--------------------------------------------------------------------------*/
8622 /* getSymFromBank - get (one) name of a symbol assigned to the given bank   */
8623 /*--------------------------------------------------------------------------*/
8624 char *getSymFromBank (pseudoBankNr bank)
8625 {
8626   assert (bank2sym);
8627
8628   if (bank < 0) return "<INVALID BANK NR>";
8629   return hTabFindByKey (bank2sym, bank % bank2sym->size, (void *) bank, &comparePtr);
8630 }
8631
8632 /*-----------------------------------------------------------------------*/
8633 /* getPseudoBsrFromOperand - maps a string to its corresponding pseudo   */
8634 /*                           bank number (uses hTab sym2bank), if the    */
8635 /*                           symbol is not yet assigned a pseudo bank it */
8636 /*                           is assigned one here                        */
8637 /*-----------------------------------------------------------------------*/
8638 pseudoBankNr getPseudoBankNrFromOperand (const char *op)
8639 {
8640   static pseudoBankNr next_bank = FIRST_PSEUDO_BANK_NR;
8641   pseudoBankNr bank;
8642   unsigned int hash;
8643
8644   assert (sym2bank);
8645
8646   hash = hashSymbol (op) % sym2bank->size;
8647   bank = (pseudoBankNr) hTabFindByKey (sym2bank, hash, op, &compareSymbol);
8648   if (bank == (pseudoBankNr)NULL) bank = UNKNOWN_BANK;
8649
8650   if (bank == UNKNOWN_BANK) {
8651     // create a pseudo bank for the operand
8652     bank = next_bank++;
8653     hTabAddItemLong (&sym2bank, hash, (char *)op, (void *)bank);
8654     hTabAddItemLong (&bank2sym, bank, (void *) bank, (void *)op);
8655     getOrAddGNode (adj, NULL, bank); // adds the node if it does not exist yet
8656     //fprintf (stderr, "%s:%d: adding %s with hash %u in bank %u\n", __FUNCTION__, __LINE__, op, hash, bank);
8657   } else {
8658     //fprintf (stderr, "%s:%d: found %s with hash %u in bank %u\n", __FUNCTION__, __LINE__, op, hash, bank);
8659   } // if
8660
8661   assert (bank >= 0);
8662
8663   return bank;
8664 }
8665
8666 /*--------------------------------------------------------------------*/
8667 /* isBanksel - check whether the given pCode is a BANKSEL instruction */
8668 /*--------------------------------------------------------------------*/
8669 int isBanksel (pCode *pc)
8670 {
8671   if (!pc) return 0;
8672
8673   if (isPCI(pc) && (PCI(pc)->op == POC_BANKSEL || PCI(pc)->op == POC_MOVLB)) {
8674     // BANKSEL <variablename>  or  MOVLB <banknr>
8675     //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8676     return 1;
8677   }
8678
8679   // check for inline assembler BANKSELs
8680   if (isPCAD(pc) && PCAD(pc)->directive && (STRCASECMP(PCAD(pc)->directive,"BANKSEL") == 0 ||
8681                                             STRCASECMP(PCAD(pc)->directive,"MOVLB") == 0)) {
8682     //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8683     return 1;
8684   }
8685
8686   // assume pc is no BANKSEL instruction
8687   return 0;
8688 }
8689
8690 /*---------------------------------------------------------------------------------*/
8691 /* invalidatesBSR - check whether the pCodeInstruction passed in modifies the BSR  */
8692 /*                  This method can not guarantee to find all modifications of the */
8693 /*                  BSR (e.g. via INDirection registers) but covers all compiler   */
8694 /*                  generated plus some cases.                                     */
8695 /*---------------------------------------------------------------------------------*/
8696 int invalidatesBSR(pCode *pc)
8697 {
8698   // assembler directives invalidate BSR (well, they might, we don't know)
8699   if (isPCAD(pc)) return 1;
8700
8701   // only ASMDIRs and pCodeInstructions can invalidate BSR
8702   if (!isPCI(pc)) return 0;
8703
8704   // we have a pCodeInstruction
8705
8706   // check for BSR modifying instructions
8707   switch (PCI(pc)->op) {
8708   case POC_CALL:
8709   case POC_RCALL:
8710   case POC_MOVLB:
8711   case POC_RETFIE:  // might be used as CALL replacement
8712   case POC_RETLW:   // might be used as CALL replacement
8713   case POC_RETURN:  // might be used as CALL replacement
8714   case POC_BANKSEL:
8715     return 1;
8716     break;
8717
8718   default:          // other instruction do not change BSR unless BSR is an explicit operand!
8719     // TODO: check for BSR as an explicit operand (e.g. INCF BSR,F), which should be rather unlikely...!
8720     break;
8721   } // switch
8722
8723   // no change of BSR possible/probable
8724   return 0;
8725 }
8726
8727 /*------------------------------------------------------------*/
8728 /* getBankFromBanksel - return the pseudo bank nr assigned to */
8729 /*                      the symbol referenced in this BANKSEL */
8730 /*------------------------------------------------------------*/
8731 pseudoBankNr getBankFromBanksel (pCode *pc)
8732 {
8733   char *sym;
8734   int data = (int)NULL;
8735
8736   if (!pc) return INVALID_BANK;
8737   
8738   if (isPCAD(pc) && PCAD(pc)->directive) {
8739     if (STRCASECMP(PCAD(pc)->directive,"BANKSEL") == 0) {
8740       // get symbolname from PCAD(pc)->arg
8741       //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8742       sym = PCAD(pc)->arg;
8743       data = getPseudoBankNrFromOperand (sym);
8744       //fprintf (stderr, "symbol: %s, data=%i\n", sym, data);
8745     } else if (STRCASECMP(PCAD(pc)->directive,"MOVLB")) {
8746       // get (literal) bank number from PCAD(pc)->arg
8747       fprintf (stderr, "%s:%d: MOVLB found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8748       assert (0 && "not yet implemented - turn off banksel optimization for now");
8749     }
8750   } else if (isPCI(pc)) {
8751     if (PCI(pc)->op == POC_BANKSEL) {
8752       // get symbolname from PCI(pc)->pcop->name (?)
8753       //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pcop->name);
8754       sym = PCI(pc)->pcop->name;
8755       data = getPseudoBankNrFromOperand (sym);
8756       //fprintf (stderr, "symbol: %s, data=%i\n", sym, data);
8757     } else if (PCI(pc)->op == POC_MOVLB) {
8758       // get (literal) bank number from PCI(pc)->pcop->name
8759       fprintf (stderr, "%s:%d: MOVLB found: %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pcop->name);
8760       assert (0 && "not yet implemented - turn off banksel optimization for now");
8761     }
8762   }
8763   
8764   if (data == 0)
8765     // no assigned bank could be found
8766     return UNKNOWN_BANK;
8767   else
8768     return data;
8769 }
8770
8771 /*------------------------------------------------------------------------------*/
8772 /* getEffectiveBank - resolves the currently assigned effective pseudo bank nr  */
8773 /*------------------------------------------------------------------------------*/
8774 pseudoBankNr getEffectiveBank (pseudoBankNr bank)
8775 {
8776   pseudoBank *data;
8777
8778   if (bank < FIRST_PSEUDO_BANK_NR) return bank;
8779
8780   do {
8781     //fprintf (stderr, "%s:%d: bank=%d\n", __FUNCTION__, __LINE__, bank);
8782     data = (pseudoBank *) hTabFindByKey (coerce, bank % coerce->size, (void *) bank, &comparePtr);
8783     if (data) {
8784       if (data->bank != bank)
8785         bank = data->bank;
8786       else
8787         data = NULL;
8788     }
8789   } while (data);
8790   
8791   //fprintf (stderr, "%s:%d: effective bank=%d\n", __FUNCTION__, __LINE__, bank);
8792   return bank;
8793 }
8794
8795 /*------------------------------------------------------------------*/
8796 /* attachBsrInfo2pBlock - create a look-up table as to which pseudo */
8797 /*                        bank is selected at a given pCode         */
8798 /*------------------------------------------------------------------*/
8799
8800 /* Create a graph with pseudo banks as its nodes and switches between
8801  * these as edges (with the edge weight representing the absolute
8802  * number of BANKSELs from one to the other).
8803  * Removes redundand BANKSELs instead iff mod == 1.
8804  * BANKSELs update the pseudo BSR, labels invalidate the current BSR
8805  * value (setting it to 0=UNNKOWN), (R)CALLs also invalidate the
8806  * pseudo BSR.
8807  * TODO: check ALL instructions operands if they modify BSR directly...
8808  *
8809  * pb - the pBlock to annotate
8810  * mod  - select either graph creation (0) or BANKSEL removal (1)
8811  */
8812 unsigned int attachBsrInfo2pBlock (pBlock *pb, int mod)
8813 {
8814   pCode *pc, *pc_next;
8815   unsigned int prevBSR = UNKNOWN_BANK, pseudoBSR = UNKNOWN_BANK;
8816   int isBankselect = 0;
8817   unsigned int banksels=0;
8818   
8819   if (!pb) return 0;
8820
8821   pc = pic16_findNextInstruction(pb->pcHead);
8822   while (pc) {
8823     isBankselect = isBanksel (pc);
8824     pc_next = pic16_findNextInstruction (pc->next);
8825
8826     if (!hasNoLabel (pc)) {
8827       // we don't know our predecessors -- assume different BSRs
8828       prevBSR = UNKNOWN_BANK;
8829       pseudoBSR = UNKNOWN_BANK;
8830       //fprintf (stderr, "invalidated by label at "); pc->print (stderr, pc);
8831     } // if
8832
8833     // check if this is a BANKSEL instruction
8834     if (isBankselect) {
8835       pseudoBSR = getEffectiveBank (getBankFromBanksel(pc));
8836       //fprintf (stderr, "BANKSEL via "); pc->print (stderr, pc);
8837       if (mod) {
8838         if (prevBSR == pseudoBSR && pseudoBSR >= 0) {
8839           //fprintf (stderr, "removing redundant "); pc->print (stderr, pc);
8840           if (1 || pic16_pcode_verbose) pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("removed redundant BANKSEL"));
8841           pic16_unlinkpCode (pc);
8842           banksels++;
8843         }
8844       } else {
8845         addGEdge2 (getOrAddGNode (adj, NULL, prevBSR), getOrAddGNode (adj, NULL, pseudoBSR), 1, 0);
8846         banksels++;
8847       }
8848     } // if
8849
8850     if (!isBankselect && invalidatesBSR(pc)) {
8851       // check if this instruction invalidates the pseudoBSR
8852       pseudoBSR = UNKNOWN_BANK;
8853       //fprintf (stderr, "invalidated via "); pc->print (stderr, pc);
8854     } // if
8855
8856     prevBSR = pseudoBSR;
8857     pc = pc_next;
8858   } // while
8859
8860   return banksels;
8861 }
8862
8863 /*------------------------------------------------------------------------------------*/
8864 /* assignToSameBank - returns 0 on success or an error code                           */
8865 /*  1 - common bank would be too large                                                */
8866 /*  2 - assignment to fixed (absolute) bank not performed                             */
8867 /*                                                                                    */
8868 /* This functions assumes that unsplittable operands are already assigned to the same */
8869 /* bank (e.g. all objects being referenced as (SYMBOL + offset) must be in the same   */
8870 /* bank so that we can make sure the bytes are laid out sequentially in memory)       */
8871 /* TODO: Symbols with an abslute address must be handled specially!                   */
8872 /*------------------------------------------------------------------------------------*/
8873 int assignToSameBank (int bank0, int bank1, int doAbs)
8874 {
8875   int eff0, eff1, dummy;
8876   pseudoBank *pbank0, *pbank1;
8877   hashtItem *hitem;
8878
8879   eff0 = getEffectiveBank (bank0);
8880   eff1 = getEffectiveBank (bank1);
8881
8882   //fprintf (stderr, "%s:%d: bank0=%d/%d, bank1=%d/%d, doAbs=%d\n", __FUNCTION__, __LINE__, bank0, eff0, bank1, eff1, doAbs);
8883
8884   // nothing to do if already same bank
8885   if (eff0 == eff1) return 0;
8886
8887   if (!doAbs && (eff0 < FIRST_PSEUDO_BANK_NR || eff1 < FIRST_PSEUDO_BANK_NR))
8888     return 2;
8889
8890   // ensure eff0 < eff1
8891   if (eff0 > eff1) {
8892     // swap eff0 and eff1
8893     dummy = eff0;
8894     eff0 = eff1;
8895     eff1 = dummy;
8896     dummy = bank0;
8897     bank0 = bank1;
8898     bank1 = dummy;
8899   } // if
8900
8901   // now assign bank eff1 to bank eff0
8902   pbank0 = (pseudoBank *) hTabFindByKey (coerce, eff0 % coerce->size, (void *)((char*)0+eff0), &comparePtr);
8903   if (!pbank0) {
8904     pbank0 = Safe_calloc (1, sizeof (pseudoBank));
8905     pbank0->bank = eff0;
8906     pbank0->size = 1;
8907     pbank0->ref = 1;
8908     hTabAddItemLong (&coerce, eff0 % coerce->size, (void *)((char*)0+eff0), (void *) pbank0);
8909   } // if
8910
8911   pbank1 = NULL;
8912   hitem = hTabSearch (coerce, eff1 % coerce->size);
8913   while (hitem && hitem->pkey != (void *)((char*)0+eff1))
8914     hitem = hitem->next;
8915
8916   if (hitem) pbank1 = (pseudoBank *) hitem->item;
8917
8918 #if 0
8919   fprintf (stderr, "bank #%d/%d & bank #%d/%d --> bank #%d: %u (%s & %s)\n", bank0, eff0, bank1, eff1,
8920            pbank0->bank, pbank0->size,
8921            getSymFromBank (eff0), getSymFromBank (eff1));
8922 #endif
8923
8924   if (pbank1) {
8925     if (pbank0->size + pbank1->size > MAX_COMMON_BANK_SIZE) {
8926 #if 0
8927       fprintf (stderr, "bank #%d: %u, bank #%d: %u --> bank #%d': %u > %u (%s,%s)\n",
8928                pbank0->bank, pbank0->size, pbank1->bank, pbank1->size,
8929                pbank0->bank, pbank0->size + pbank1->size, MAX_COMMON_BANK_SIZE,
8930                getSymFromBank (pbank0->bank), getSymFromBank (pbank1->bank));
8931 #endif
8932       return 1;
8933     } // if
8934     pbank0->size += pbank1->size;
8935     pbank1->ref--;
8936     if (pbank1->ref == 0) Safe_free (pbank1);
8937   } else {
8938     pbank0->size++;
8939   } // if
8940
8941   if (hitem)
8942     hitem->item = pbank0;
8943   else  
8944     hTabAddItemLong (&coerce, eff1 % coerce->size, (void *)((char*)0+eff1), (void *) pbank0);
8945   pbank0->ref++;
8946
8947   //fprintf (stderr, "%s:%d: leaving.\n", __FUNCTION__, __LINE__);
8948
8949   return 0;
8950 }
8951
8952 /*----------------------------------------------------------------*/
8953 /* mergeGraphNodes - combines two nodes into one and modifies all */
8954 /*                   edges to and from the nodes accordingly      */
8955 /* This method needs complete backedges, i.e. if (A,B) is an edge */
8956 /* then also (B,A) must be an edge (possibly with weight 0).      */
8957 /*----------------------------------------------------------------*/
8958 void mergeGraphNodes (GraphNode *node1, GraphNode *node2)
8959 {
8960   GraphEdge *edge, *backedge, *nextedge;
8961   GraphNode *node;
8962   int backweight;
8963
8964   assert (node1 && node2);
8965   assert (node1 != node2);
8966   
8967   // add all edges starting at node2 to node1
8968   edge = node2->edge;
8969   while (edge) {
8970     nextedge = edge->next;
8971     node = edge->node;
8972     backedge = getGEdge (node, node2);
8973     if (backedge)
8974       backweight = backedge->weight;
8975     else
8976       backweight = 0;
8977     // insert edges (node1,node) and (node,node1)
8978     addGEdge2 (node1, node, edge->weight, backweight);
8979     // remove edges (node, node2) and (node2, node)
8980     remGEdge (node2, node);
8981     remGEdge (node, node2);
8982     edge = nextedge;
8983   } // while
8984   
8985   // now node2 should not be referenced by any other GraphNode...
8986   //remGNode (adj, node2->data, node2->hash);
8987 }
8988
8989 /*----------------------------------------------------------------*/
8990 /* showGraph - dump the current BANKSEL graph as a node/edge list */
8991 /*----------------------------------------------------------------*/
8992 void showGraph (Graph *g)
8993 {
8994   GraphNode *node;
8995   GraphEdge *edge;
8996   pseudoBankNr bankNr;
8997   pseudoBank *pbank;
8998   unsigned int size;
8999
9000   node = g->node;
9001   while (node) {
9002     edge = node->edge;
9003     bankNr = getEffectiveBank (node->hash);
9004     assert (bankNr >= 0);
9005     pbank = (pseudoBank *) hTabFindByKey (coerce, bankNr % coerce->size, (void *) bankNr, &comparePtr);
9006     if (pbank) {
9007       bankNr = pbank->bank;
9008       size = pbank->size;
9009     } else {
9010       size = 1;
9011     }
9012     
9013     fprintf (stderr, "edges from %s (bank %u, size %u) to:\n", getSymFromBank (node->hash), bankNr, size);
9014
9015     while (edge) {
9016       if (edge->weight > 0)
9017         fprintf (stderr, "  %4u x %s\n", edge->weight, getSymFromBank (edge->node->hash));
9018       edge = edge->next;
9019     } // while (edge)
9020     node = node->next;
9021   } // while (node)
9022 }
9023
9024 /*---------------------------------------------------------------*/
9025 /* pic16_OptimizeBanksel - remove redundant BANKSEL instructions */
9026 /*---------------------------------------------------------------*/
9027 void pic16_OptimizeBanksel ()
9028 {
9029   GraphNode *node, *node1, *node1next;
9030
9031 #if 0
9032   // needed for more effective bank assignment (needs adjusted pic16_emit_usection())
9033   GraphEdge *edge, *backedge;
9034   GraphEdge *max;
9035   int maxWeight, weight, mergeMore, absMaxWeight;
9036   pseudoBankNr curr0, curr1;
9037 #endif
9038   pseudoBank *pbank;
9039   pseudoBankNr bankNr;
9040   char *base_symbol0, *base_symbol1;
9041   int len0, len1;
9042   pBlock *pb;
9043   set *set;
9044   regs *reg;
9045   unsigned int bankselsTotal = 0, bankselsRemoved = 0; 
9046
9047   //fprintf (stderr, "%s:%s:%d: entered.\n", __FILE__, __FUNCTION__, __LINE__);
9048
9049   if (!the_pFile || !the_pFile->pbHead) return;
9050
9051   adj = newGraph (NULL);
9052   sym2bank = newHashTable ( 255 );
9053   bank2sym = newHashTable ( 255 );
9054   coerce = newHashTable ( 255 );
9055
9056   // create graph of BANKSEL relationships (node = operands, edge (A,B) iff BANKSEL B follows BANKSEL A)
9057   for (pb = the_pFile->pbHead; pb; pb = pb->next) {
9058     bankselsTotal += attachBsrInfo2pBlock (pb, 0);
9059   } // for pb
9060
9061 #if 1
9062   // assign symbols with absolute addresses to their respective bank nrs
9063   set = pic16_fix_udata;
9064   for (reg = setFirstItem (set); reg; reg = setNextItem (set)) {
9065     bankNr = reg->address >> 8;
9066     node = getOrAddGNode (adj, NULL, bankNr);
9067     bankNr = (pseudoBankNr) getEffectiveBank (getPseudoBankNrFromOperand(reg->name));
9068     assignToSameBank (node->hash, bankNr, 1);
9069     
9070     assert (bankNr >= 0);
9071     pbank = (pseudoBank *) hTabFindByKey (coerce, bankNr % coerce->size, (void *) bankNr, &comparePtr);
9072     if (!pbank) {
9073       pbank = Safe_calloc (1, sizeof (pseudoBank));
9074       pbank->bank = reg->address >> 8; //FIXED_BANK;
9075       pbank->size = 1;
9076       pbank->ref = 1;
9077       hTabAddItemLong (&coerce, bankNr % coerce->size, (void *) bankNr, pbank);
9078     } else {
9079       assert (pbank->bank == (reg->address >> 8));
9080       pbank->bank = reg->address >> 8; //FIXED_BANK;
9081     }
9082     //fprintf (stderr, "ABS: %s (%d bytes) at %x in bank %u\n", reg->name, reg->size, reg->address, bankNr);
9083   } // for reg
9084 #endif
9085
9086 #if 1
9087   // assign operands referring to the same symbol (which is not given an absolute address) to the same bank
9088   //fprintf (stderr, "assign operands with the same symbol to the same bank\n");
9089   node = adj->node;
9090   while (node) {
9091     if (node->hash < 0) { node = node->next; continue; }
9092     base_symbol0 = getSymbolFromOperand (getSymFromBank (getEffectiveBank(node->hash)), &len0);
9093     node1 = node->next;
9094     while (node1) {
9095       if (node1->hash < 0) { node1 = node1->next; continue; }
9096       node1next = node1->next;
9097       base_symbol1 = getSymbolFromOperand (getSymFromBank (getEffectiveBank (node1->hash)), &len1);
9098       if (len0 == len1 && len0 > 0 && strncmp (base_symbol0, base_symbol1, len0) == 0) {
9099         // TODO: check for symbols with absolute addresses -- these might be placed across bank boundaries!
9100         //fprintf (stderr, "merging %s and %s\n", getSymFromBank (getEffectiveBank(node->hash)), getSymFromBank (getEffectiveBank(node1->hash)));
9101         if (assignToSameBank (node->hash, node1->hash, 0)) {
9102           fprintf (stderr, "%s(%d) == %s(%d)\n", base_symbol0, len0, base_symbol1, len1);
9103           assert (0 && "Could not assign a symbol to a bank!");
9104         }
9105         mergeGraphNodes (node, node1);
9106         /*
9107         if (node->hash < node1->hash)
9108           mergeGraphNodes (node, node1);
9109         else
9110           mergeGraphNodes (node1, node); // this removes node so node->next will fail...
9111         */
9112       } // if
9113       node1 = node1next;
9114     } // while (node1)
9115     node = node->next;
9116   } // while (node)
9117 #endif
9118
9119 #if 0
9120   // >>> THIS ALSO NEEDS AN UPDATED pic16_emit_usection() TO REFLECT THE BANK ASSIGNMENTS <<<
9121   // assign tightly coupled operands to the same (pseudo) bank
9122   //fprintf (stderr, "assign tightly coupled operands to the same bank\n");
9123   mergeMore = 1;
9124   absMaxWeight = 0;
9125   while (mergeMore) {
9126     node = adj->node;
9127     max = NULL;
9128     maxWeight = 0;
9129     while (node) {
9130       curr0 = getEffectiveBank (node->hash);
9131       if (curr0 < 0) { node = node->next; continue; }
9132       edge = node->edge;
9133       while (edge) {
9134         assert (edge->src == node);
9135         backedge = getGEdge (edge->node, edge->src);
9136         weight = edge->weight + (backedge ? backedge->weight : 0);
9137         curr1 = getEffectiveBank (edge->node->hash);
9138         if (curr1 < 0) { edge = edge->next; continue; }
9139
9140         // merging is only useful if the items are not assigned to the same bank already...
9141         if (curr0 != curr1 && weight > maxWeight) {
9142           if (maxWeight > absMaxWeight) absMaxWeight = maxWeight;
9143           maxWeight = weight;
9144           max = edge;
9145         } // if
9146         edge = edge->next;
9147       } // while
9148       node = node->next;
9149     } // while
9150     
9151     if (maxWeight > 0) {
9152 #if 0
9153       fprintf (stderr, "%s:%d: merging (%4u) %d(%s) and %d(%s)\n", __FUNCTION__, __LINE__, maxWeight,
9154                max->src->hash, getSymFromBank (max->src->hash),
9155                max->node->hash, getSymFromBank (max->node->hash));
9156 #endif
9157
9158       node = getGNode (adj, max->src->data, max->src->hash);
9159       node1 = getGNode (adj, max->node->data, max->node->hash);
9160
9161       if (0 == assignToSameBank (max->src->hash, max->node->hash, 0)) {
9162         if (max->src->hash < max->node->hash)
9163           mergeGraphNodes (node, node1);
9164         else
9165           mergeGraphNodes (node1, node);
9166       } else {
9167         remGEdge (node, node1);
9168         remGEdge (node1, node);
9169         //mergeMore = 0;
9170       }
9171
9172     } else {
9173       mergeMore = 0;
9174     }
9175   } // while
9176 #endif
9177
9178 #if 1  
9179   // remove redundant BANKSELs
9180   //fprintf (stderr, "removing redundant BANKSELs\n");
9181   for (pb = the_pFile->pbHead; pb; pb = pb->next) {
9182     bankselsRemoved += attachBsrInfo2pBlock (pb, 1);
9183   } // for pb
9184 #endif
9185
9186 #if 0
9187   fprintf (stderr, "display graph\n");
9188   showGraph ();
9189 #endif
9190
9191   deleteGraph (adj);
9192   //fprintf (stderr, "%s:%s:%d: leaving, %u/%u BANKSELs removed...\n", __FILE__, __FUNCTION__, __LINE__, bankselsRemoved, bankselsTotal);
9193 }
9194
9195 /*** END of stuff belonging to the BANKSEL optimization ***/