* device/include/pic16/string.h: modified prototype for memccpy()
[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
6203       pct=pic16_findNextInstruction(pc->next);
6204       LinkFlow_pCode(PCI(pc),PCI(pct));
6205       pct=pic16_findNextInstruction(pct->next);
6206       LinkFlow_pCode(PCI(pc),PCI(pct));
6207       continue;
6208     }
6209
6210     if(isPCI_BRANCH(pc)) {
6211       pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6212
6213       //fprintf(stderr, "ends with branch\n  ");
6214       //pc->print(stderr,pc);
6215
6216       if(!(pcol && isPCOLAB(pcol))) {
6217         if((PCI(pc)->op != POC_RETLW)
6218                 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RETFIE) ) {
6219         
6220                 /* continue if label is '$' which assembler knows how to parse */
6221                 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
6222
6223                 if(pic16_pcode_verbose) {
6224                         pc->print(stderr,pc);
6225                         fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
6226                 }
6227         }
6228         continue;
6229       }
6230
6231       if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
6232         LinkFlow_pCode(PCI(pc),PCI(pct));
6233       else
6234         fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
6235                 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
6236
6237 //      fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6238
6239       continue;
6240     }
6241
6242     if(isPCI(pc)) {
6243       //fprintf(stderr, "ends with non-branching instruction:\n");
6244       //pc->print(stderr,pc);
6245
6246       LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6247
6248       continue;
6249     }
6250
6251     if(pc) {
6252       //fprintf(stderr, "ends with unknown\n");
6253       //pc->print(stderr,pc);
6254       continue;
6255     }
6256
6257     //fprintf(stderr, "ends with nothing: ERROR\n");
6258     
6259   }
6260 }
6261 /*-----------------------------------------------------------------*/
6262 /*-----------------------------------------------------------------*/
6263
6264 /*-----------------------------------------------------------------*/
6265 /*-----------------------------------------------------------------*/
6266 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6267 {
6268
6269   if(!pc || !pcflow)
6270     return 0;
6271
6272   if((!isPCI(pc) && !isPCAD(pc)) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6273     return 0;
6274
6275   if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6276     return 1;
6277
6278   return 0;
6279 }
6280
6281
6282
6283
6284
6285 /*-----------------------------------------------------------------*/
6286 /* insertBankSwitch - inserts a bank switch statement in the       */
6287 /*                    assembly listing                             */
6288 /*                                                                 */
6289 /* position == 0: insert before                                    */
6290 /* position == 1: insert after pc                                  */
6291 /* position == 2: like 0 but previous was a skip instruction       */
6292 /*-----------------------------------------------------------------*/
6293 pCodeOp *pic16_popGetLabel(unsigned int key);
6294 extern int pic16_labelOffset;
6295
6296 static void insertBankSwitch(unsigned char position, pCode *pc)
6297 {
6298   pCode *new_pc;
6299
6300         if(!pc)
6301                 return;
6302
6303         /* emit BANKSEL [symbol] */
6304
6305
6306         new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6307         
6308 //      position = 0;           // position is always before (sanity check!)
6309
6310 #if 0
6311         fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6312         pc->print(stderr, pc);
6313 #endif
6314
6315         switch(position) {
6316                 case 1: {
6317                         /* insert the bank switch after this pc instruction */
6318                         pCode *pcnext = pic16_findNextInstruction(pc);
6319
6320                                 pic16_pCodeInsertAfter(pc, new_pc);
6321                                 if(pcnext)pc = pcnext;
6322                 }; break;
6323                 
6324                 case 0:
6325                         /* insert the bank switch BEFORE this pc instruction */
6326                         pic16_pCodeInsertAfter(pc->prev, new_pc);
6327                         break;
6328
6329                 case 2: {
6330                           symbol *tlbl;
6331                           pCode *pcnext, *pcprev, *npci, *ppc;
6332                           PIC_OPCODE ipci;
6333                           int ofs1=0, ofs2=0, len=0;
6334                           
6335                         /* just like 0, but previous was a skip instruction,
6336                          * so some care should be taken */
6337                           
6338                                 pic16_labelOffset += 10000;
6339                                 tlbl = newiTempLabel(NULL);
6340                                 
6341                                 /* invert skip instruction */
6342                                 pcprev = pic16_findPrevInstruction(pc->prev);
6343                                 ipci = PCI(pcprev)->inverted_op;
6344                                 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6345
6346 //                              fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6347
6348                                 /* copy info from old pCode */
6349                                 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6350                                 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6351                                 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6352                                 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6353                                 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6354                                 PCI(npci)->op = PCI(pcprev)->inverted_op;
6355                                 
6356                                 /* unlink old pCode */
6357                                 ppc = pcprev->prev;
6358                                 ppc->next = pcprev->next;
6359                                 pcprev->next->prev = ppc;
6360                                 pic16_pCodeInsertAfter(ppc, npci);
6361                                 
6362                                 /* extra instructions to handle invertion */
6363                                 pcnext = pic16_newpCode(POC_BRA, pic16_popGetLabel(tlbl->key));
6364                                 pic16_pCodeInsertAfter(npci, pcnext);
6365                                 pic16_pCodeInsertAfter(pc->prev, new_pc);
6366                                 
6367                                 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6368                                 pic16_pCodeInsertAfter(pc, pcnext);
6369                         }; break;
6370         }
6371         
6372
6373         /* Move the label, if there is one */
6374         if(PCI(pc)->label) {
6375 //              fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6376 //                      __FILE__, __LINE__, pc, new_pc);
6377                 PCAD(new_pc)->pci.label = PCI(pc)->label;
6378                 PCI(pc)->label = NULL;
6379         }
6380 }
6381
6382
6383 /*-----------------------------------------------------------------*/
6384 /*int compareBankFlow - compare the banking requirements between   */
6385 /*  flow objects. */
6386 /*-----------------------------------------------------------------*/
6387 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6388 {
6389
6390   if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6391     return 0;
6392
6393   if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6394     return 0;
6395
6396   if(pcflow->firstBank == -1)
6397     return 0;
6398
6399
6400   if(pcflowLink->pcflow->firstBank == -1) {
6401     pCodeFlowLink *pctl = setFirstItem( toORfrom ? 
6402                                         pcflowLink->pcflow->to : 
6403                                         pcflowLink->pcflow->from);
6404     return compareBankFlow(pcflow, pctl, toORfrom);
6405   }
6406
6407   if(toORfrom) {
6408     if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6409       return 0;
6410
6411     pcflowLink->bank_conflict++;
6412     pcflowLink->pcflow->FromConflicts++;
6413     pcflow->ToConflicts++;
6414   } else {
6415     
6416     if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6417       return 0;
6418
6419     pcflowLink->bank_conflict++;
6420     pcflowLink->pcflow->ToConflicts++;
6421     pcflow->FromConflicts++;
6422
6423   }
6424   /*
6425   fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6426           pcflowLink->pcflow->pc.seq,
6427           pcflowLink->pcflow->FromConflicts,
6428           pcflowLink->pcflow->ToConflicts);
6429   */
6430   return 1;
6431
6432 }
6433
6434 #if 0
6435 /*-----------------------------------------------------------------*/
6436 /*-----------------------------------------------------------------*/
6437 static void DumpFlow(pBlock *pb)
6438 {
6439   pCode *pc=NULL;
6440   pCode *pcflow;
6441   pCodeFlowLink *pcfl;
6442
6443
6444   fprintf(stderr,"Dump flow \n");
6445   pb->pcHead->print(stderr, pb->pcHead);
6446
6447   pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6448   pcflow->print(stderr,pcflow);
6449
6450   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
6451        pcflow != NULL;
6452        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6453
6454     if(!isPCFL(pcflow)) {
6455       fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6456       continue;
6457     }
6458     fprintf(stderr,"dumping: ");
6459     pcflow->print(stderr,pcflow);
6460     FlowStats(PCFL(pcflow));
6461
6462     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6463
6464       pc = PCODE(pcfl->pcflow);
6465
6466       fprintf(stderr, "    from seq %d:\n",pc->seq);
6467       if(!isPCFL(pc)) {
6468         fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6469         pc->print(stderr,pc);
6470       }
6471
6472     }
6473
6474     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6475
6476       pc = PCODE(pcfl->pcflow);
6477
6478       fprintf(stderr, "    to seq %d:\n",pc->seq);
6479       if(!isPCFL(pc)) {
6480         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6481         pc->print(stderr,pc);
6482       }
6483
6484     }
6485
6486   }
6487
6488 }
6489 #endif
6490 /*-----------------------------------------------------------------*/
6491 /*-----------------------------------------------------------------*/
6492 static int OptimizepBlock(pBlock *pb)
6493 {
6494   pCode *pc, *pcprev;
6495   int matches =0;
6496
6497   if(!pb || !peepOptimizing)
6498     return 0;
6499
6500   DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6501 /*
6502   for(pc = pb->pcHead; pc; pc = pc->next)
6503     matches += pic16_pCodePeepMatchRule(pc);
6504 */
6505
6506   pc = pic16_findNextInstruction(pb->pcHead);
6507   if(!pc)
6508     return 0;
6509
6510   pcprev = pc->prev;
6511   do {
6512
6513
6514     if(pic16_pCodePeepMatchRule(pc)) {
6515
6516       matches++;
6517
6518       if(pcprev)
6519         pc = pic16_findNextInstruction(pcprev->next);
6520       else 
6521         pc = pic16_findNextInstruction(pb->pcHead);
6522     } else
6523       pc = pic16_findNextInstruction(pc->next);
6524   } while(pc);
6525
6526   if(matches)
6527     DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6528   return matches;
6529
6530 }
6531
6532 /*-----------------------------------------------------------------*/
6533 /*-----------------------------------------------------------------*/
6534 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6535 {
6536   pCode *pc;
6537
6538   for(pc = pcs; pc; pc = pc->next) {
6539
6540     if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE)) && 
6541        (PCI(pc)->pcop) && 
6542        (PCI(pc)->pcop->type == PO_LABEL) &&
6543        (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6544       return pc;
6545   }
6546  
6547
6548   return NULL;
6549 }
6550
6551 /*-----------------------------------------------------------------*/
6552 /*-----------------------------------------------------------------*/
6553 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6554 {
6555
6556   char *s=NULL;
6557
6558   if(isPCI(pc) && 
6559      (PCI(pc)->pcop) && 
6560      (PCI(pc)->pcop->type == PO_LABEL)) {
6561
6562     pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6563
6564 //      fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6565 //    if(pcol->pcop.name)
6566 //      Safe_free(pcol->pcop.name);
6567
6568     /* If the key is negative, then we (probably) have a label to
6569      * a function and the name is already defined */
6570        
6571     if(pcl->key>0)
6572       sprintf(s=buffer,"_%05d_DS_",pcl->key);
6573     else 
6574       s = pcl->label;
6575
6576     //sprintf(buffer,"_%05d_DS_",pcl->key);
6577     if(!s) {
6578       fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6579     }
6580     pcol->pcop.name = Safe_strdup(s);
6581     pcol->key = pcl->key;
6582     //pc->print(stderr,pc);
6583
6584   }
6585
6586
6587 }
6588
6589 /*-----------------------------------------------------------------*/
6590 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
6591 /*                            pCode chain if they're not used.     */
6592 /*-----------------------------------------------------------------*/
6593 static void pBlockRemoveUnusedLabels(pBlock *pb)
6594 {
6595   pCode *pc; pCodeLabel *pcl;
6596
6597   if(!pb)
6598     return;
6599
6600   for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6601
6602     pBranch *pbr = PCI(pc)->label;
6603     if(pbr && pbr->next) {
6604       pCode *pcd = pb->pcHead;
6605
6606 //      fprintf(stderr, "multiple labels\n");
6607 //      pc->print(stderr,pc);
6608
6609       pbr = pbr->next;
6610       while(pbr) {
6611
6612         while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6613           //fprintf(stderr,"Used by:\n");
6614           //pcd->print(stderr,pcd);
6615
6616           exchangeLabels(PCL(pbr->pc),pcd);
6617
6618           pcd = pcd->next;
6619         }
6620         pbr = pbr->next;
6621       }
6622     }
6623   }
6624
6625   for(pc = pb->pcHead; pc; pc = pc->next) {
6626
6627     if(isPCL(pc)) // pc->type == PC_LABEL)
6628       pcl = PCL(pc);
6629     else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6630       pcl = PCL(PCI(pc)->label->pc);
6631     else continue;
6632
6633 //      fprintf(stderr," found  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6634
6635     /* This pCode is a label, so search the pBlock to see if anyone
6636      * refers to it */
6637
6638     if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6639         && (!pcl->force)) {
6640     //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6641       /* Couldn't find an instruction that refers to this label
6642        * So, unlink the pCode label from it's pCode chain
6643        * and destroy the label */
6644 //      fprintf(stderr," removed  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6645
6646       DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6647       if(pc->type == PC_LABEL) {
6648         pic16_unlinkpCode(pc);
6649         pCodeLabelDestruct(pc);
6650       } else {
6651         unlinkpCodeFromBranch(pc, PCODE(pcl));
6652         /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6653           Safe_free(pc->label);
6654         }*/
6655       }
6656
6657     }
6658   }
6659
6660 }
6661
6662
6663 /*-----------------------------------------------------------------*/
6664 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode      */
6665 /*                     chain and put them into pBranches that are  */
6666 /*                     associated with the appropriate pCode       */
6667 /*                     instructions.                               */
6668 /*-----------------------------------------------------------------*/
6669 void pic16_pBlockMergeLabels(pBlock *pb)
6670 {
6671   pBranch *pbr;
6672   pCode *pc, *pcnext=NULL;
6673
6674   if(!pb)
6675     return;
6676
6677   /* First, Try to remove any unused labels */
6678   //pBlockRemoveUnusedLabels(pb);
6679
6680   /* Now loop through the pBlock and merge the labels with the opcodes */
6681
6682   pc = pb->pcHead;
6683   //  for(pc = pb->pcHead; pc; pc = pc->next) {
6684
6685   while(pc) {
6686     pCode *pcn = pc->next;
6687
6688     if(pc->type == PC_LABEL) {
6689
6690 //      fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6691 //      fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6692
6693       if((pcnext = pic16_findNextInstruction(pc) )) {
6694
6695 //              pcnext->print(stderr, pcnext);
6696
6697         // Unlink the pCode label from it's pCode chain
6698         pic16_unlinkpCode(pc);
6699         
6700 //      fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6701         // And link it into the instruction's pBranch labels. (Note, since
6702         // it's possible to have multiple labels associated with one instruction
6703         // we must provide a means to accomodate the additional labels. Thus
6704         // the labels are placed into the singly-linked list "label" as 
6705         // opposed to being a single member of the pCodeInstruction.)
6706
6707         //_ALLOC(pbr,sizeof(pBranch));
6708 #if 1
6709         pbr = Safe_calloc(1,sizeof(pBranch));
6710         pbr->pc = pc;
6711         pbr->next = NULL;
6712
6713         PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6714 #endif
6715       } else {
6716         if(pic16_pcode_verbose)
6717         fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6718       }
6719     } else if(pc->type == PC_CSOURCE) {
6720
6721       /* merge the source line symbolic info into the next instruction */
6722       if((pcnext = pic16_findNextInstruction(pc) )) {
6723
6724         // Unlink the pCode label from it's pCode chain
6725         pic16_unlinkpCode(pc);
6726         PCI(pcnext)->cline = PCCS(pc);
6727         //fprintf(stderr, "merging CSRC\n");
6728         //genericPrint(stderr,pcnext);
6729       }
6730
6731     }
6732     pc = pcn;
6733   }
6734   pBlockRemoveUnusedLabels(pb);
6735
6736 }
6737
6738 /*-----------------------------------------------------------------*/
6739 /*-----------------------------------------------------------------*/
6740 static int OptimizepCode(char dbName)
6741 {
6742 #define MAX_PASSES 4
6743
6744   int matches = 0;
6745   int passes = 0;
6746   pBlock *pb;
6747
6748   if(!the_pFile)
6749     return 0;
6750
6751   DFPRINTF((stderr," Optimizing pCode\n"));
6752
6753   do {
6754     matches = 0;
6755     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6756       if('*' == dbName || getpBlock_dbName(pb) == dbName)
6757         matches += OptimizepBlock(pb);
6758     }
6759   }
6760   while(matches && ++passes < MAX_PASSES);
6761
6762   return matches;
6763 }
6764
6765
6766
6767 const char *pic16_pCodeOpType(pCodeOp *pcop);
6768 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6769
6770
6771 /*-----------------------------------------------------------------*/
6772 /* pic16_popCopyGPR2Bit - copy a pcode operator                          */
6773 /*-----------------------------------------------------------------*/
6774
6775 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6776 {
6777   pCodeOp *pcop=NULL;
6778
6779 //  fprintf(stderr, "%s:%d pc type: %s\tname: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc), pc->name);
6780
6781   if(pc->name) {
6782         pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6783   } else {
6784     if(PCOR(pc)->r)pcop = pic16_newpCodeOpBit(PCOR(pc)->r->name, bitval, 0, pc->type);
6785   }
6786
6787   assert(pcop != NULL);
6788
6789   if( !( (pcop->type == PO_LABEL) ||
6790          (pcop->type == PO_LITERAL) ||
6791          (pcop->type == PO_STR) ))
6792     PCOR(pcop)->r = PCOR(pc)->r;  /* This is dangerous... */
6793     PCOR(pcop)->r->wasUsed = 1;
6794     PCOR(pcop)->instance = PCOR(pc)->instance;
6795
6796   return pcop;
6797 }
6798
6799
6800 /*----------------------------------------------------------------------*
6801  * pic16_areRegsSame - check to see if the names of two registers match *
6802  *----------------------------------------------------------------------*/
6803 int pic16_areRegsSame(regs *r1, regs *r2)
6804 {
6805         if(!strcmp(r1->name, r2->name))return 1;
6806
6807   return 0;
6808 }
6809
6810
6811 /*-----------------------------------------------------------------*/
6812 /*-----------------------------------------------------------------*/
6813 static void pic16_FixRegisterBanking(pBlock *pb)
6814 {
6815   pCode *pc=NULL;
6816   pCode *pcprev=NULL;
6817   regs *reg, *prevreg;
6818   unsigned char flag=0;
6819   
6820         if(!pb)
6821                 return;
6822
6823         pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6824         if(!pc)return;
6825
6826         /* loop through all of the flow blocks with in one pblock */
6827
6828 //      fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6829
6830         prevreg = NULL;
6831         do {
6832                 /* at this point, pc should point to a PC_FLOW object */
6833                 /* for each flow block, determine the register banking 
6834                  * requirements */
6835
6836                 
6837                 /* if label, then might come from other point, force banksel */
6838                 if(isPCL(pc))prevreg = NULL;
6839                 
6840                 if(!isPCI(pc))goto loop;
6841
6842                 if(PCI(pc)->label)prevreg = NULL;
6843
6844                 if(PCI(pc)->is2MemOp)goto loop;
6845
6846                 /* if goto, then force banksel */
6847 //              if(PCI(pc)->op == POC_GOTO)prevreg = NULL;
6848        
6849                 reg = pic16_getRegFromInstruction(pc);
6850
6851 #if 0
6852                 pc->print(stderr, pc);
6853                 fprintf(stderr, "reg = %p\n", reg);
6854
6855                 if(reg) {
6856                         fprintf(stderr, "%s:%d:  %s  %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6857                         fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6858                                 reg->address,reg->isBitField, reg->isFixed);
6859                 }
6860 #endif
6861
6862                 /* now make some tests to make sure that instruction needs bank switch */
6863
6864                 /* if no register exists, and if not a bit opcode goto loop */
6865                 if(!reg) {
6866                         if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6867                 }
6868                  
6869                 if(isPCI_SKIP(pc)) {
6870 //                      fprintf(stderr, "instruction is SKIP instruction\n");
6871 //                prevreg = NULL;
6872                 }
6873                 if(reg && isACCESS_BANK(reg))goto loop;
6874
6875                 if(!isBankInstruction(pc))goto loop;
6876
6877                 if(isPCI_LIT(pc))goto loop;
6878          
6879                 if(PCI(pc)->op == POC_CALL)goto loop;
6880
6881                 /* Examine the instruction before this one to make sure it is
6882                  * not a skip type instruction */
6883                 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
6884
6885                 flag = 0;               /* add before this instruction */
6886                 
6887                 /* if previous instruction is a skip one, then set flag
6888                  * to 2 and call insertBankSwitch */
6889                 if(pcprev && isPCI_SKIP(pcprev)) {
6890                   flag=2;       //goto loop
6891 //                prevreg = NULL;
6892                 }
6893                  
6894                 if(pic16_options.opt_banksel>0) {
6895                   char op1[128], op2[128];
6896                   
6897                     if(prevreg) {
6898                       strcpy(op1, pic16_get_op_from_instruction(PCI(pc)));
6899                       strcpy(op2, pic16_get_op_from_instruction(PCI(pcprev)));
6900                       if(!strcmp(op1, op2))goto loop;
6901                     }
6902                 }
6903                 prevreg = reg;
6904                 insertBankSwitch(flag, pc);
6905
6906 //              fprintf(stderr, "BANK SWITCH inserted\n");
6907                 
6908 loop:
6909                 pcprev = pc;
6910                 pc = pc->next;
6911         } while (pc);
6912 }
6913
6914 /** ADDITIONS BY RAPHAEL NEIDER, 2004-11-16: GOTO OPTIMIZATIONS **/
6915
6916 /* Returns the (maximum of the) number of bytes used by the specified pCode. */
6917 int instrSize (pCode *pc)
6918 {
6919   if (!pc) return 0;
6920
6921   if (isPCAD(pc)) {
6922     if (!PCAD(pc)->directive || strlen (PCAD(pc)->directive) < 3) return 0;
6923     return 4; // assumes only regular instructions using <= 4 bytes
6924   }
6925
6926   if (isPCI(pc)) return PCI(pc)->isize;
6927
6928   return 0;
6929 }
6930
6931 /* Returns 1 if pc is referenced by the given label (either
6932  * pc is the label itself or is an instruction with an attached
6933  * label).
6934  * Returns 0 if pc is not preceeded by the specified label.
6935  */
6936 int isLabel (pCode *pc, char *label)
6937 {
6938   if (!pc) return 0;
6939
6940   // label attached to the pCode?  
6941   if (isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO) {
6942     pBranch *lab = NULL;
6943     lab = PCI(pc)->label;
6944
6945     while (lab) {
6946       if (isPCL(lab->pc) && strcmp(PCL(lab->pc)->label, label) == 0) {
6947         return 1;
6948       }
6949       lab = lab->next;
6950     } // while
6951   } // if
6952
6953   // is inline assembly label?
6954   if (isPCAD(pc) && PCAD(pc)->directive == NULL && PCAD(pc)->arg) {
6955     // do not compare trailing ':'
6956     if (strncmp (PCAD(pc)->arg, label, strlen (label)) == 0) {
6957       return 1;
6958     }
6959   } // if
6960   
6961   // is pCodeLabel?
6962   if (isPCL(pc)) {
6963       if (strcmp(PCL(pc)->label,label) == 0) {
6964       return 1;
6965     }
6966   } // if
6967   
6968   // no label/no label attached/wrong label(s)
6969   return 0;
6970 }
6971
6972 /* Returns the distance to the given label in terms of words.
6973  * Labels are searched only within -max .. max words from pc.
6974  * Returns max if the label could not be found or
6975  * its distance from pc in (-max..+max).
6976  */
6977 int findpCodeLabel (pCode *pc, char *label, int max, pCode **target) {
6978   int dist = instrSize(pc);
6979   pCode *curr = pc;
6980
6981   // search backwards
6982   while (dist < max && curr && !isLabel (curr, label)) {
6983     curr = curr->prev;
6984     dist += instrSize(curr); // sizeof (instruction)
6985   } // while
6986   if (curr && dist < max) {
6987     if (target != NULL) *target = curr;
6988     return -dist;
6989   }
6990
6991   dist = 0;
6992   curr = pic16_findNextInstruction (pc->next);
6993   //search forwards
6994   while (dist < max && curr && !isLabel (curr, label)) {
6995     dist += instrSize(curr); // sizeof (instruction)
6996     curr = curr->next;
6997   } // while
6998   if (curr && dist < max) {
6999     if (target != NULL) *target = curr;
7000     return dist;
7001   }
7002
7003   if (target != NULL) *target = NULL;
7004   return max;
7005 }
7006
7007 /* Returns -1 if pc does NOT denote an instruction like
7008  * BTFS[SC] STATUS,i
7009  * Otherwise we return 
7010  *   (a) 0x10 + i for BTFSS
7011  *   (b) 0x00 + i for BTFSC
7012  */
7013 int isSkipOnStatus (pCode *pc)
7014 {
7015   int res = -1;
7016   pCodeOp *pcop;
7017   if (!pc || !isPCI(pc)) return -1;
7018   if (PCI(pc)->op == POC_BTFSS) res = 0x10;
7019   else if (PCI(pc)->op == POC_BTFSC) res = 0x00;
7020   else return -1;
7021
7022   pcop = PCI(pc)->pcop;
7023
7024   if (pcop->type == PO_STATUS || (pcop->type == PO_GPR_BIT && strcmp(pcop->name, "STATUS") == 0)) {
7025     return res + ((pCodeOpRegBit *)pcop)->bit;
7026   }
7027
7028   return -1;
7029 }
7030
7031 /* Returns 1 if pc is one of BC, BZ, BOV, BN, BNC, BNZ, BNOV or BNN,
7032  * returns 0 otherwise. */
7033 int isConditionalBranch (pCode *pc)
7034 {
7035   if (!pc || !isPCI_BRANCH(pc)) return 0;
7036
7037   switch (PCI(pc)->op) {
7038   case POC_BC:
7039   case POC_BZ:
7040   case POC_BOV:
7041   case POC_BN:
7042   case POC_BNC:
7043   case POC_BNZ:
7044   case POC_BNOV:
7045   case POC_BNN:
7046     return 1;
7047
7048   default:
7049     break;
7050   } // switch
7051
7052   return 0;
7053 }
7054
7055 /* Returns 1 if pc has a label attached to it.
7056  * This can be either a label stored in the pCode itself (.label)
7057  * or a label making up its own pCode preceding this pc.
7058  * Returns 0 if pc cannot be reached directly via a label.
7059  */
7060 int hasNoLabel (pCode *pc)
7061 {
7062   pCode *prev;
7063   if (!pc) return 1;
7064
7065   // are there any label pCodes between pc and the previous instruction?
7066   prev = pic16_findPrevInstruction (pc->prev);
7067   while (pc && pc != prev) {
7068     // pCode with attached label?
7069     if ((isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO)
7070         && PCI(pc)->label) {
7071       return 0;
7072     }
7073     // is inline assembly label?
7074     if (isPCAD(pc) && PCAD(pc)->directive == NULL) return 0;
7075     if (isPCW(pc) && PCW(pc)->label) return 0;
7076
7077     // pCodeLabel?
7078     if (isPCL(pc)) return 0;
7079
7080     pc = pc->prev;
7081   } // if
7082
7083   // no label found
7084   return 1;
7085 }
7086
7087 /* Replaces the old pCode with the new one, moving the labels,
7088  * C source line and probably flow information to the new pCode.
7089  */
7090 void pic16_pCodeReplace (pCode *oldPC, pCode *newPC) {
7091   if (!oldPC || !newPC || !isPCI(oldPC) || !isPCI(newPC))
7092     return;
7093
7094   /* first move all labels from old to new */
7095   PCI(newPC)->label = pic16_pBranchAppend (PCI(oldPC)->label, PCI(newPC)->label);
7096   PCI(oldPC)->label = NULL;
7097   
7098   /* move C source line (if possible) */
7099   if (PCI(oldPC)->cline && !PCI(newPC)->cline)
7100     PCI(newPC)->cline = PCI(oldPC)->cline;
7101
7102   /* insert new pCode into pBlock */
7103   pic16_pCodeInsertAfter (oldPC, newPC);
7104   pic16_unlinkpCode (oldPC);
7105   
7106   /* TODO: update flow (newPC->from, newPC->to) */
7107   PCI(newPC)->pcflow = PCI(oldPC)->pcflow;
7108
7109   /* destruct replaced pCode */
7110   oldPC->destruct (oldPC);
7111 }
7112
7113 /* Returns the inverted conditional branch (if any) or NULL.
7114  * pcop must be set to the new jump target.
7115  */
7116 pCode *getNegatedBcc (pCode *bcc, pCodeOp *pcop)
7117 {
7118   pCode *newBcc;
7119
7120   if (!bcc || !isPCI(bcc)) return NULL;
7121
7122   switch (PCI(bcc)->op) {
7123   case POC_BC:   newBcc = pic16_newpCode (POC_BNC , pcop); break;
7124   case POC_BZ:   newBcc = pic16_newpCode (POC_BNZ , pcop); break;
7125   case POC_BOV:  newBcc = pic16_newpCode (POC_BNOV, pcop); break;
7126   case POC_BN:   newBcc = pic16_newpCode (POC_BNN , pcop); break;
7127   case POC_BNC:  newBcc = pic16_newpCode (POC_BC  , pcop); break;
7128   case POC_BNZ:  newBcc = pic16_newpCode (POC_BZ  , pcop); break;
7129   case POC_BNOV: newBcc = pic16_newpCode (POC_BOV , pcop); break;
7130   case POC_BNN:  newBcc = pic16_newpCode (POC_BN  , pcop); break;
7131   default:
7132     newBcc = NULL;
7133   }
7134   return newBcc;
7135 }
7136
7137 #define MAX_DIST_GOTO         0x7FFFFFFF
7138 #define MAX_DIST_BRA                1020        // maximum offset (in bytes) possible with BRA
7139 #define MAX_DIST_BCC                 120        // maximum offset (in bytes) possible with Bcc
7140 #define MAX_JUMPCHAIN_DEPTH           16        // number of GOTOs to follow in resolveJumpChain() (to prevent endless loops)
7141 #define IS_GOTO(arg) ((arg) && isPCI(arg) && (PCI(arg)->op == POC_GOTO || PCI(arg)->op == POC_BRA))
7142
7143 /* Follows GOTO/BRA instructions to their target instructions, stores the
7144  * final destination (not a GOTO or BRA instruction) in target and returns
7145  * the distance from the original pc to *target.
7146  */
7147 int resolveJumpChain (pCode *pc, pCode **target, pCodeOp **pcop) {
7148         pCode *curr = pc;
7149         pCode *last = NULL;
7150         pCodeOp *lastPCOP = NULL;
7151         int dist = 0;
7152         int depth = 0;
7153
7154         //fprintf (stderr, "%s:%d: -=-", __FUNCTION__, __LINE__);
7155
7156         /* only follow unconditional branches, except for the initial pCode (which may be a conditional branch) */
7157         while (curr && (last != curr) && (depth++ < MAX_JUMPCHAIN_DEPTH) && isPCI(curr)
7158                         && (PCI(curr)->op == POC_GOTO || PCI(curr)->op == POC_BRA || (curr == pc && isConditionalBranch(curr)))) {
7159                 last = curr;
7160                 lastPCOP = PCI(curr)->pcop;
7161                 dist = findpCodeLabel (pc, PCI(curr)->pcop->name, MAX_DIST_GOTO, &curr);
7162                 //fprintf (stderr, "last:%p, curr:%p, label:%s\n", last, curr, PCI(last)->pcop->name);
7163         } // while
7164
7165         if (target) *target = last;
7166         if (pcop) *pcop = lastPCOP;
7167         return dist;
7168 }
7169
7170 /* Returns pc if it is not a OPT_JUMPTABLE_BEGIN INFO pCode.
7171  * Otherwise the first pCode after the jumptable (after
7172  * the OPT_JUMPTABLE_END tag) is returned.
7173  */
7174 pCode *skipJumptables (pCode *pc, int *isJumptable)
7175 {
7176   *isJumptable = 0;
7177   if (!pc) return NULL;
7178   
7179   while (pc->type == PC_INFO && PCINF(pc)->type == INF_OPTIMIZATION && PCOO(PCINF(pc)->oper1)->type == OPT_JUMPTABLE_BEGIN) {
7180     *isJumptable = 1;
7181     //fprintf (stderr, "SKIPPING jumptable\n");
7182     do {
7183       //pc->print(stderr, pc);
7184       pc = pc->next;
7185     } while (pc && (pc->type != PC_INFO || PCINF(pc)->type != INF_OPTIMIZATION
7186                     || PCOO(PCINF(pc)->oper1)->type != OPT_JUMPTABLE_END));
7187     //fprintf (stderr, "<<JUMPTAB:\n");
7188     // skip OPT_END as well
7189     if (pc) pc = pc->next;
7190   } // while
7191
7192   return pc;
7193 }
7194
7195 pCode *pic16_findNextInstructionSkipJumptables (pCode *pc, int *isJumptable)
7196 {
7197   int isJumptab;
7198   *isJumptable = 0;
7199   while (pc && !isPCI(pc) && !isPCAD(pc) && !isPCW(pc)) {
7200     // set pc to the first pCode after a jumptable, leave pc untouched otherwise
7201     pc = skipJumptables (pc, &isJumptab);
7202     if (isJumptab) {
7203         // pc is the first pCode after the jumptable
7204         *isJumptable = 1;
7205     } else {
7206         // pc has not been changed by skipJumptables()
7207         pc = pc->next;
7208     }
7209   } // while
7210   
7211   return pc;
7212 }
7213
7214 /* Turn GOTOs into BRAs if distance between GOTO and label
7215  * is less than 1024 bytes.
7216  *
7217  * This method is especially useful if GOTOs after BTFS[SC]
7218  * can be turned into BRAs as GOTO would cost another NOP
7219  * if skipped.
7220  */
7221 void pic16_OptimizeJumps ()
7222 {
7223   pCode *pc;
7224   pCode *pc_prev = NULL;
7225   pCode *pc_next = NULL;
7226   pBlock *pb;
7227   pCode *target;
7228   int change, iteration, isJumptab;
7229   int isHandled = 0;
7230   char *label;
7231   int opt=0, toofar=0, opt_cond = 0, cond_toofar=0, opt_reorder = 0, opt_gotonext = 0, opt_gotochain = 0;
7232   
7233   if (!the_pFile) return;
7234   
7235   //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__);
7236   
7237   for (pb = the_pFile->pbHead; pb != NULL; pb = pb->next) {
7238     int matchedInvertRule = 1;
7239     iteration = 1;
7240     do {
7241       //fprintf (stderr, "%s:%d: iterating over pBlock %p\n", __FUNCTION__, __LINE__, pb);
7242       change = 0;
7243       pc = pic16_findNextInstruction (pb->pcHead);
7244     
7245       while (pc) {
7246         pc_next = pic16_findNextInstructionSkipJumptables (pc->next, &isJumptab);
7247         if (isJumptab) {
7248                 // skip jumptable, i.e. start over with no pc_prev!     
7249                 pc_prev = NULL;
7250                 pc = pc_next;
7251                 continue;
7252         } // if
7253
7254         /* (1) resolve chained jumps
7255          * Do not perform this until pattern (4) is no longer present! Otherwise we will
7256          * (a) leave dead code in and
7257          * (b) skip over the dead code with an (unneccessary) jump.
7258          */
7259         if (!matchedInvertRule && (IS_GOTO(pc) || isConditionalBranch(pc))) {
7260           pCodeOp *lastTargetOp = NULL;
7261           int newDist = resolveJumpChain (pc, &target, &lastTargetOp);
7262           int maxDist = MAX_DIST_BCC;
7263           if (PCI(pc)->op == POC_BRA) maxDist = MAX_DIST_BRA;
7264           if (PCI(pc)->op == POC_GOTO) maxDist = MAX_DIST_GOTO;
7265           
7266           /* be careful NOT to make the jump instruction longer (might break previously shortened jumps!) */
7267           if (lastTargetOp && newDist <= maxDist && lastTargetOp != PCI(pc)->pcop
7268               && strcmp (lastTargetOp->name, PCI(pc)->pcop->name) != 0) {
7269             //fprintf (stderr, "(1) ");pc->print(stderr, pc); fprintf (stderr, " --> %s\n", lastTargetOp->name);
7270             if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(1) jump chain resolved")); }
7271             PCI(pc)->pcop->name = lastTargetOp->name;
7272             change++;
7273             opt_gotochain++;
7274           } // if
7275         } // if
7276
7277
7278         if (IS_GOTO(pc)) {
7279           int dist;
7280           int condBraType = isSkipOnStatus(pc_prev);
7281           label = PCI(pc)->pcop->name;
7282           dist = findpCodeLabel(pc, label, MAX_DIST_BRA, &target);
7283           if (dist < 0) dist = -dist;
7284           //fprintf (stderr, "distance: %d (", dist); pc->print(stderr, pc);fprintf (stderr, ")\n");
7285           isHandled = 0;
7286           
7287           
7288           /* (2) remove "GOTO label; label:" */
7289           if (isLabel (pc_next, label)) {
7290             //fprintf (stderr, "(2) GOTO next instruction: ");pc->print(stderr, pc);fprintf (stderr, " --> ");pc_next->print(stderr, pc_next); fprintf(stderr, "\n");
7291             // first remove all preceeding SKIP instructions
7292             while (pc_prev && isPCI_SKIP(pc_prev)) {
7293               // attach labels on this instruction to pc_next
7294               //fprintf (stderr, "(2) preceeding SKIP removed: ");pc_prev->print(stderr, pc_prev);fprintf(stderr, "\n");
7295               PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc_prev)->label, PCI(pc_next)->label);
7296               PCI(pc_prev)->label = NULL;
7297               if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(2) SKIP removed")); }
7298               pic16_unlinkpCode (pc_prev);
7299               pc_prev = pic16_findPrevInstruction (pc);
7300             } // while
7301             // now remove the redundant goto itself
7302             PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc)->label, PCI(pc_next)->label);
7303             if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc, pic16_newpCodeCharP("(2) GOTO next instruction removed")); }
7304             pic16_unlinkpCode (pc);
7305             pc = pic16_findPrevInstruction(pc_next->prev);
7306             isHandled = 1; // do not perform further optimizations
7307             opt_gotonext++;
7308             change++;
7309           } // if
7310           
7311           
7312           /* (3) turn BTFSx STATUS,i; GOTO label into Bcc label if possible */
7313           if (!isHandled && condBraType != -1 && hasNoLabel(pc)) {
7314             if (dist < MAX_DIST_BCC) {
7315               pCode *bcc = NULL;
7316               switch (condBraType) {
7317               case 0x00: bcc = pic16_newpCode (POC_BC, PCI(pc)->pcop);break;
7318                 // no BDC on DIGIT CARRY available
7319               case 0x02: bcc = pic16_newpCode (POC_BZ, PCI(pc)->pcop);break;
7320               case 0x03: bcc = pic16_newpCode (POC_BOV, PCI(pc)->pcop);break;
7321               case 0x04: bcc = pic16_newpCode (POC_BN, PCI(pc)->pcop);break;
7322               case 0x10: bcc = pic16_newpCode (POC_BNC, PCI(pc)->pcop);break;
7323                 // no BNDC on DIGIT CARRY available
7324               case 0x12: bcc = pic16_newpCode (POC_BNZ, PCI(pc)->pcop);break;
7325               case 0x13: bcc = pic16_newpCode (POC_BNOV, PCI(pc)->pcop);break;
7326               case 0x14: bcc = pic16_newpCode (POC_BNN, PCI(pc)->pcop);break;
7327               default:
7328                 // no replacement possible
7329                 bcc = NULL;
7330                 break;
7331               } // switch
7332               if (bcc) {
7333                 // ATTENTION: keep labels attached to BTFSx!
7334                 // HINT: GOTO is label free (checked above)
7335                 //fprintf (stderr, "%s:%d: (3) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(bcc)->mnemonic, label);
7336                 isHandled = 1; // do not perform further optimizations
7337                 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(3) conditional branch introduced")); }
7338                 pic16_pCodeReplace (pc_prev, bcc);
7339                 pc->destruct(pc);
7340                 pc = bcc;
7341                 opt_cond++;
7342                 change++;
7343               } // if
7344             } else {
7345               //fprintf (stderr, "(%d, too far for Bcc)\n", dist);
7346               cond_toofar++;
7347             } // if
7348           } // if
7349
7350           if (!isHandled) {
7351             // (4) eliminate the following (common) tripel:
7352             //           <pred.>;
7353             //  labels1: Bcc label2;
7354             //           GOTO somewhere;    ; <-- instruction referenced by pc
7355             //  label2:  <cont.>
7356             // and replace it by
7357             //  labels1: B#(cc) somewhere;  ; #(cc) is the negated condition cc
7358             //  label2:  <cont.>
7359             // ATTENTION: all labels pointing to "Bcc label2" must be attached
7360             //            to <cont.> instead
7361             // ATTENTION: This optimization is only valid if <pred.> is
7362             //            not a skip operation!
7363             // ATTENTION: somewhere must be within MAX_DIST_BCC bytes!
7364             // ATTENTION: no label may be attached to the GOTO instruction!
7365             if (isConditionalBranch(pc_prev)
7366                 && (!isPCI_SKIP(pic16_findPrevInstruction(pc_prev->prev)))
7367                 && (dist < MAX_DIST_BCC)
7368                 && isLabel(pc_next,PCI(pc_prev)->pcop->name)
7369                 && hasNoLabel(pc)) {
7370               pCode *newBcc = getNegatedBcc (pc_prev, PCI(pc)->pcop);
7371             
7372               if (newBcc) {
7373                 //fprintf (stderr, "%s:%d: (4) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBcc)->mnemonic, label);
7374                 isHandled = 1; // do not perform further optimizations
7375                 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(4) conditional skipping branch inverted")); }
7376                 pic16_pCodeReplace (pc_prev, newBcc);
7377                 pc->destruct(pc);
7378                 pc = newBcc;
7379                 opt_reorder++;
7380                 change++;
7381                 matchedInvertRule++;
7382               }
7383             }
7384           }
7385           
7386           /* (5) now just turn GOTO into BRA */ 
7387           if (!isHandled && (PCI(pc)->op == POC_GOTO)) {
7388             if (dist < MAX_DIST_BRA) {
7389               pCode *newBra = pic16_newpCode (POC_BRA, PCI(pc)->pcop);
7390               //fprintf (stderr, "%s:%d: (5) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBra)->mnemonic, label);
7391               if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc->prev, pic16_newpCodeCharP("(5) GOTO replaced by BRA")); }
7392               pic16_pCodeReplace (pc, newBra);
7393               pc = newBra;
7394               opt++;
7395               change++;
7396             } else {
7397               //fprintf (stderr, "(%d, too far for BRA)\n", dist);
7398               toofar++;
7399             }
7400           } // if (!isHandled)
7401         } // if
7402
7403         pc_prev = pc;
7404         pc = pc_next;
7405       } // while (pc)
7406       
7407       pBlockRemoveUnusedLabels (pb);
7408       
7409       // This line enables goto chain resolution!
7410       if (matchedInvertRule > 1) matchedInvertRule = 1; else matchedInvertRule = 0;
7411
7412       iteration++;
7413     } while (change); /* fixpoint iteration per pBlock */
7414   } // for (pb)
7415   
7416   // emit some statistics concerning goto-optimization
7417 #if 0
7418   if (pic16_debug_verbose || pic16_pcode_verbose) {
7419     fprintf (stderr, "optimize-goto:\n"
7420              "\t%5d GOTO->BRA; (%d GOTOs too far)\n"
7421              "\t%5d BTFSx, GOTO->Bcc (%d too far)\n"
7422              "\t%5d conditional \"skipping\" jumps inverted\n"
7423              "\t%5d GOTOs to next instruction removed\n"
7424              "\t%5d chained GOTOs resolved\n",
7425              opt, toofar, opt_cond, cond_toofar, opt_reorder, opt_gotonext, opt_gotochain);
7426   } // if
7427 #endif
7428   //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__);
7429 }
7430
7431 #undef IS_GOTO
7432 #undef MAX_JUMPCHAIN_DEPTH
7433 #undef MAX_DIST_GOTO
7434 #undef MAX_DIST_BRA
7435 #undef MAX_DIST_BCC
7436
7437 /** END OF RAPHAEL NEIDER'S ADDITIONS **/
7438
7439 static void pBlockDestruct(pBlock *pb)
7440 {
7441
7442   if(!pb)
7443     return;
7444
7445
7446 //  Safe_free(pb);
7447
7448 }
7449
7450 /*-----------------------------------------------------------------*/
7451 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
7452 /*                                  name dbName and combine them   */
7453 /*                                  into one block                 */
7454 /*-----------------------------------------------------------------*/
7455 static void mergepBlocks(char dbName)
7456 {
7457
7458   pBlock *pb, *pbmerged = NULL,*pbn;
7459
7460   pb = the_pFile->pbHead;
7461
7462   //fprintf(stderr," merging blocks named %c\n",dbName);
7463   while(pb) {
7464
7465     pbn = pb->next;
7466     //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
7467     if( getpBlock_dbName(pb) == dbName) {
7468
7469       //fprintf(stderr," merged block %c\n",dbName);
7470
7471       if(!pbmerged) {
7472         pbmerged = pb;
7473       } else {
7474         pic16_addpCode2pBlock(pbmerged, pb->pcHead);
7475         /* pic16_addpCode2pBlock doesn't handle the tail: */
7476         pbmerged->pcTail = pb->pcTail;
7477
7478         pb->prev->next = pbn;
7479         if(pbn) 
7480           pbn->prev = pb->prev;
7481
7482
7483         pBlockDestruct(pb);
7484       }
7485       //pic16_printpBlock(stderr, pbmerged);
7486     } 
7487     pb = pbn;
7488   }
7489
7490 }
7491
7492 /*-----------------------------------------------------------------*/
7493 /* AnalyzeFlow - Examine the flow of the code and optimize         */
7494 /*                                                                 */
7495 /* level 0 == minimal optimization                                 */
7496 /*   optimize registers that are used only by two instructions     */
7497 /* level 1 == maximal optimization                                 */
7498 /*   optimize by looking at pairs of instructions that use the     */
7499 /*   register.                                                     */
7500 /*-----------------------------------------------------------------*/
7501
7502 static void AnalyzeFlow(int level)
7503 {
7504   static int times_called=0;
7505   pBlock *pb;
7506
7507         if(!the_pFile) {
7508
7509                 /* remove unused allocated registers before exiting */
7510                 pic16_RemoveUnusedRegisters();
7511         
7512           return;
7513         }
7514
7515
7516   /* if this is not the first time this function has been called,
7517      then clean up old flow information */
7518         if(times_called++) {
7519                 for(pb = the_pFile->pbHead; pb; pb = pb->next)
7520                         unBuildFlow(pb);
7521
7522                 pic16_RegsUnMapLiveRanges();
7523         }
7524
7525         GpcFlowSeq = 1;
7526
7527   /* Phase 2 - Flow Analysis - Register Banking
7528    *
7529    * In this phase, the individual flow blocks are examined
7530    * and register banking is fixed.
7531    */
7532
7533 #if 0
7534         for(pb = the_pFile->pbHead; pb; pb = pb->next)
7535                 pic16_FixRegisterBanking(pb);
7536 #endif
7537
7538   /* Phase 2 - Flow Analysis
7539    *
7540    * In this phase, the pCode is partition into pCodeFlow 
7541    * blocks. The flow blocks mark the points where a continuous
7542    * stream of instructions changes flow (e.g. because of
7543    * a call or goto or whatever).
7544    */
7545
7546         for(pb = the_pFile->pbHead; pb; pb = pb->next)
7547                 pic16_BuildFlow(pb);
7548
7549
7550   /* Phase 2 - Flow Analysis - linking flow blocks
7551    *
7552    * In this phase, the individual flow blocks are examined
7553    * to determine their order of excution.
7554    */
7555
7556         for(pb = the_pFile->pbHead; pb; pb = pb->next)
7557                 LinkFlow(pb);
7558
7559   /* Phase 3 - Flow Analysis - Flow Tree
7560    *
7561    * In this phase, the individual flow blocks are examined
7562    * to determine their order of execution.
7563    */
7564
7565         for(pb = the_pFile->pbHead; pb; pb = pb->next)
7566                 pic16_BuildFlowTree(pb);
7567
7568
7569   /* Phase x - Flow Analysis - Used Banks
7570    *
7571    * In this phase, the individual flow blocks are examined
7572    * to determine the Register Banks they use
7573    */
7574
7575 #if 0
7576         for(pb = the_pFile->pbHead; pb; pb = pb->next)
7577                 FixBankFlow(pb);
7578 #endif
7579
7580
7581         for(pb = the_pFile->pbHead; pb; pb = pb->next)
7582                 pic16_pCodeRegMapLiveRanges(pb);
7583
7584         pic16_RemoveUnusedRegisters();
7585
7586   //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
7587         pic16_pCodeRegOptimizeRegUsage(level);
7588
7589
7590         if(!options.nopeep)
7591                 OptimizepCode('*');
7592
7593
7594 #if 0
7595         for(pb = the_pFile->pbHead; pb; pb = pb->next)
7596                 DumpFlow(pb);
7597 #endif
7598
7599   /* debug stuff */ 
7600         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7601           pCode *pcflow;
7602                 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
7603                         (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7604                         pcflow = pcflow->next) {
7605
7606                         FillFlow(PCFL(pcflow));
7607                 }
7608         }
7609
7610 #if 0
7611         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7612           pCode *pcflow;
7613
7614                 for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
7615                         (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7616                         pcflow = pcflow->next) {
7617
7618                         FlowStats(PCFL(pcflow));
7619                 }
7620         }
7621 #endif
7622 }
7623
7624 /* VR -- no need to analyze banking in flow, but left here :
7625  *      1. because it may be used in the future for other purposes
7626  *      2. because if omitted we'll miss some optimization done here
7627  *
7628  * Perhaps I should rename it to something else
7629  */
7630
7631 /*-----------------------------------------------------------------*/
7632 /* pic16_AnalyzeBanking - Called after the memory addresses have been    */
7633 /*                  assigned to the registers.                     */
7634 /*                                                                 */
7635 /*-----------------------------------------------------------------*/
7636
7637 void pic16_AnalyzeBanking(void)
7638 {
7639   pBlock  *pb;
7640
7641
7642         /* Phase x - Flow Analysis - Used Banks
7643          *
7644          * In this phase, the individual flow blocks are examined
7645          * to determine the Register Banks they use
7646          */
7647
7648         AnalyzeFlow(0);
7649         AnalyzeFlow(1);
7650
7651         if(!the_pFile)return;
7652
7653         if(!pic16_options.no_banksel) {
7654                 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7655 //                      fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
7656                         pic16_FixRegisterBanking(pb);
7657                 }
7658         }
7659
7660 }
7661
7662 /*-----------------------------------------------------------------*/
7663 /* buildCallTree - Look at the flow and extract all of the calls.  */
7664 /*-----------------------------------------------------------------*/
7665 static set *register_usage(pBlock *pb);
7666
7667 static void buildCallTree(void    )
7668 {
7669   pBranch *pbr;
7670   pBlock  *pb;
7671   pCode   *pc;
7672   regs *r;
7673   
7674   if(!the_pFile)
7675     return;
7676
7677
7678
7679   /* Now build the call tree.
7680      First we examine all of the pCodes for functions.
7681      Keep in mind that the function boundaries coincide
7682      with pBlock boundaries. 
7683
7684      The algorithm goes something like this:
7685      We have two nested loops. The outer loop iterates
7686      through all of the pBlocks/functions. The inner
7687      loop iterates through all of the pCodes for
7688      a given pBlock. When we begin iterating through
7689      a pBlock, the variable pc_fstart, pCode of the start
7690      of a function, is cleared. We then search for pCodes
7691      of type PC_FUNCTION. When one is encountered, we
7692      initialize pc_fstart to this and at the same time
7693      associate a new pBranch object that signifies a 
7694      branch entry. If a return is found, then this signifies
7695      a function exit point. We'll link the pCodes of these
7696      returns to the matching pc_fstart.
7697
7698      When we're done, a doubly linked list of pBranches
7699      will exist. The head of this list is stored in
7700      `the_pFile', which is the meta structure for all
7701      of the pCode. Look at the pic16_printCallTree function
7702      on how the pBranches are linked together.
7703
7704    */
7705   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7706     pCode *pc_fstart=NULL;
7707     for(pc = pb->pcHead; pc; pc = pc->next) {
7708
7709         if(isPCI(pc) && pc_fstart) {
7710                 if(PCI(pc)->is2MemOp) {
7711                         r = pic16_getRegFromInstruction2(pc);
7712                         if(r && !strcmp(r->name, "POSTDEC1"))
7713                                 PCF(pc_fstart)->stackusage++;
7714                 } else {
7715                         r = pic16_getRegFromInstruction(pc);
7716                         if(r && !strcmp(r->name, "PREINC1"))
7717                                 PCF(pc_fstart)->stackusage--;
7718                 }
7719         }
7720
7721       if(isPCF(pc)) {
7722         if (PCF(pc)->fname) {
7723
7724           if(STRCASECMP(PCF(pc)->fname, "_main") == 0) {
7725             //fprintf(stderr," found main \n");
7726             pb->cmemmap = NULL;  /* FIXME do we need to free ? */
7727             pb->dbName = 'M';
7728           }
7729
7730           pbr = Safe_calloc(1,sizeof(pBranch));
7731           pbr->pc = pc_fstart = pc;
7732           pbr->next = NULL;
7733
7734           the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
7735
7736           // Here's a better way of doing the same:
7737           addSet(&pb->function_entries, pc);
7738
7739         } else {
7740           // Found an exit point in a function, e.g. return
7741           // (Note, there may be more than one return per function)
7742           if(pc_fstart)
7743             pBranchLink(PCF(pc_fstart), PCF(pc));
7744
7745           addSet(&pb->function_exits, pc);
7746         }
7747       } else if(isCALL(pc)) {
7748         addSet(&pb->function_calls,pc);
7749       }
7750     }
7751   }
7752
7753
7754 #if 0
7755   /* This is not needed because currently all register used
7756    * by a function are stored in stack -- VR */
7757    
7758   /* Re-allocate the registers so that there are no collisions
7759    * between local variables when one function call another */
7760
7761   // this is weird...
7762   //  pic16_deallocateAllRegs();
7763
7764   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7765     if(!pb->visited)
7766       register_usage(pb);
7767   }
7768 #endif
7769
7770 }
7771
7772 /*-----------------------------------------------------------------*/
7773 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
7774 /*                all of the logical connections.                  */
7775 /*                                                                 */
7776 /* Essentially what's done here is that the pCode flow is          */
7777 /* determined.                                                     */
7778 /*-----------------------------------------------------------------*/
7779
7780 void pic16_AnalyzepCode(char dbName)
7781 {
7782   pBlock *pb;
7783   int i,changes;
7784
7785   if(!the_pFile)
7786     return;
7787
7788   mergepBlocks('D');
7789
7790
7791   /* Phase 1 - Register allocation and peep hole optimization
7792    *
7793    * The first part of the analysis is to determine the registers
7794    * that are used in the pCode. Once that is done, the peep rules
7795    * are applied to the code. We continue to loop until no more
7796    * peep rule optimizations are found (or until we exceed the
7797    * MAX_PASSES threshold). 
7798    *
7799    * When done, the required registers will be determined.
7800    *
7801    */
7802   i = 0;
7803   do {
7804
7805     DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7806     //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7807
7808     /* First, merge the labels with the instructions */
7809     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7810       if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7811
7812         DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7813         //fprintf(stderr," analyze and merging block %c\n",dbName);
7814         pic16_pBlockMergeLabels(pb);
7815         AnalyzepBlock(pb);
7816       } else {
7817         DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7818       }
7819     }
7820
7821         if(!options.nopeep)
7822                 changes = OptimizepCode(dbName);
7823         else changes = 0;
7824
7825   } while(changes && (i++ < MAX_PASSES));
7826
7827   
7828   buildCallTree();
7829 }
7830
7831
7832 /* convert a series of movff's of local regs to stack, with a single call to
7833  * a support functions which does the same thing via loop */
7834 static void pic16_convertLocalRegs2Support(pCode *pcstart, pCode *pcend, int count, regs *r, int entry)
7835 {
7836   pBranch *pbr;
7837   pCode *pc, *pct;
7838   char *fname[]={"__lr_store", "__lr_restore"};
7839
7840 //    pc = pic16_newpCode(POC_CALL, pic16_popGetFromString( (entry?fname[0]:fname[1]) ));
7841
7842     pct = pic16_findNextInstruction(pcstart->next);
7843     do {
7844       pc = pct;
7845       pct = pc->next;   //pic16_findNextInstruction(pc->next);
7846 //      pc->print(stderr, pc);
7847       if(isPCI(pc) && PCI(pc)->label) {
7848         pbr = PCI(pc)->label;
7849         while(pbr && pbr->pc) {
7850           PCI(pcstart)->label = pic16_pBranchAppend(PCI(pcstart)->label, pbr);
7851           pbr = pbr->next;
7852         }
7853
7854 //        pc->print(stderr, pc);
7855         /* unlink pCode */
7856         pc->prev->next = pct;
7857         pct->prev = pc->prev;
7858 //        pc->next = NULL;
7859 //        pc->prev = NULL;
7860       }
7861     } while ((pc) && (pc != pcend));
7862
7863     /* unlink movff instructions */
7864     pcstart->next = pcend;
7865     pcend->prev = pcstart;
7866
7867     pc = pcstart;
7868 //    if(!entry) {
7869 //      pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
7870 //              pic16_popCopyReg(&pic16_pc_fsr0l), pic16_popCopyReg(pic16_framepnt_lo)))); pc = pct;
7871 //    }
7872                 
7873     pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetWithString(r->name)))); pc = pct;
7874     pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_MOVLW, pic16_popGetLit( count ))); pc = pct;
7875     pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_CALL, pic16_popGetWithString( fname[ (entry==1?0:1) ] ))); pc = pct;
7876
7877 //    if(!entry) {
7878 //      pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
7879 //              pic16_popCopyReg(pic16_framepnt_lo), pic16_popCopyReg(&pic16_pc_fsr0l)))); pc = pct;
7880 //    }
7881
7882     
7883     {
7884       symbol *sym;
7885
7886         sym = newSymbol( fname[ entry?0:1 ], 0 );
7887         strcpy(sym->rname, fname[ entry?0:1 ]);
7888         checkAddSym(&externs, sym);
7889         
7890 //        fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fname[ entry?0:1 ]);
7891     }
7892
7893 }
7894
7895 /*-----------------------------------------------------------------*/
7896 /* OptimizeLocalRegs - turn sequence of MOVFF instructions for     */
7897 /*    local registers to a support function call                   */
7898 /*-----------------------------------------------------------------*/
7899 void pic16_OptimizeLocalRegs(void)
7900 {
7901   pBlock  *pb;
7902   pCode   *pc;
7903   pCodeInfo *pci;
7904   pCodeOpLocalReg *pclr;
7905   int regCount=0;
7906   int inRegCount=0;
7907   regs *r, *lastr=NULL, *firstr=NULL;
7908   pCode *pcstart=NULL, *pcend=NULL;
7909   int inEntry=0;
7910   char *curFunc=NULL;
7911
7912         /* Overview:
7913          *   local_regs begin mark
7914          *      MOVFF r0x01, POSTDEC1
7915          *      MOVFF r0x02, POSTDEC1
7916          *      ...
7917          *      ...
7918          *      MOVFF r0x0n, POSTDEC1
7919          *   local_regs end mark
7920          *
7921          * convert the above to the below:
7922          *      MOVLW   starting_register_index
7923          *      MOVWF   PRODL
7924          *      MOVLW   register_count
7925          *      call    __save_registers_in_stack
7926          */
7927
7928     if(!the_pFile)
7929       return;
7930
7931     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7932       inRegCount = regCount = 0;
7933       firstr = lastr = NULL;
7934       for(pc = pb->pcHead; pc; pc = pc->next) {
7935
7936         /* hold current function name */
7937         if(pc && isPCF(pc))curFunc = PCF(pc)->fname;
7938         
7939         if(pc && (pc->type == PC_INFO)) {
7940           pci = PCINF(pc);
7941
7942           if(pci->type == INF_LOCALREGS) {
7943             pclr = PCOLR(pci->oper1);
7944             
7945             if((pclr->type == LR_ENTRY_BEGIN)
7946               || (pclr->type == LR_ENTRY_END))inEntry = 1;
7947             else inEntry = 0;
7948             
7949             switch(pclr->type) {
7950               case LR_ENTRY_BEGIN:
7951               case LR_EXIT_BEGIN:
7952                         inRegCount = 1; regCount = 0;
7953                         pcstart = pc;   //pic16_findNextInstruction(pc->next);
7954                         firstr = lastr = NULL;
7955                         break;
7956               
7957               case LR_ENTRY_END:
7958               case LR_EXIT_END:
7959                         inRegCount = -1;
7960                         pcend = pc;     //pic16_findPrevInstruction(pc->prev);
7961
7962 #if 1
7963                         if(curFunc && inWparamList(curFunc+1)) {
7964                           fprintf(stderr, "sdcc: %s: warning: disabling lr-support for functionn %s\n",
7965                                         filename, curFunc);
7966                         } else {
7967                           if(regCount>2) {
7968                             pic16_convertLocalRegs2Support(pcstart, pcend, regCount,
7969                               firstr, inEntry);
7970                           }
7971                         }
7972 #endif
7973                         firstr = lastr = NULL;
7974                         break;
7975             }
7976             
7977             if(inRegCount == -1) {
7978 //              fprintf(stderr, "%s:%d registers used [%s] %d\n", __FILE__, __LINE__, inEntry?"entry":"exit", regCount);
7979               regCount = 0;
7980               inRegCount = 0;
7981             }
7982           }
7983         } else {
7984           if(isPCI(pc) && (PCI(pc)->op == POC_MOVFF) && (inRegCount == 1)) {
7985             if(inEntry)
7986               r = pic16_getRegFromInstruction(pc);
7987             else
7988               r = pic16_getRegFromInstruction2(pc);
7989             if(r && (r->type == REG_GPR) && (r->pc_type == PO_GPR_TEMP)) {
7990               if(!firstr)firstr = r;
7991               regCount++;
7992 //              fprintf(stderr, "%s:%d\t%s\t%i\t%d/%d\n", __FILE__, __LINE__, r->name, r->rIdx);
7993             }
7994           }
7995         }
7996       }
7997     }
7998 }
7999               
8000             
8001
8002
8003
8004 /*-----------------------------------------------------------------*/
8005 /* ispCodeFunction - returns true if *pc is the pCode of a         */
8006 /*                   function                                      */
8007 /*-----------------------------------------------------------------*/
8008 static bool ispCodeFunction(pCode *pc)
8009 {
8010
8011   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
8012     return 1;
8013
8014   return 0;
8015 }
8016
8017 /*-----------------------------------------------------------------*/
8018 /* findFunction - Search for a function by name (given the name)   */
8019 /*                in the set of all functions that are in a pBlock */
8020 /* (note - I expect this to change because I'm planning to limit   */
8021 /*  pBlock's to just one function declaration                      */
8022 /*-----------------------------------------------------------------*/
8023 static pCode *findFunction(char *fname)
8024 {
8025   pBlock *pb;
8026   pCode *pc;
8027   if(!fname)
8028     return NULL;
8029
8030   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8031
8032     pc = setFirstItem(pb->function_entries);
8033     while(pc) {
8034     
8035       if((pc->type == PC_FUNCTION) &&
8036          (PCF(pc)->fname) && 
8037          (strcmp(fname, PCF(pc)->fname)==0))
8038         return pc;
8039
8040       pc = setNextItem(pb->function_entries);
8041
8042     }
8043
8044   }
8045   return NULL;
8046 }
8047
8048 static void MarkUsedRegisters(set *regset)
8049 {
8050
8051   regs *r1,*r2;
8052
8053   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
8054 //      fprintf(stderr, "marking register = %s\t", r1->name);
8055     r2 = pic16_regWithIdx(r1->rIdx);
8056 //      fprintf(stderr, "to register = %s\n", r2->name);
8057     r2->isFree = 0;
8058     r2->wasUsed = 1;
8059   }
8060 }
8061
8062 static void pBlockStats(FILE *of, pBlock *pb)
8063 {
8064
8065   pCode *pc;
8066   regs  *r;
8067
8068         if(!pic16_pcode_verbose)return;
8069         
8070   fprintf(of,";***\n;  pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
8071
8072   // for now just print the first element of each set
8073   pc = setFirstItem(pb->function_entries);
8074   if(pc) {
8075     fprintf(of,";entry:  ");
8076     pc->print(of,pc);
8077   }
8078   pc = setFirstItem(pb->function_exits);
8079   if(pc) {
8080     fprintf(of,";has an exit\n");
8081     //pc->print(of,pc);
8082   }
8083
8084   pc = setFirstItem(pb->function_calls);
8085   if(pc) {
8086     fprintf(of,";functions called:\n");
8087
8088     while(pc) {
8089       if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8090         fprintf(of,";   %s\n",pic16_get_op_from_instruction(PCI(pc)));
8091       }
8092       pc = setNextItem(pb->function_calls);
8093     }
8094   }
8095
8096   r = setFirstItem(pb->tregisters);
8097   if(r) {
8098     int n = elementsInSet(pb->tregisters);
8099
8100     fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
8101
8102     while (r) {
8103       fprintf(of,";   %s\n",r->name);
8104       r = setNextItem(pb->tregisters);
8105     }
8106   }
8107   
8108   fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
8109 }
8110
8111 /*-----------------------------------------------------------------*/
8112 /*-----------------------------------------------------------------*/
8113 #if 0
8114 static void sequencepCode(void)
8115 {
8116   pBlock *pb;
8117   pCode *pc;
8118
8119
8120   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8121
8122     pb->seq = GpCodeSequenceNumber+1;
8123
8124     for( pc = pb->pcHead; pc; pc = pc->next)
8125       pc->seq = ++GpCodeSequenceNumber;
8126   }
8127
8128 }
8129 #endif
8130
8131 /*-----------------------------------------------------------------*/
8132 /*-----------------------------------------------------------------*/
8133 static set *register_usage(pBlock *pb)
8134 {
8135   pCode *pc,*pcn;
8136   set *registers=NULL;
8137   set *registersInCallPath = NULL;
8138
8139   /* check recursion */
8140
8141   pc = setFirstItem(pb->function_entries);
8142
8143   if(!pc)
8144     return registers;
8145
8146   pb->visited = 1;
8147
8148   if(pc->type != PC_FUNCTION)
8149     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
8150
8151   pc = setFirstItem(pb->function_calls);
8152   for( ; pc; pc = setNextItem(pb->function_calls)) {
8153
8154     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8155       char *dest = pic16_get_op_from_instruction(PCI(pc));
8156
8157       pcn = findFunction(dest);
8158       if(pcn) 
8159         registersInCallPath = register_usage(pcn->pb);
8160     } else
8161       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8162
8163   }
8164
8165 #ifdef PCODE_DEBUG
8166   pBlockStats(stderr,pb);  // debug
8167 #endif
8168
8169   // Mark the registers in this block as used.
8170
8171   MarkUsedRegisters(pb->tregisters);
8172   if(registersInCallPath) {
8173     /* registers were used in the functions this pBlock has called */
8174     /* so now, we need to see if these collide with the ones we are */
8175     /* using here */
8176
8177     regs *r1,*r2, *newreg;
8178
8179     DFPRINTF((stderr,"comparing registers\n"));
8180
8181     r1 = setFirstItem(registersInCallPath);
8182     while(r1) {
8183
8184       r2 = setFirstItem(pb->tregisters);
8185
8186       while(r2 && (r1->type != REG_STK)) {
8187
8188         if(r2->rIdx == r1->rIdx) {
8189           newreg = pic16_findFreeReg(REG_GPR);
8190
8191
8192           if(!newreg) {
8193             DFPRINTF((stderr,"Bummer, no more registers.\n"));
8194             exit(1);
8195           }
8196
8197           DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
8198                   r1->rIdx, newreg->rIdx));
8199           r2->rIdx = newreg->rIdx;
8200           //if(r2->name) Safe_free(r2->name);
8201           if(newreg->name)
8202             r2->name = Safe_strdup(newreg->name);
8203           else
8204             r2->name = NULL;
8205           newreg->isFree = 0;
8206           newreg->wasUsed = 1;
8207         }
8208         r2 = setNextItem(pb->tregisters);
8209       }
8210
8211       r1 = setNextItem(registersInCallPath);
8212     }
8213
8214     /* Collisions have been resolved. Now free the registers in the call path */
8215     r1 = setFirstItem(registersInCallPath);
8216     while(r1) {
8217       if(r1->type != REG_STK) {
8218         newreg = pic16_regWithIdx(r1->rIdx);
8219         newreg->isFree = 1;
8220       }
8221       r1 = setNextItem(registersInCallPath);
8222     }
8223
8224   }// else
8225   //    MarkUsedRegisters(pb->registers);
8226
8227   registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
8228 #ifdef PCODE_DEBUG
8229   if(registers) 
8230     DFPRINTF((stderr,"returning regs\n"));
8231   else
8232     DFPRINTF((stderr,"not returning regs\n"));
8233
8234   DFPRINTF((stderr,"pBlock after register optim.\n"));
8235   pBlockStats(stderr,pb);  // debug
8236 #endif
8237
8238   return registers;
8239 }
8240
8241 /*-----------------------------------------------------------------*/
8242 /* pct2 - writes the call tree to a file                           */
8243 /*                                                                 */
8244 /*-----------------------------------------------------------------*/
8245 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
8246 {
8247   pCode *pc,*pcn;
8248   int i;
8249   //  set *registersInCallPath = NULL;
8250
8251   if(!of)
8252     return;
8253
8254   if(indent > 10) {
8255         fprintf(of, "recursive function\n");
8256     return; //recursion ?
8257   }
8258
8259   pc = setFirstItem(pb->function_entries);
8260
8261   if(!pc)
8262     return;
8263
8264   pb->visited = 0;
8265
8266   for(i=0;i<indent;i++)   // Indentation
8267         fputs("+   ", of);
8268   fputs("+- ", of);
8269
8270   if(pc->type == PC_FUNCTION) {
8271     usedstack += PCF(pc)->stackusage;
8272     fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
8273   } else return;  // ???
8274
8275
8276   pc = setFirstItem(pb->function_calls);
8277   for( ; pc; pc = setNextItem(pb->function_calls)) {
8278
8279     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8280       char *dest = pic16_get_op_from_instruction(PCI(pc));
8281
8282       pcn = findFunction(dest);
8283       if(pcn) 
8284         pct2(of,pcn->pb,indent+1, usedstack);   // + PCF(pcn)->stackusage);
8285     } else
8286       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8287
8288   }
8289
8290
8291 }
8292
8293
8294 /*-----------------------------------------------------------------*/
8295 /* pic16_printCallTree - writes the call tree to a file                  */
8296 /*                                                                 */
8297 /*-----------------------------------------------------------------*/
8298
8299 void pic16_printCallTree(FILE *of)
8300 {
8301   pBranch *pbr;
8302   pBlock  *pb;
8303   pCode   *pc;
8304
8305   if(!the_pFile)
8306     return;
8307
8308   if(!of)
8309     of = stderr;
8310
8311   fprintf(of, "\npBlock statistics\n");
8312   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
8313     pBlockStats(of,pb);
8314
8315
8316   fprintf(of,"Call Tree\n");
8317   pbr = the_pFile->functions;
8318   while(pbr) {
8319     if(pbr->pc) {
8320       pc = pbr->pc;
8321       if(!ispCodeFunction(pc))
8322         fprintf(of,"bug in call tree");
8323
8324
8325       fprintf(of,"Function: %s\n", PCF(pc)->fname);
8326
8327       while(pc->next && !ispCodeFunction(pc->next)) {
8328         pc = pc->next;
8329         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
8330           fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
8331       }
8332     }
8333
8334     pbr = pbr->next;
8335   }
8336
8337
8338   fprintf(of,"\n**************\n\na better call tree\n");
8339   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8340 //    if(pb->visited)
8341       pct2(of,pb,0,0);
8342   }
8343
8344   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8345     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
8346   }
8347 }
8348
8349
8350
8351 /*-----------------------------------------------------------------*/
8352 /*                                                                 */
8353 /*-----------------------------------------------------------------*/
8354
8355 static void InlineFunction(pBlock *pb)
8356 {
8357   pCode *pc;
8358   pCode *pc_call;
8359
8360   if(!pb)
8361     return;
8362
8363   pc = setFirstItem(pb->function_calls);
8364
8365   for( ; pc; pc = setNextItem(pb->function_calls)) {
8366
8367     if(isCALL(pc)) {
8368       pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
8369       pCode *pct;
8370       pCode *pce;
8371
8372       pBranch *pbr;
8373
8374       if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) {               /* change 0 to 1 to enable inlining */
8375         
8376         //fprintf(stderr,"Cool can inline:\n");
8377         //pcn->print(stderr,pcn);
8378
8379         //fprintf(stderr,"recursive call Inline\n");
8380         InlineFunction(pcn->pb);
8381         //fprintf(stderr,"return from recursive call Inline\n");
8382
8383         /*
8384           At this point, *pc points to a CALL mnemonic, and
8385           *pcn points to the function that is being called.
8386
8387           To in-line this call, we need to remove the CALL
8388           and RETURN(s), and link the function pCode in with
8389           the CALLee pCode.
8390
8391         */
8392
8393
8394         /* Remove the CALL */
8395         pc_call = pc;
8396         pc = pc->prev;
8397
8398         /* remove callee pBlock from the pBlock linked list */
8399         removepBlock(pcn->pb);
8400
8401         pce = pcn;
8402         while(pce) {
8403           pce->pb = pb;
8404           pce = pce->next;
8405         }
8406
8407         /* Remove the Function pCode */
8408         pct = pic16_findNextInstruction(pcn->next);
8409
8410         /* Link the function with the callee */
8411         pc->next = pcn->next;
8412         pcn->next->prev = pc;
8413         
8414         /* Convert the function name into a label */
8415
8416         pbr = Safe_calloc(1,sizeof(pBranch));
8417         pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
8418         pbr->next = NULL;
8419         PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
8420         PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
8421
8422         /* turn all of the return's except the last into goto's */
8423         /* check case for 2 instruction pBlocks */
8424         pce = pic16_findNextInstruction(pcn->next);
8425         while(pce) {
8426           pCode *pce_next = pic16_findNextInstruction(pce->next);
8427
8428           if(pce_next == NULL) {
8429             /* found the last return */
8430             pCode *pc_call_next =  pic16_findNextInstruction(pc_call->next);
8431
8432             //fprintf(stderr,"found last return\n");
8433             //pce->print(stderr,pce);
8434             pce->prev->next = pc_call->next;
8435             pc_call->next->prev = pce->prev;
8436             PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
8437                                                       PCI(pce)->label);
8438           }
8439
8440           pce = pce_next;
8441         }
8442
8443
8444       }
8445     } else
8446       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8447
8448   }
8449
8450 }
8451
8452 /*-----------------------------------------------------------------*/
8453 /*                                                                 */
8454 /*-----------------------------------------------------------------*/
8455
8456 void pic16_InlinepCode(void)
8457 {
8458
8459   pBlock  *pb;
8460   pCode   *pc;
8461
8462   if(!the_pFile)
8463     return;
8464
8465   if(!functionInlining)
8466     return;
8467
8468   /* Loop through all of the function definitions and count the
8469    * number of times each one is called */
8470   //fprintf(stderr,"inlining %d\n",__LINE__);
8471
8472   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8473
8474     pc = setFirstItem(pb->function_calls);
8475
8476     for( ; pc; pc = setNextItem(pb->function_calls)) {
8477
8478       if(isCALL(pc)) {
8479         pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
8480         if(pcn && isPCF(pcn)) {
8481           PCF(pcn)->ncalled++;
8482         }
8483       } else
8484         fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8485
8486     }
8487   }
8488
8489   //fprintf(stderr,"inlining %d\n",__LINE__);
8490
8491   /* Now, Loop through the function definitions again, but this
8492    * time inline those functions that have only been called once. */
8493   
8494   InlineFunction(the_pFile->pbHead);
8495   //fprintf(stderr,"inlining %d\n",__LINE__);
8496
8497   for(pb = the_pFile->pbHead; pb; pb = pb->next)
8498     unBuildFlow(pb);
8499
8500 }
8501
8502 char *pic_optype_names[]={
8503         "PO_NONE",         // No operand e.g. NOP
8504         "PO_W",              // The working register (as a destination)
8505         "PO_WREG",           // The working register (as a file register)
8506         "PO_STATUS",         // The 'STATUS' register
8507         "PO_BSR",            // The 'BSR' register
8508         "PO_FSR0",           // The "file select register" (in PIC18 family it's one 
8509                              // of three)
8510         "PO_INDF0",          // The Indirect register
8511         "PO_INTCON",         // Interrupt Control register
8512         "PO_GPR_REGISTER",   // A general purpose register
8513         "PO_GPR_BIT",        // A bit of a general purpose register
8514         "PO_GPR_TEMP",       // A general purpose temporary register
8515         "PO_SFR_REGISTER",   // A special function register (e.g. PORTA)
8516         "PO_PCL",            // Program counter Low register
8517         "PO_PCLATH",         // Program counter Latch high register
8518         "PO_PCLATU",         // Program counter Latch upper register
8519         "PO_PRODL",          // Product Register Low
8520         "PO_PRODH",          // Product Register High
8521         "PO_LITERAL",        // A constant
8522         "PO_REL_ADDR",       // A relative address
8523         "PO_IMMEDIATE",      //  (8051 legacy)
8524         "PO_DIR",            // Direct memory (8051 legacy)
8525         "PO_CRY",            // bit memory (8051 legacy)
8526         "PO_BIT",            // bit operand.
8527         "PO_STR",            //  (8051 legacy)
8528         "PO_LABEL",
8529         "PO_WILD"            // Wild card operand in peep optimizer
8530 };
8531
8532
8533 char *dumpPicOptype(PIC_OPTYPE type)
8534 {
8535         return (pic_optype_names[ type ]);
8536 }
8537
8538
8539 /*** BEGIN of stuff belonging to the BANKSEL optimization ***/
8540 #include "graph.h"
8541
8542 #define MAX_COMMON_BANK_SIZE    32
8543 #define FIRST_PSEUDO_BANK_NR  1000
8544
8545 hTab *sym2bank = NULL; // <OPERAND NAME> --> <PSEUDO BANK NR>
8546 hTab *bank2sym = NULL; // <PSEUDO BANK NR> --> <OPERAND NAME>
8547 hTab *coerce = NULL;   // <PSEUDO BANK NR> --> <&PSEUDOBANK>
8548 Graph *adj = NULL;
8549
8550 typedef enum { INVALID_BANK = -1, UNKNOWN_BANK = -2, FIXED_BANK = -3 } pseudoBankNr;
8551
8552 typedef struct {
8553   pseudoBankNr bank;  // number assigned to this pseudoBank
8554   unsigned int size;  // number of operands assigned to this bank
8555   unsigned int ref;   // number of symbols referring to this pseudoBank (for garbage collection)
8556 } pseudoBank;
8557
8558 /*----------------------------------------------------------------------*/
8559 /* hashSymbol - hash function used to map SYMBOLs (or operands) to ints */
8560 /*----------------------------------------------------------------------*/
8561 unsigned int hashSymbol (const char *str)
8562 {
8563   unsigned int res = 0;
8564   if (!str) return 0;
8565
8566   while (*str) {
8567     res ^= (*str);
8568     res = (res << 4) | (res >> (8 * sizeof(unsigned int) - 4));
8569     str++;
8570   } // while
8571
8572   return res;
8573 }
8574
8575 /*-----------------------------------------------------------------------*/
8576 /* compareSymbol - return 1 iff sym1 equals sym2                         */
8577 /*-----------------------------------------------------------------------*/
8578 int compareSymbol (const void *sym1, const void *sym2)
8579 {
8580   char *s1 = (char*) sym1;
8581   char *s2 = (char*) sym2;
8582   
8583   return (strcmp (s1,s2) == 0);
8584 }
8585
8586 /*-----------------------------------------------------------------------*/
8587 /* comparePre - return 1 iff p1 == p2                                    */
8588 /*-----------------------------------------------------------------------*/
8589 int comparePtr (const void *p1, const void *p2)
8590 {
8591   return (p1 == p2);
8592 }
8593
8594 /*----------------------------------------------------------*/
8595 /* getSymbolFromOperand - return a pointer to the symbol in */
8596 /*                        the given operand and its length  */
8597 /*----------------------------------------------------------*/
8598 char *getSymbolFromOperand (char *op, unsigned int *len)
8599 {
8600   char *sym, *curr;
8601   *len = 0;
8602
8603   if (!op) return NULL;
8604
8605   // we recognize two forms of operands: SYMBOL and (SYMBOL + offset)
8606   sym = op;
8607   if (*sym == '(') sym++;
8608
8609   curr = sym;
8610   while (((*curr >= 'A') && (*curr <= 'Z'))
8611          || ((*curr >= 'a') && (*curr <= 'z'))
8612          || ((curr != sym) && (*curr >= '0') && (*curr <= '9'))
8613          || (*curr == '_')) {
8614     // find end of symbol [A-Za-z_]?[A-Za-z0-9]*
8615     curr++;
8616     (*len)++;
8617   } // while
8618
8619   return sym;
8620 }
8621
8622 /*--------------------------------------------------------------------------*/
8623 /* getSymFromBank - get (one) name of a symbol assigned to the given bank   */
8624 /*--------------------------------------------------------------------------*/
8625 char *getSymFromBank (pseudoBankNr bank)
8626 {
8627   assert (bank2sym);
8628
8629   if (bank < 0) return "<INVALID BANK NR>";
8630   return hTabFindByKey (bank2sym, bank % bank2sym->size, (void *) bank, &comparePtr);
8631 }
8632
8633 /*-----------------------------------------------------------------------*/
8634 /* getPseudoBsrFromOperand - maps a string to its corresponding pseudo   */
8635 /*                           bank number (uses hTab sym2bank), if the    */
8636 /*                           symbol is not yet assigned a pseudo bank it */
8637 /*                           is assigned one here                        */
8638 /*-----------------------------------------------------------------------*/
8639 pseudoBankNr getPseudoBankNrFromOperand (const char *op)
8640 {
8641   static pseudoBankNr next_bank = FIRST_PSEUDO_BANK_NR;
8642   pseudoBankNr bank;
8643   unsigned int hash;
8644
8645   assert (sym2bank);
8646
8647   hash = hashSymbol (op) % sym2bank->size;
8648   bank = (pseudoBankNr) hTabFindByKey (sym2bank, hash, op, &compareSymbol);
8649   if (bank == (pseudoBankNr)NULL) bank = UNKNOWN_BANK;
8650
8651   if (bank == UNKNOWN_BANK) {
8652     // create a pseudo bank for the operand
8653     bank = next_bank++;
8654     hTabAddItemLong (&sym2bank, hash, (char *)op, (void *)bank);
8655     hTabAddItemLong (&bank2sym, bank, (void *) bank, (void *)op);
8656     getOrAddGNode (adj, NULL, bank); // adds the node if it does not exist yet
8657     //fprintf (stderr, "%s:%d: adding %s with hash %u in bank %u\n", __FUNCTION__, __LINE__, op, hash, bank);
8658   } else {
8659     //fprintf (stderr, "%s:%d: found %s with hash %u in bank %u\n", __FUNCTION__, __LINE__, op, hash, bank);
8660   } // if
8661
8662   assert (bank >= 0);
8663
8664   return bank;
8665 }
8666
8667 /*--------------------------------------------------------------------*/
8668 /* isBanksel - check whether the given pCode is a BANKSEL instruction */
8669 /*--------------------------------------------------------------------*/
8670 int isBanksel (pCode *pc)
8671 {
8672   if (!pc) return 0;
8673
8674   if (isPCI(pc) && (PCI(pc)->op == POC_BANKSEL || PCI(pc)->op == POC_MOVLB)) {
8675     // BANKSEL <variablename>  or  MOVLB <banknr>
8676     //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8677     return 1;
8678   }
8679
8680   // check for inline assembler BANKSELs
8681   if (isPCAD(pc) && PCAD(pc)->directive && (STRCASECMP(PCAD(pc)->directive,"BANKSEL") == 0 ||
8682                                             STRCASECMP(PCAD(pc)->directive,"MOVLB") == 0)) {
8683     //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8684     return 1;
8685   }
8686
8687   // assume pc is no BANKSEL instruction
8688   return 0;
8689 }
8690
8691 /*---------------------------------------------------------------------------------*/
8692 /* invalidatesBSR - check whether the pCodeInstruction passed in modifies the BSR  */
8693 /*                  This method can not guarantee to find all modifications of the */
8694 /*                  BSR (e.g. via INDirection registers) but covers all compiler   */
8695 /*                  generated plus some cases.                                     */
8696 /*---------------------------------------------------------------------------------*/
8697 int invalidatesBSR(pCode *pc)
8698 {
8699   // assembler directives invalidate BSR (well, they might, we don't know)
8700   if (isPCAD(pc)) return 1;
8701
8702   // only ASMDIRs and pCodeInstructions can invalidate BSR
8703   if (!isPCI(pc)) return 0;
8704
8705   // we have a pCodeInstruction
8706
8707   // check for BSR modifying instructions
8708   switch (PCI(pc)->op) {
8709   case POC_CALL:
8710   case POC_RCALL:
8711   case POC_MOVLB:
8712   case POC_RETFIE:  // might be used as CALL replacement
8713   case POC_RETLW:   // might be used as CALL replacement
8714   case POC_RETURN:  // might be used as CALL replacement
8715   case POC_BANKSEL:
8716     return 1;
8717     break;
8718
8719   default:          // other instruction do not change BSR unless BSR is an explicit operand!
8720     // TODO: check for BSR as an explicit operand (e.g. INCF BSR,F), which should be rather unlikely...!
8721     break;
8722   } // switch
8723
8724   // no change of BSR possible/probable
8725   return 0;
8726 }
8727
8728 /*------------------------------------------------------------*/
8729 /* getBankFromBanksel - return the pseudo bank nr assigned to */
8730 /*                      the symbol referenced in this BANKSEL */
8731 /*------------------------------------------------------------*/
8732 pseudoBankNr getBankFromBanksel (pCode *pc)
8733 {
8734   char *sym;
8735   int data = (int)NULL;
8736
8737   if (!pc) return INVALID_BANK;
8738   
8739   if (isPCAD(pc) && PCAD(pc)->directive) {
8740     if (STRCASECMP(PCAD(pc)->directive,"BANKSEL") == 0) {
8741       // get symbolname from PCAD(pc)->arg
8742       //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8743       sym = PCAD(pc)->arg;
8744       data = getPseudoBankNrFromOperand (sym);
8745       //fprintf (stderr, "symbol: %s, data=%i\n", sym, data);
8746     } else if (STRCASECMP(PCAD(pc)->directive,"MOVLB")) {
8747       // get (literal) bank number from PCAD(pc)->arg
8748       fprintf (stderr, "%s:%d: MOVLB found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8749       assert (0 && "not yet implemented - turn off banksel optimization for now");
8750     }
8751   } else if (isPCI(pc)) {
8752     if (PCI(pc)->op == POC_BANKSEL) {
8753       // get symbolname from PCI(pc)->pcop->name (?)
8754       //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pcop->name);
8755       sym = PCI(pc)->pcop->name;
8756       data = getPseudoBankNrFromOperand (sym);
8757       //fprintf (stderr, "symbol: %s, data=%i\n", sym, data);
8758     } else if (PCI(pc)->op == POC_MOVLB) {
8759       // get (literal) bank number from PCI(pc)->pcop->name
8760       fprintf (stderr, "%s:%d: MOVLB found: %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pcop->name);
8761       assert (0 && "not yet implemented - turn off banksel optimization for now");
8762     }
8763   }
8764   
8765   if (data == 0)
8766     // no assigned bank could be found
8767     return UNKNOWN_BANK;
8768   else
8769     return data;
8770 }
8771
8772 /*------------------------------------------------------------------------------*/
8773 /* getEffectiveBank - resolves the currently assigned effective pseudo bank nr  */
8774 /*------------------------------------------------------------------------------*/
8775 pseudoBankNr getEffectiveBank (pseudoBankNr bank)
8776 {
8777   pseudoBank *data;
8778
8779   if (bank < FIRST_PSEUDO_BANK_NR) return bank;
8780
8781   do {
8782     //fprintf (stderr, "%s:%d: bank=%d\n", __FUNCTION__, __LINE__, bank);
8783     data = (pseudoBank *) hTabFindByKey (coerce, bank % coerce->size, (void *) bank, &comparePtr);
8784     if (data) {
8785       if (data->bank != bank)
8786         bank = data->bank;
8787       else
8788         data = NULL;
8789     }
8790   } while (data);
8791   
8792   //fprintf (stderr, "%s:%d: effective bank=%d\n", __FUNCTION__, __LINE__, bank);
8793   return bank;
8794 }
8795
8796 /*------------------------------------------------------------------*/
8797 /* attachBsrInfo2pBlock - create a look-up table as to which pseudo */
8798 /*                        bank is selected at a given pCode         */
8799 /*------------------------------------------------------------------*/
8800
8801 /* Create a graph with pseudo banks as its nodes and switches between
8802  * these as edges (with the edge weight representing the absolute
8803  * number of BANKSELs from one to the other).
8804  * Removes redundand BANKSELs instead iff mod == 1.
8805  * BANKSELs update the pseudo BSR, labels invalidate the current BSR
8806  * value (setting it to 0=UNNKOWN), (R)CALLs also invalidate the
8807  * pseudo BSR.
8808  * TODO: check ALL instructions operands if they modify BSR directly...
8809  *
8810  * pb - the pBlock to annotate
8811  * mod  - select either graph creation (0) or BANKSEL removal (1)
8812  */
8813 unsigned int attachBsrInfo2pBlock (pBlock *pb, int mod)
8814 {
8815   pCode *pc, *pc_next;
8816   unsigned int prevBSR = UNKNOWN_BANK, pseudoBSR = UNKNOWN_BANK;
8817   int isBankselect = 0;
8818   unsigned int banksels=0;
8819   
8820   if (!pb) return 0;
8821
8822   pc = pic16_findNextInstruction(pb->pcHead);
8823   while (pc) {
8824     isBankselect = isBanksel (pc);
8825     pc_next = pic16_findNextInstruction (pc->next);
8826
8827     if (!hasNoLabel (pc)) {
8828       // we don't know our predecessors -- assume different BSRs
8829       prevBSR = UNKNOWN_BANK;
8830       pseudoBSR = UNKNOWN_BANK;
8831       //fprintf (stderr, "invalidated by label at "); pc->print (stderr, pc);
8832     } // if
8833
8834     // check if this is a BANKSEL instruction
8835     if (isBankselect) {
8836       pseudoBSR = getEffectiveBank (getBankFromBanksel(pc));
8837       //fprintf (stderr, "BANKSEL via "); pc->print (stderr, pc);
8838       if (mod) {
8839         if (prevBSR == pseudoBSR && pseudoBSR >= 0) {
8840           //fprintf (stderr, "removing redundant "); pc->print (stderr, pc);
8841           if (1 || pic16_pcode_verbose) pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("removed redundant BANKSEL"));
8842           pic16_unlinkpCode (pc);
8843           banksels++;
8844         }
8845       } else {
8846         addGEdge2 (getOrAddGNode (adj, NULL, prevBSR), getOrAddGNode (adj, NULL, pseudoBSR), 1, 0);
8847         banksels++;
8848       }
8849     } // if
8850
8851     if (!isBankselect && invalidatesBSR(pc)) {
8852       // check if this instruction invalidates the pseudoBSR
8853       pseudoBSR = UNKNOWN_BANK;
8854       //fprintf (stderr, "invalidated via "); pc->print (stderr, pc);
8855     } // if
8856
8857     prevBSR = pseudoBSR;
8858     pc = pc_next;
8859   } // while
8860
8861   return banksels;
8862 }
8863
8864 /*------------------------------------------------------------------------------------*/
8865 /* assignToSameBank - returns 0 on success or an error code                           */
8866 /*  1 - common bank would be too large                                                */
8867 /*  2 - assignment to fixed (absolute) bank not performed                             */
8868 /*                                                                                    */
8869 /* This functions assumes that unsplittable operands are already assigned to the same */
8870 /* bank (e.g. all objects being referenced as (SYMBOL + offset) must be in the same   */
8871 /* bank so that we can make sure the bytes are laid out sequentially in memory)       */
8872 /* TODO: Symbols with an abslute address must be handled specially!                   */
8873 /*------------------------------------------------------------------------------------*/
8874 int assignToSameBank (int bank0, int bank1, int doAbs)
8875 {
8876   int eff0, eff1, dummy;
8877   pseudoBank *pbank0, *pbank1;
8878   hashtItem *hitem;
8879
8880   eff0 = getEffectiveBank (bank0);
8881   eff1 = getEffectiveBank (bank1);
8882
8883   //fprintf (stderr, "%s:%d: bank0=%d/%d, bank1=%d/%d, doAbs=%d\n", __FUNCTION__, __LINE__, bank0, eff0, bank1, eff1, doAbs);
8884
8885   // nothing to do if already same bank
8886   if (eff0 == eff1) return 0;
8887
8888   if (!doAbs && (eff0 < FIRST_PSEUDO_BANK_NR || eff1 < FIRST_PSEUDO_BANK_NR))
8889     return 2;
8890
8891   // ensure eff0 < eff1
8892   if (eff0 > eff1) {
8893     // swap eff0 and eff1
8894     dummy = eff0;
8895     eff0 = eff1;
8896     eff1 = dummy;
8897     dummy = bank0;
8898     bank0 = bank1;
8899     bank1 = dummy;
8900   } // if
8901
8902   // now assign bank eff1 to bank eff0
8903   pbank0 = (pseudoBank *) hTabFindByKey (coerce, eff0 % coerce->size, (void *)((char*)0+eff0), &comparePtr);
8904   if (!pbank0) {
8905     pbank0 = Safe_calloc (1, sizeof (pseudoBank));
8906     pbank0->bank = eff0;
8907     pbank0->size = 1;
8908     pbank0->ref = 1;
8909     hTabAddItemLong (&coerce, eff0 % coerce->size, (void *)((char*)0+eff0), (void *) pbank0);
8910   } // if
8911
8912   pbank1 = NULL;
8913   hitem = hTabSearch (coerce, eff1 % coerce->size);
8914   while (hitem && hitem->pkey != (void *)((char*)0+eff1))
8915     hitem = hitem->next;
8916
8917   if (hitem) pbank1 = (pseudoBank *) hitem->item;
8918
8919 #if 0
8920   fprintf (stderr, "bank #%d/%d & bank #%d/%d --> bank #%d: %u (%s & %s)\n", bank0, eff0, bank1, eff1,
8921            pbank0->bank, pbank0->size,
8922            getSymFromBank (eff0), getSymFromBank (eff1));
8923 #endif
8924
8925   if (pbank1) {
8926     if (pbank0->size + pbank1->size > MAX_COMMON_BANK_SIZE) {
8927 #if 0
8928       fprintf (stderr, "bank #%d: %u, bank #%d: %u --> bank #%d': %u > %u (%s,%s)\n",
8929                pbank0->bank, pbank0->size, pbank1->bank, pbank1->size,
8930                pbank0->bank, pbank0->size + pbank1->size, MAX_COMMON_BANK_SIZE,
8931                getSymFromBank (pbank0->bank), getSymFromBank (pbank1->bank));
8932 #endif
8933       return 1;
8934     } // if
8935     pbank0->size += pbank1->size;
8936     pbank1->ref--;
8937     if (pbank1->ref == 0) Safe_free (pbank1);
8938   } else {
8939     pbank0->size++;
8940   } // if
8941
8942   if (hitem)
8943     hitem->item = pbank0;
8944   else  
8945     hTabAddItemLong (&coerce, eff1 % coerce->size, (void *)((char*)0+eff1), (void *) pbank0);
8946   pbank0->ref++;
8947
8948   //fprintf (stderr, "%s:%d: leaving.\n", __FUNCTION__, __LINE__);
8949
8950   return 0;
8951 }
8952
8953 /*----------------------------------------------------------------*/
8954 /* mergeGraphNodes - combines two nodes into one and modifies all */
8955 /*                   edges to and from the nodes accordingly      */
8956 /* This method needs complete backedges, i.e. if (A,B) is an edge */
8957 /* then also (B,A) must be an edge (possibly with weight 0).      */
8958 /*----------------------------------------------------------------*/
8959 void mergeGraphNodes (GraphNode *node1, GraphNode *node2)
8960 {
8961   GraphEdge *edge, *backedge, *nextedge;
8962   GraphNode *node;
8963   int backweight;
8964
8965   assert (node1 && node2);
8966   assert (node1 != node2);
8967   
8968   // add all edges starting at node2 to node1
8969   edge = node2->edge;
8970   while (edge) {
8971     nextedge = edge->next;
8972     node = edge->node;
8973     backedge = getGEdge (node, node2);
8974     if (backedge)
8975       backweight = backedge->weight;
8976     else
8977       backweight = 0;
8978     // insert edges (node1,node) and (node,node1)
8979     addGEdge2 (node1, node, edge->weight, backweight);
8980     // remove edges (node, node2) and (node2, node)
8981     remGEdge (node2, node);
8982     remGEdge (node, node2);
8983     edge = nextedge;
8984   } // while
8985   
8986   // now node2 should not be referenced by any other GraphNode...
8987   //remGNode (adj, node2->data, node2->hash);
8988 }
8989
8990 /*----------------------------------------------------------------*/
8991 /* showGraph - dump the current BANKSEL graph as a node/edge list */
8992 /*----------------------------------------------------------------*/
8993 void showGraph (Graph *g)
8994 {
8995   GraphNode *node;
8996   GraphEdge *edge;
8997   pseudoBankNr bankNr;
8998   pseudoBank *pbank;
8999   unsigned int size;
9000
9001   node = g->node;
9002   while (node) {
9003     edge = node->edge;
9004     bankNr = getEffectiveBank (node->hash);
9005     assert (bankNr >= 0);
9006     pbank = (pseudoBank *) hTabFindByKey (coerce, bankNr % coerce->size, (void *) bankNr, &comparePtr);
9007     if (pbank) {
9008       bankNr = pbank->bank;
9009       size = pbank->size;
9010     } else {
9011       size = 1;
9012     }
9013     
9014     fprintf (stderr, "edges from %s (bank %u, size %u) to:\n", getSymFromBank (node->hash), bankNr, size);
9015
9016     while (edge) {
9017       if (edge->weight > 0)
9018         fprintf (stderr, "  %4u x %s\n", edge->weight, getSymFromBank (edge->node->hash));
9019       edge = edge->next;
9020     } // while (edge)
9021     node = node->next;
9022   } // while (node)
9023 }
9024
9025 /*---------------------------------------------------------------*/
9026 /* pic16_OptimizeBanksel - remove redundant BANKSEL instructions */
9027 /*---------------------------------------------------------------*/
9028 void pic16_OptimizeBanksel ()
9029 {
9030   GraphNode *node, *node1, *node1next;
9031
9032 #if 0
9033   // needed for more effective bank assignment (needs adjusted pic16_emit_usection())
9034   GraphEdge *edge, *backedge;
9035   GraphEdge *max;
9036   int maxWeight, weight, mergeMore, absMaxWeight;
9037   pseudoBankNr curr0, curr1;
9038 #endif
9039   pseudoBank *pbank;
9040   pseudoBankNr bankNr;
9041   char *base_symbol0, *base_symbol1;
9042   int len0, len1;
9043   pBlock *pb;
9044   set *set;
9045   regs *reg;
9046   unsigned int bankselsTotal = 0, bankselsRemoved = 0; 
9047
9048   //fprintf (stderr, "%s:%s:%d: entered.\n", __FILE__, __FUNCTION__, __LINE__);
9049
9050   if (!the_pFile || !the_pFile->pbHead) return;
9051
9052   adj = newGraph (NULL);
9053   sym2bank = newHashTable ( 255 );
9054   bank2sym = newHashTable ( 255 );
9055   coerce = newHashTable ( 255 );
9056
9057   // create graph of BANKSEL relationships (node = operands, edge (A,B) iff BANKSEL B follows BANKSEL A)
9058   for (pb = the_pFile->pbHead; pb; pb = pb->next) {
9059     bankselsTotal += attachBsrInfo2pBlock (pb, 0);
9060   } // for pb
9061
9062 #if 1
9063   // assign symbols with absolute addresses to their respective bank nrs
9064   set = pic16_fix_udata;
9065   for (reg = setFirstItem (set); reg; reg = setNextItem (set)) {
9066     bankNr = reg->address >> 8;
9067     node = getOrAddGNode (adj, NULL, bankNr);
9068     bankNr = (pseudoBankNr) getEffectiveBank (getPseudoBankNrFromOperand(reg->name));
9069     assignToSameBank (node->hash, bankNr, 1);
9070     
9071     assert (bankNr >= 0);
9072     pbank = (pseudoBank *) hTabFindByKey (coerce, bankNr % coerce->size, (void *) bankNr, &comparePtr);
9073     if (!pbank) {
9074       pbank = Safe_calloc (1, sizeof (pseudoBank));
9075       pbank->bank = reg->address >> 8; //FIXED_BANK;
9076       pbank->size = 1;
9077       pbank->ref = 1;
9078       hTabAddItemLong (&coerce, bankNr % coerce->size, (void *) bankNr, pbank);
9079     } else {
9080       assert (pbank->bank == (reg->address >> 8));
9081       pbank->bank = reg->address >> 8; //FIXED_BANK;
9082     }
9083     //fprintf (stderr, "ABS: %s (%d bytes) at %x in bank %u\n", reg->name, reg->size, reg->address, bankNr);
9084   } // for reg
9085 #endif
9086
9087 #if 1
9088   // assign operands referring to the same symbol (which is not given an absolute address) to the same bank
9089   //fprintf (stderr, "assign operands with the same symbol to the same bank\n");
9090   node = adj->node;
9091   while (node) {
9092     if (node->hash < 0) { node = node->next; continue; }
9093     base_symbol0 = getSymbolFromOperand (getSymFromBank (getEffectiveBank(node->hash)), &len0);
9094     node1 = node->next;
9095     while (node1) {
9096       if (node1->hash < 0) { node1 = node1->next; continue; }
9097       node1next = node1->next;
9098       base_symbol1 = getSymbolFromOperand (getSymFromBank (getEffectiveBank (node1->hash)), &len1);
9099       if (len0 == len1 && len0 > 0 && strncmp (base_symbol0, base_symbol1, len0) == 0) {
9100         // TODO: check for symbols with absolute addresses -- these might be placed across bank boundaries!
9101         //fprintf (stderr, "merging %s and %s\n", getSymFromBank (getEffectiveBank(node->hash)), getSymFromBank (getEffectiveBank(node1->hash)));
9102         if (assignToSameBank (node->hash, node1->hash, 0)) {
9103           fprintf (stderr, "%s(%d) == %s(%d)\n", base_symbol0, len0, base_symbol1, len1);
9104           assert (0 && "Could not assign a symbol to a bank!");
9105         }
9106         mergeGraphNodes (node, node1);
9107         /*
9108         if (node->hash < node1->hash)
9109           mergeGraphNodes (node, node1);
9110         else
9111           mergeGraphNodes (node1, node); // this removes node so node->next will fail...
9112         */
9113       } // if
9114       node1 = node1next;
9115     } // while (node1)
9116     node = node->next;
9117   } // while (node)
9118 #endif
9119
9120 #if 0
9121   // >>> THIS ALSO NEEDS AN UPDATED pic16_emit_usection() TO REFLECT THE BANK ASSIGNMENTS <<<
9122   // assign tightly coupled operands to the same (pseudo) bank
9123   //fprintf (stderr, "assign tightly coupled operands to the same bank\n");
9124   mergeMore = 1;
9125   absMaxWeight = 0;
9126   while (mergeMore) {
9127     node = adj->node;
9128     max = NULL;
9129     maxWeight = 0;
9130     while (node) {
9131       curr0 = getEffectiveBank (node->hash);
9132       if (curr0 < 0) { node = node->next; continue; }
9133       edge = node->edge;
9134       while (edge) {
9135         assert (edge->src == node);
9136         backedge = getGEdge (edge->node, edge->src);
9137         weight = edge->weight + (backedge ? backedge->weight : 0);
9138         curr1 = getEffectiveBank (edge->node->hash);
9139         if (curr1 < 0) { edge = edge->next; continue; }
9140
9141         // merging is only useful if the items are not assigned to the same bank already...
9142         if (curr0 != curr1 && weight > maxWeight) {
9143           if (maxWeight > absMaxWeight) absMaxWeight = maxWeight;
9144           maxWeight = weight;
9145           max = edge;
9146         } // if
9147         edge = edge->next;
9148       } // while
9149       node = node->next;
9150     } // while
9151     
9152     if (maxWeight > 0) {
9153 #if 0
9154       fprintf (stderr, "%s:%d: merging (%4u) %d(%s) and %d(%s)\n", __FUNCTION__, __LINE__, maxWeight,
9155                max->src->hash, getSymFromBank (max->src->hash),
9156                max->node->hash, getSymFromBank (max->node->hash));
9157 #endif
9158
9159       node = getGNode (adj, max->src->data, max->src->hash);
9160       node1 = getGNode (adj, max->node->data, max->node->hash);
9161
9162       if (0 == assignToSameBank (max->src->hash, max->node->hash, 0)) {
9163         if (max->src->hash < max->node->hash)
9164           mergeGraphNodes (node, node1);
9165         else
9166           mergeGraphNodes (node1, node);
9167       } else {
9168         remGEdge (node, node1);
9169         remGEdge (node1, node);
9170         //mergeMore = 0;
9171       }
9172
9173     } else {
9174       mergeMore = 0;
9175     }
9176   } // while
9177 #endif
9178
9179 #if 1  
9180   // remove redundant BANKSELs
9181   //fprintf (stderr, "removing redundant BANKSELs\n");
9182   for (pb = the_pFile->pbHead; pb; pb = pb->next) {
9183     bankselsRemoved += attachBsrInfo2pBlock (pb, 1);
9184   } // for pb
9185 #endif
9186
9187 #if 0
9188   fprintf (stderr, "display graph\n");
9189   showGraph ();
9190 #endif
9191
9192   deleteGraph (adj);
9193   //fprintf (stderr, "%s:%s:%d: leaving, %u/%u BANKSELs removed...\n", __FILE__, __FUNCTION__, __LINE__, bankselsRemoved, bankselsTotal);
9194 }
9195
9196 /*** END of stuff belonging to the BANKSEL optimization ***/