* sim/ucsim/cmd.src/cmdutil.cc: NUL device is detected as CG_FILE type
[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 extern char *pic16_aopGet (struct asmop *aop, int offset, bool bit16, bool dname);
36
37 #if defined(__BORLANDC__) || defined(_MSC_VER)
38 #define inline
39 #endif
40
41 #define DUMP_DF_GRAPHS 0
42
43 /****************************************************************/
44 /****************************************************************/
45
46 static peepCommand peepCommands[] = {
47
48   {NOTBITSKIP, "_NOTBITSKIP_"},
49   {BITSKIP, "_BITSKIP_"},
50   {INVERTBITSKIP, "_INVERTBITSKIP_"},
51
52   {-1, NULL}
53 };
54
55
56
57 // Eventually this will go into device dependent files:
58 pCodeOpReg pic16_pc_status    = {{PO_STATUS,  "STATUS"}, -1, NULL,0,NULL};
59 pCodeOpReg pic16_pc_intcon    = {{PO_INTCON,  "INTCON"}, -1, NULL,0,NULL};
60 pCodeOpReg pic16_pc_pcl       = {{PO_PCL,     "PCL"}, -1, NULL,0,NULL};
61 pCodeOpReg pic16_pc_pclath    = {{PO_PCLATH,  "PCLATH"}, -1, NULL,0,NULL};
62 pCodeOpReg pic16_pc_pclatu    = {{PO_PCLATU,  "PCLATU"}, -1, NULL,0,NULL}; // patch 14
63 pCodeOpReg pic16_pc_wreg      = {{PO_WREG,    "WREG"}, -1, NULL,0,NULL};
64 pCodeOpReg pic16_pc_bsr       = {{PO_BSR,     "BSR"}, -1, NULL,0,NULL};
65
66 pCodeOpReg pic16_pc_tosl      = {{PO_SFR_REGISTER,   "TOSL"}, -1, NULL,0,NULL}; // patch 14
67 pCodeOpReg pic16_pc_tosh      = {{PO_SFR_REGISTER,   "TOSH"}, -1, NULL,0,NULL}; //
68 pCodeOpReg pic16_pc_tosu      = {{PO_SFR_REGISTER,   "TOSU"}, -1, NULL,0,NULL}; // patch 14
69
70 pCodeOpReg pic16_pc_tblptrl   = {{PO_SFR_REGISTER,   "TBLPTRL"}, -1, NULL,0,NULL}; // patch 15
71 pCodeOpReg pic16_pc_tblptrh   = {{PO_SFR_REGISTER,   "TBLPTRH"}, -1, NULL,0,NULL}; //
72 pCodeOpReg pic16_pc_tblptru   = {{PO_SFR_REGISTER,   "TBLPTRU"}, -1, NULL,0,NULL}; //
73 pCodeOpReg pic16_pc_tablat    = {{PO_SFR_REGISTER,   "TABLAT"}, -1, NULL,0,NULL};  // patch 15
74
75 //pCodeOpReg pic16_pc_fsr0      = {{PO_FSR0,    "FSR0"}, -1, NULL,0,NULL}; //deprecated !
76
77 pCodeOpReg pic16_pc_fsr0l       = {{PO_FSR0,    "FSR0L"}, -1, NULL, 0, NULL};
78 pCodeOpReg pic16_pc_fsr0h       = {{PO_FSR0,    "FSR0H"}, -1, NULL, 0, NULL};
79 pCodeOpReg pic16_pc_fsr1l       = {{PO_FSR0,    "FSR1L"}, -1, NULL, 0, NULL};
80 pCodeOpReg pic16_pc_fsr1h       = {{PO_FSR0,    "FSR1H"}, -1, NULL, 0, NULL};
81 pCodeOpReg pic16_pc_fsr2l       = {{PO_FSR0,    "FSR2L"}, -1, NULL, 0, NULL};
82 pCodeOpReg pic16_pc_fsr2h       = {{PO_FSR0,    "FSR2H"}, -1, NULL, 0, NULL};
83
84 pCodeOpReg pic16_pc_indf0       = {{PO_INDF0,   "INDF0"}, -1, NULL,0,NULL};
85 pCodeOpReg pic16_pc_postinc0    = {{PO_INDF0,   "POSTINC0"}, -1, NULL, 0, NULL};
86 pCodeOpReg pic16_pc_postdec0    = {{PO_INDF0,   "POSTDEC0"}, -1, NULL, 0, NULL};
87 pCodeOpReg pic16_pc_preinc0     = {{PO_INDF0,   "PREINC0"}, -1, NULL, 0, NULL};
88 pCodeOpReg pic16_pc_plusw0      = {{PO_INDF0,   "PLUSW0"}, -1, NULL, 0, NULL};
89
90 pCodeOpReg pic16_pc_indf1       = {{PO_INDF0,   "INDF1"}, -1, NULL,0,NULL};
91 pCodeOpReg pic16_pc_postinc1    = {{PO_INDF0,   "POSTINC1"}, -1, NULL, 0, NULL};
92 pCodeOpReg pic16_pc_postdec1    = {{PO_INDF0,   "POSTDEC1"}, -1, NULL, 0, NULL};
93 pCodeOpReg pic16_pc_preinc1     = {{PO_INDF0,   "PREINC1"}, -1, NULL, 0, NULL};
94 pCodeOpReg pic16_pc_plusw1      = {{PO_INDF0,   "PLUSW1"}, -1, NULL, 0, NULL};
95
96 pCodeOpReg pic16_pc_indf2       = {{PO_INDF0,   "INDF2"}, -1, NULL,0,NULL};
97 pCodeOpReg pic16_pc_postinc2    = {{PO_INDF0,   "POSTINC2"}, -1, NULL, 0, NULL};
98 pCodeOpReg pic16_pc_postdec2    = {{PO_INDF0,   "POSTDEC2"}, -1, NULL, 0, NULL};
99 pCodeOpReg pic16_pc_preinc2     = {{PO_INDF0,   "PREINC2"}, -1, NULL, 0, NULL};
100 pCodeOpReg pic16_pc_plusw2      = {{PO_INDF0,   "PLUSW2"}, -1, NULL, 0, NULL};
101
102 pCodeOpReg pic16_pc_prodl       = {{PO_PRODL, "PRODL"}, -1, NULL, 0, NULL};
103 pCodeOpReg pic16_pc_prodh       = {{PO_PRODH, "PRODH"}, -1, NULL, 0, NULL};
104
105 /* EEPROM registers */
106 pCodeOpReg pic16_pc_eecon1      = {{PO_SFR_REGISTER, "EECON1"}, -1, NULL, 0, NULL};
107 pCodeOpReg pic16_pc_eecon2      = {{PO_SFR_REGISTER, "EECON2"}, -1, NULL, 0, NULL};
108 pCodeOpReg pic16_pc_eedata      = {{PO_SFR_REGISTER, "EEDATA"}, -1, NULL, 0, NULL};
109 pCodeOpReg pic16_pc_eeadr       = {{PO_SFR_REGISTER, "EEADR"}, -1, NULL, 0, NULL};
110
111 pCodeOpReg pic16_pc_kzero     = {{PO_GPR_REGISTER,  "KZ"}, -1, NULL,0,NULL};
112 pCodeOpReg pic16_pc_wsave     = {{PO_GPR_REGISTER,  "WSAVE"}, -1, NULL,0,NULL};
113 pCodeOpReg pic16_pc_ssave     = {{PO_GPR_REGISTER,  "SSAVE"}, -1, NULL,0,NULL};
114
115 pCodeOpReg *pic16_stackpnt_lo;
116 pCodeOpReg *pic16_stackpnt_hi;
117 pCodeOpReg *pic16_stack_postinc;
118 pCodeOpReg *pic16_stack_postdec;
119 pCodeOpReg *pic16_stack_preinc;
120 pCodeOpReg *pic16_stack_plusw;
121
122 pCodeOpReg *pic16_framepnt_lo;
123 pCodeOpReg *pic16_framepnt_hi;
124 pCodeOpReg *pic16_frame_postinc;
125 pCodeOpReg *pic16_frame_postdec;
126 pCodeOpReg *pic16_frame_preinc;
127 pCodeOpReg *pic16_frame_plusw;
128
129 pCodeOpReg pic16_pc_gpsimio   = {{PO_GPR_REGISTER, "GPSIMIO"}, -1, NULL, 0, NULL};
130 pCodeOpReg pic16_pc_gpsimio2  = {{PO_GPR_REGISTER, "GPSIMIO2"}, -1, NULL, 0, NULL};
131
132 char *OPT_TYPE_STR[] = { "begin", "end", "jumptable_begin", "jumptable_end" };
133 char *LR_TYPE_STR[] = { "entry begin", "entry end", "exit begin", "exit end" };
134
135
136 static int mnemonics_initialized = 0;
137
138
139 static hTab *pic16MnemonicsHash = NULL;
140 static hTab *pic16pCodePeepCommandsHash = NULL;
141
142 static pFile *the_pFile = NULL;
143 static pBlock *pb_dead_pcodes = NULL;
144
145 /* Hardcoded flags to change the behavior of the PIC port */
146 static int peepOptimizing = 1;        /* run the peephole optimizer if nonzero */
147 static int functionInlining = 1;      /* inline functions if nonzero */
148 int pic16_debug_verbose = 0;                /* Set true to inundate .asm file */
149
150 int pic16_pcode_verbose = 0;
151
152 //static int GpCodeSequenceNumber = 1;
153 static int GpcFlowSeq = 1;
154
155 extern void pic16_RemoveUnusedRegisters(void);
156 extern void pic16_RegsUnMapLiveRanges(void);
157 extern void pic16_BuildFlowTree(pBlock *pb);
158 extern void pic16_pCodeRegOptimizeRegUsage(int level);
159 extern int pic16_picIsInitialized(void);
160 extern void SAFE_snprintf(char **str, size_t *size, const char *format, ...);
161 extern int mnem2key(unsigned char const *mnem);
162
163 /****************************************************************/
164 /*                      Forward declarations                    */
165 /****************************************************************/
166
167 void pic16_unlinkpCode(pCode *pc);
168 #if 0
169 static void genericAnalyze(pCode *pc);
170 static void AnalyzeGOTO(pCode *pc);
171 static void AnalyzeSKIP(pCode *pc);
172 static void AnalyzeRETURN(pCode *pc);
173 #endif
174
175 static void genericDestruct(pCode *pc);
176 static void genericPrint(FILE *of,pCode *pc);
177
178 static void pCodePrintLabel(FILE *of, pCode *pc);
179 static void pCodePrintFunction(FILE *of, pCode *pc);
180 static void pCodeOpPrint(FILE *of, pCodeOp *pcop);
181 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc);
182 char *pic16_get_op(pCodeOp *pcop,char *buff,size_t buf_size);
183 int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd);
184 int pic16_pCodePeepMatchRule(pCode *pc);
185 static void pBlockStats(FILE *of, pBlock *pb);
186 static pBlock *newpBlock(void);
187 extern void pic16_pCodeInsertAfter(pCode *pc1, pCode *pc2);
188 extern pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
189 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval);
190 void pic16_pCodeRegMapLiveRanges(pBlock *pb);
191 void OptimizeLocalRegs(void);
192 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst);
193
194 char *dumpPicOptype(PIC_OPTYPE type);
195
196 pCodeOp *pic16_popGetLit2(int, pCodeOp *);
197 pCodeOp *pic16_popGetLit(int);
198 pCodeOp *pic16_popGetWithString(char *);
199 extern int inWparamList(char *s);
200
201 /** data flow optimization helpers **/
202 #if defined (DUMP_DF_GRAPHS) && DUMP_DF_GRAPHS > 0
203 static void pic16_vcg_dump (FILE *of, pBlock *pb);
204 static void pic16_vcg_dump_default (pBlock *pb);
205 #endif
206 static int pic16_pCodeIsAlive (pCode *pc);
207 static void pic16_df_stats ();
208 static void pic16_createDF (pBlock *pb);
209 static int pic16_removeUnusedRegistersDF ();
210 static void pic16_destructDF (pBlock *pb);
211 static void releaseStack ();
212
213 /****************************************************************/
214 /*                    PIC Instructions                          */
215 /****************************************************************/
216
217 pCodeInstruction pic16_pciADDWF = {
218   {PC_OPCODE, NULL, NULL, 0, NULL, 
219    //   genericAnalyze,
220    genericDestruct,
221    genericPrint},
222   POC_ADDWF,
223   "ADDWF",
224   2,
225   NULL, // from branch
226   NULL, // to branch
227   NULL, // label
228   NULL, // operand
229   NULL, // flow block
230   NULL, // C source 
231   3,    // num ops
232   1,0,  // dest, bit instruction
233   0,0,  // branch, skip
234   0,    // literal operand
235   1,    // RAM access bit
236   0,    // fast call/return mode select bit
237   0,    // second memory operand
238   0,    // second literal operand
239   POC_NOP,
240   (PCC_W | PCC_REGISTER),   // inCond
241   (PCC_REGISTER | PCC_STATUS), // outCond
242   PCI_MAGIC
243 };
244
245 pCodeInstruction pic16_pciADDFW = {
246   {PC_OPCODE, NULL, NULL, 0, NULL, 
247    //   genericAnalyze,
248    genericDestruct,
249    genericPrint},
250   POC_ADDFW,
251   "ADDWF",
252   2,
253   NULL, // from branch
254   NULL, // to branch
255   NULL, // label
256   NULL, // operand
257   NULL, // flow block
258   NULL, // C source 
259   3,    // num ops
260   0,0,  // dest, bit instruction
261   0,0,  // branch, skip
262   0,    // literal operand
263   1,    // RAM access bit
264   0,    // fast call/return mode select bit
265   0,    // second memory operand
266   0,    // second literal operand
267   POC_NOP,
268   (PCC_W | PCC_REGISTER),   // inCond
269   (PCC_W | PCC_STATUS), // outCond
270   PCI_MAGIC
271 };
272
273 pCodeInstruction pic16_pciADDWFC = { // mdubuc - New
274   {PC_OPCODE, NULL, NULL, 0, NULL, 
275    //   genericAnalyze,
276    genericDestruct,
277    genericPrint},
278   POC_ADDWFC,
279   "ADDWFC",
280   2,
281   NULL, // from branch
282   NULL, // to branch
283   NULL, // label
284   NULL, // operand
285   NULL, // flow block
286   NULL, // C source 
287   3,    // num ops
288   1,0,  // dest, bit instruction
289   0,0,  // branch, skip
290   0,    // literal operand
291   1,    // RAM access bit
292   0,    // fast call/return mode select bit
293   0,    // second memory operand
294   0,    // second literal operand
295   POC_NOP,
296   (PCC_W | PCC_REGISTER | PCC_C),   // inCond
297   (PCC_REGISTER | PCC_STATUS), // outCond
298   PCI_MAGIC
299 };
300
301 pCodeInstruction pic16_pciADDFWC = {
302   {PC_OPCODE, NULL, NULL, 0, NULL, 
303    //   genericAnalyze,
304    genericDestruct,
305    genericPrint},
306   POC_ADDFWC,
307   "ADDWFC",
308   2,
309   NULL, // from branch
310   NULL, // to branch
311   NULL, // label
312   NULL, // operand
313   NULL, // flow block
314   NULL, // C source 
315   3,    // num ops
316   0,0,  // dest, bit instruction
317   0,0,  // branch, skip
318   0,    // literal operand
319   1,    // RAM access bit
320   0,    // fast call/return mode select bit
321   0,    // second memory operand
322   0,    // second literal operand
323   POC_NOP,
324   (PCC_W | PCC_REGISTER | PCC_C),   // inCond
325   (PCC_W | PCC_STATUS), // outCond
326   PCI_MAGIC
327 };
328
329 pCodeInstruction pic16_pciADDLW = {
330   {PC_OPCODE, NULL, NULL, 0, NULL, 
331    //   genericAnalyze,
332    genericDestruct,
333    genericPrint},
334   POC_ADDLW,
335   "ADDLW",
336   2,
337   NULL, // from branch
338   NULL, // to branch
339   NULL, // label
340   NULL, // operand
341   NULL, // flow block
342   NULL, // C source 
343   1,    // num ops
344   0,0,  // dest, bit instruction
345   0,0,  // branch, skip
346   1,    // literal operand
347   0,    // RAM access bit
348   0,    // fast call/return mode select bit
349   0,    // second memory operand
350   0,    // second literal operand
351   POC_NOP,
352   (PCC_W | PCC_LITERAL),   // inCond
353   (PCC_W | PCC_STATUS), // outCond
354   PCI_MAGIC
355 };
356
357 pCodeInstruction pic16_pciANDLW = {
358   {PC_OPCODE, NULL, NULL, 0, NULL, 
359    //   genericAnalyze,
360    genericDestruct,
361    genericPrint},
362   POC_ANDLW,
363   "ANDLW",
364   2,
365   NULL, // from branch
366   NULL, // to branch
367   NULL, // label
368   NULL, // operand
369   NULL, // flow block
370   NULL, // C source 
371   1,    // num ops
372   0,0,  // dest, bit instruction
373   0,0,  // branch, skip
374   1,    // literal operand
375   0,    // RAM access bit
376   0,    // fast call/return mode select bit
377   0,    // second memory operand
378   0,    // second literal operand
379   POC_NOP,
380   (PCC_W | PCC_LITERAL),   // inCond
381   (PCC_W | PCC_Z | PCC_N), // outCond
382   PCI_MAGIC
383 };
384
385 pCodeInstruction pic16_pciANDWF = {
386   {PC_OPCODE, NULL, NULL, 0, NULL, 
387    //   genericAnalyze,
388    genericDestruct,
389    genericPrint},
390   POC_ANDWF,
391   "ANDWF",
392   2,
393   NULL, // from branch
394   NULL, // to branch
395   NULL, // label
396   NULL, // operand
397   NULL, // flow block
398   NULL, // C source 
399   3,    // num ops
400   1,0,  // dest, bit instruction
401   0,0,  // branch, skip
402   0,    // literal operand
403   1,    // RAM access bit
404   0,    // fast call/return mode select bit
405   0,    // second memory operand
406   0,    // second literal operand
407   POC_NOP,
408   (PCC_W | PCC_REGISTER),   // inCond
409   (PCC_REGISTER | PCC_Z | PCC_N), // outCond
410   PCI_MAGIC
411 };
412
413 pCodeInstruction pic16_pciANDFW = {
414   {PC_OPCODE, NULL, NULL, 0, NULL, 
415    //   genericAnalyze,
416    genericDestruct,
417    genericPrint},
418   POC_ANDFW,
419   "ANDWF",
420   2,
421   NULL, // from branch
422   NULL, // to branch
423   NULL, // label
424   NULL, // operand
425   NULL, // flow block
426   NULL, // C source 
427   3,    // num ops
428   0,0,  // dest, bit instruction
429   0,0,  // branch, skip
430   0,    // literal operand
431   1,    // RAM access bit
432   0,    // fast call/return mode select bit
433   0,    // second memory operand
434   0,    // second literal operand
435   POC_NOP,
436   (PCC_W | PCC_REGISTER),   // inCond
437   (PCC_W | PCC_Z | PCC_N) // outCond
438 };
439
440 pCodeInstruction pic16_pciBC = { // mdubuc - New
441   {PC_OPCODE, NULL, NULL, 0, NULL, 
442    //   genericAnalyze,
443    genericDestruct,
444    genericPrint},
445   POC_BC,
446   "BC",
447   2,
448   NULL, // from branch
449   NULL, // to branch
450   NULL, // label
451   NULL, // operand
452   NULL, // flow block
453   NULL, // C source 
454   1,    // num ops
455   0,0,  // dest, bit instruction
456   1,0,  // branch, skip
457   0,    // literal operand
458   0,    // RAM access bit
459   0,    // fast call/return mode select bit
460   0,    // second memory operand
461   0,    // second literal operand
462   POC_NOP,
463   (PCC_REL_ADDR | PCC_C),   // inCond
464   PCC_NONE,    // outCond
465   PCI_MAGIC
466 };
467
468 pCodeInstruction pic16_pciBCF = {
469   {PC_OPCODE, NULL, NULL, 0, NULL, 
470    //   genericAnalyze,
471    genericDestruct,
472    genericPrint},
473   POC_BCF,
474   "BCF",
475   2,
476   NULL, // from branch
477   NULL, // to branch
478   NULL, // label
479   NULL, // operand
480   NULL, // flow block
481   NULL, // C source 
482   3,    // num ops
483   1,1,  // dest, bit instruction
484   0,0,  // branch, skip
485   0,    // literal operand
486   1,    // RAM access bit
487   0,    // fast call/return mode select bit
488   0,    // second memory operand
489   0,    // second literal operand
490   POC_BSF,
491   (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
492   PCC_REGISTER, // outCond
493   PCI_MAGIC
494 };
495
496 pCodeInstruction pic16_pciBN = { // mdubuc - New
497   {PC_OPCODE, NULL, NULL, 0, NULL, 
498    //   genericAnalyze,
499    genericDestruct,
500    genericPrint},
501   POC_BN,
502   "BN",
503   2,
504   NULL, // from branch
505   NULL, // to branch
506   NULL, // label
507   NULL, // operand
508   NULL, // flow block
509   NULL, // C source 
510   1,    // num ops
511   0,0,  // dest, bit instruction
512   1,0,  // branch, skip
513   0,    // literal operand
514   0,    // RAM access bit
515   0,    // fast call/return mode select bit
516   0,    // second memory operand
517   0,    // second literal operand
518   POC_NOP,
519   (PCC_REL_ADDR | PCC_N),   // inCond
520   PCC_NONE   , // outCond
521   PCI_MAGIC
522 };
523
524 pCodeInstruction pic16_pciBNC = { // mdubuc - New
525   {PC_OPCODE, NULL, NULL, 0, NULL, 
526    //   genericAnalyze,
527    genericDestruct,
528    genericPrint},
529   POC_BNC,
530   "BNC",
531   2,
532   NULL, // from branch
533   NULL, // to branch
534   NULL, // label
535   NULL, // operand
536   NULL, // flow block
537   NULL, // C source 
538   1,    // num ops
539   0,0,  // dest, bit instruction
540   1,0,  // branch, skip
541   0,    // literal operand
542   0,    // RAM access bit
543   0,    // fast call/return mode select bit
544   0,    // second memory operand
545   0,    // second literal operand
546   POC_NOP,
547   (PCC_REL_ADDR | PCC_C),   // inCond
548   PCC_NONE   , // outCond
549   PCI_MAGIC
550 };
551
552 pCodeInstruction pic16_pciBNN = { // mdubuc - New
553   {PC_OPCODE, NULL, NULL, 0, NULL, 
554    //   genericAnalyze,
555    genericDestruct,
556    genericPrint},
557   POC_BNN,
558   "BNN",
559   2,
560   NULL, // from branch
561   NULL, // to branch
562   NULL, // label
563   NULL, // operand
564   NULL, // flow block
565   NULL, // C source 
566   1,    // num ops
567   0,0,  // dest, bit instruction
568   1,0,  // branch, skip
569   0,    // literal operand
570   0,    // RAM access bit
571   0,    // fast call/return mode select bit
572   0,    // second memory operand
573   0,    // second literal operand
574   POC_NOP,
575   (PCC_REL_ADDR | PCC_N),   // inCond
576   PCC_NONE   , // outCond
577   PCI_MAGIC
578 };
579
580 pCodeInstruction pic16_pciBNOV = { // mdubuc - New
581   {PC_OPCODE, NULL, NULL, 0, NULL, 
582    //   genericAnalyze,
583    genericDestruct,
584    genericPrint},
585   POC_BNOV,
586   "BNOV",
587   2,
588   NULL, // from branch
589   NULL, // to branch
590   NULL, // label
591   NULL, // operand
592   NULL, // flow block
593   NULL, // C source 
594   1,    // num ops
595   0,0,  // dest, bit instruction
596   1,0,  // branch, skip
597   0,    // literal operand
598   0,    // RAM access bit
599   0,    // fast call/return mode select bit
600   0,    // second memory operand
601   0,    // second literal operand
602   POC_NOP,
603   (PCC_REL_ADDR | PCC_OV),   // inCond
604   PCC_NONE   , // outCond
605   PCI_MAGIC
606 };
607
608 pCodeInstruction pic16_pciBNZ = { // mdubuc - New
609   {PC_OPCODE, NULL, NULL, 0, NULL, 
610    //   genericAnalyze,
611    genericDestruct,
612    genericPrint},
613   POC_BNZ,
614   "BNZ",
615   2,
616   NULL, // from branch
617   NULL, // to branch
618   NULL, // label
619   NULL, // operand
620   NULL, // flow block
621   NULL, // C source 
622   1,    // num ops
623   0,0,  // dest, bit instruction
624   1,0,  // branch, skip
625   0,    // literal operand
626   0,    // RAM access bit
627   0,    // fast call/return mode select bit
628   0,    // second memory operand
629   0,    // second literal operand
630   POC_NOP,
631   (PCC_REL_ADDR | PCC_Z),   // inCond
632   PCC_NONE   , // outCond
633   PCI_MAGIC
634 };
635
636 pCodeInstruction pic16_pciBOV = { // mdubuc - New
637   {PC_OPCODE, NULL, NULL, 0, NULL, 
638    //   genericAnalyze,
639    genericDestruct,
640    genericPrint},
641   POC_BOV,
642   "BOV",
643   2,
644   NULL, // from branch
645   NULL, // to branch
646   NULL, // label
647   NULL, // operand
648   NULL, // flow block
649   NULL, // C source 
650   1,    // num ops
651   0,0,  // dest, bit instruction
652   1,0,  // branch, skip
653   0,    // literal operand
654   0,    // RAM access bit
655   0,    // fast call/return mode select bit
656   0,    // second memory operand
657   0,    // second literal operand
658   POC_NOP,
659   (PCC_REL_ADDR | PCC_OV),   // inCond
660   PCC_NONE , // outCond
661   PCI_MAGIC
662 };
663
664 pCodeInstruction pic16_pciBRA = { // mdubuc - New
665   {PC_OPCODE, NULL, NULL, 0, NULL, 
666    //   genericAnalyze,
667    genericDestruct,
668    genericPrint},
669   POC_BRA,
670   "BRA",
671   2,
672   NULL, // from branch
673   NULL, // to branch
674   NULL, // label
675   NULL, // operand
676   NULL, // flow block
677   NULL, // C source 
678   1,    // num ops
679   0,0,  // dest, bit instruction
680   1,0,  // branch, skip
681   0,    // literal operand
682   0,    // RAM access bit
683   0,    // fast call/return mode select bit
684   0,    // second memory operand
685   0,    // second literal operand
686   POC_NOP,
687   PCC_REL_ADDR,   // inCond
688   PCC_NONE   , // outCond
689   PCI_MAGIC
690 };
691
692 pCodeInstruction pic16_pciBSF = {
693   {PC_OPCODE, NULL, NULL, 0, NULL, 
694    //   genericAnalyze,
695    genericDestruct,
696    genericPrint},
697   POC_BSF,
698   "BSF",
699   2,
700   NULL, // from branch
701   NULL, // to branch
702   NULL, // label
703   NULL, // operand
704   NULL, // flow block
705   NULL, // C source 
706   3,    // num ops
707   1,1,  // dest, bit instruction
708   0,0,  // branch, skip
709   0,    // literal operand
710   1,    // RAM access bit
711   0,    // fast call/return mode select bit
712   0,    // second memory operand
713   0,    // second literal operand
714   POC_BCF,
715   (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
716   (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
717   PCI_MAGIC
718 };
719
720 pCodeInstruction pic16_pciBTFSC = {
721   {PC_OPCODE, NULL, NULL, 0, NULL, 
722    //   AnalyzeSKIP,
723    genericDestruct,
724    genericPrint},
725   POC_BTFSC,
726   "BTFSC",
727   2,
728   NULL, // from branch
729   NULL, // to branch
730   NULL, // label
731   NULL, // operand
732   NULL, // flow block
733   NULL, // C source 
734   3,    // num ops
735   0,1,  // dest, bit instruction
736   1,1,  // branch, skip
737   0,    // literal operand
738   1,    // RAM access bit
739   0,    // fast call/return mode select bit
740   0,    // second memory operand
741   0,    // second literal operand
742   POC_BTFSS,
743   (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
744   PCC_EXAMINE_PCOP, // outCond
745   PCI_MAGIC
746 };
747
748 pCodeInstruction pic16_pciBTFSS = {
749   {PC_OPCODE, NULL, NULL, 0, NULL, 
750    //   AnalyzeSKIP,
751    genericDestruct,
752    genericPrint},
753   POC_BTFSS,
754   "BTFSS",
755   2,
756   NULL, // from branch
757   NULL, // to branch
758   NULL, // label
759   NULL, // operand
760   NULL, // flow block
761   NULL, // C source 
762   3,    // num ops
763   0,1,  // dest, bit instruction
764   1,1,  // branch, skip
765   0,    // literal operand
766   1,    // RAM access bit
767   0,    // fast call/return mode select bit
768   0,    // second memory operand
769   0,    // second literal operand
770   POC_BTFSC,
771   (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
772   PCC_EXAMINE_PCOP, // outCond
773   PCI_MAGIC
774 };
775
776 pCodeInstruction pic16_pciBTG = { // mdubuc - New
777   {PC_OPCODE, NULL, NULL, 0, NULL, 
778    //   genericAnalyze,
779    genericDestruct,
780    genericPrint},
781   POC_BTG,
782   "BTG",
783   2,
784   NULL, // from branch
785   NULL, // to branch
786   NULL, // label
787   NULL, // operand
788   NULL, // flow block
789   NULL, // C source 
790   3,    // num ops
791   0,1,  // dest, bit instruction
792   0,0,  // branch, skip
793   0,    // literal operand
794   1,    // RAM access bit
795   0,    // fast call/return mode select bit
796   0,    // second memory operand
797   0,    // second literal operand
798   POC_NOP,
799   (PCC_REGISTER | PCC_EXAMINE_PCOP),   // inCond
800   (PCC_REGISTER | PCC_EXAMINE_PCOP), // outCond
801   PCI_MAGIC
802 };
803
804 pCodeInstruction pic16_pciBZ = { // mdubuc - New
805   {PC_OPCODE, NULL, NULL, 0, NULL, 
806    //   genericAnalyze,
807    genericDestruct,
808    genericPrint},
809   POC_BZ,
810   "BZ",
811   2,
812   NULL, // from branch
813   NULL, // to branch
814   NULL, // label
815   NULL, // operand
816   NULL, // flow block
817   NULL, // C source 
818   1,    // num ops
819   0,0,  // dest, bit instruction
820   1,0,  // branch, skip
821   0,    // literal operand
822   0,    // RAM access bit
823   0,    // fast call/return mode select bit
824   0,    // second memory operand
825   0,    // second literal operand
826   POC_NOP,
827   (PCC_REL_ADDR | PCC_Z),   // inCond
828   PCC_NONE, // outCond
829   PCI_MAGIC
830 };
831
832 pCodeInstruction pic16_pciCALL = {
833   {PC_OPCODE, NULL, NULL, 0, NULL, 
834    //   genericAnalyze,
835    genericDestruct,
836    genericPrint},
837   POC_CALL,
838   "CALL",
839   4,
840   NULL, // from branch
841   NULL, // to branch
842   NULL, // label
843   NULL, // operand
844   NULL, // flow block
845   NULL, // C source 
846   2,    // num ops
847   0,0,  // dest, bit instruction
848   1,0,  // branch, skip
849   0,    // literal operand
850   0,    // RAM access bit
851   1,    // fast call/return mode select bit
852   0,    // second memory operand
853   0,    // second literal operand
854   POC_NOP,
855   PCC_NONE, // inCond
856   PCC_NONE, // outCond
857   PCI_MAGIC
858 };
859
860 pCodeInstruction pic16_pciCOMF = {
861   {PC_OPCODE, NULL, NULL, 0, NULL, 
862    //   genericAnalyze,
863    genericDestruct,
864    genericPrint},
865   POC_COMF,
866   "COMF",
867   2,
868   NULL, // from branch
869   NULL, // to branch
870   NULL, // label
871   NULL, // operand
872   NULL, // flow block
873   NULL, // C source 
874   3,    // num ops
875   1,0,  // dest, bit instruction
876   0,0,  // branch, skip
877   0,    // literal operand
878   1,    // RAM access bit
879   0,    // fast call/return mode select bit
880   0,    // second memory operand
881   0,    // second literal operand
882   POC_NOP,
883   PCC_REGISTER,  // inCond
884   (PCC_REGISTER | PCC_Z | PCC_N) , // outCond
885   PCI_MAGIC
886 };
887
888 pCodeInstruction pic16_pciCOMFW = {
889   {PC_OPCODE, NULL, NULL, 0, NULL, 
890    //   genericAnalyze,
891    genericDestruct,
892    genericPrint},
893   POC_COMFW,
894   "COMF",
895   2,
896   NULL, // from branch
897   NULL, // to branch
898   NULL, // label
899   NULL, // operand
900   NULL, // flow block
901   NULL, // C source 
902   3,    // num ops
903   0,0,  // dest, bit instruction
904   0,0,  // branch, skip
905   0,    // literal operand
906   1,    // RAM access bit
907   0,    // fast call/return mode select bit
908   0,    // second memory operand
909   0,    // second literal operand
910   POC_NOP,
911   PCC_REGISTER,  // inCond
912   (PCC_W | PCC_Z | PCC_N) , // outCond
913   PCI_MAGIC
914 };
915
916 pCodeInstruction pic16_pciCLRF = {
917   {PC_OPCODE, NULL, NULL, 0, NULL, 
918    //   genericAnalyze,
919    genericDestruct,
920    genericPrint},
921   POC_CLRF,
922   "CLRF",
923   2,
924   NULL, // from branch
925   NULL, // to branch
926   NULL, // label
927   NULL, // operand
928   NULL, // flow block
929   NULL, // C source 
930   2,    // num ops
931   0,0,  // dest, bit instruction
932   0,0,  // branch, skip
933   0,    // literal operand
934   1,    // RAM access bit
935   0,    // fast call/return mode select bit
936   0,    // second memory operand
937   0,    // second literal operand
938   POC_NOP,
939   PCC_NONE, // inCond
940   (PCC_REGISTER | PCC_Z), // outCond
941   PCI_MAGIC
942 };
943
944 pCodeInstruction pic16_pciCLRWDT = {
945   {PC_OPCODE, NULL, NULL, 0, NULL, 
946    //   genericAnalyze,
947    genericDestruct,
948    genericPrint},
949   POC_CLRWDT,
950   "CLRWDT",
951   2,
952   NULL, // from branch
953   NULL, // to branch
954   NULL, // label
955   NULL, // operand
956   NULL, // flow block
957   NULL, // C source 
958   0,    // num ops
959   0,0,  // dest, bit instruction
960   0,0,  // branch, skip
961   0,    // literal operand
962   0,    // RAM access bit
963   0,    // fast call/return mode select bit
964   0,    // second memory operand
965   0,    // second literal operand
966   POC_NOP,
967   PCC_NONE, // inCond
968   PCC_NONE , // outCond
969   PCI_MAGIC
970 };
971
972 pCodeInstruction pic16_pciCPFSEQ = { // mdubuc - New
973   {PC_OPCODE, NULL, NULL, 0, NULL, 
974    //   genericAnalyze,
975    genericDestruct,
976    genericPrint},
977   POC_CPFSEQ,
978   "CPFSEQ",
979   2,
980   NULL, // from branch
981   NULL, // to branch
982   NULL, // label
983   NULL, // operand
984   NULL, // flow block
985   NULL, // C source 
986   2,    // num ops
987   0,0,  // dest, bit instruction
988   1,1,  // branch, skip
989   0,    // literal operand
990   1,    // RAM access bit
991   0,    // fast call/return mode select bit
992   0,    // second memory operand
993   0,    // second literal operand
994   POC_NOP,
995   (PCC_W | PCC_REGISTER), // inCond
996   PCC_NONE , // outCond
997   PCI_MAGIC
998 };
999
1000 pCodeInstruction pic16_pciCPFSGT = { // mdubuc - New
1001   {PC_OPCODE, NULL, NULL, 0, NULL, 
1002    //   genericAnalyze,
1003    genericDestruct,
1004    genericPrint},
1005   POC_CPFSGT,
1006   "CPFSGT",
1007   2,
1008   NULL, // from branch
1009   NULL, // to branch
1010   NULL, // label
1011   NULL, // operand
1012   NULL, // flow block
1013   NULL, // C source 
1014   2,    // num ops
1015   0,0,  // dest, bit instruction
1016   1,1,  // branch, skip
1017   0,    // literal operand
1018   1,    // RAM access bit
1019   0,    // fast call/return mode select bit
1020   0,    // second memory operand
1021   0,    // second literal operand
1022   POC_NOP,
1023   (PCC_W | PCC_REGISTER), // inCond
1024   PCC_NONE , // outCond
1025   PCI_MAGIC
1026 };
1027
1028 pCodeInstruction pic16_pciCPFSLT = { // mdubuc - New
1029   {PC_OPCODE, NULL, NULL, 0, NULL, 
1030    //   genericAnalyze,
1031    genericDestruct,
1032    genericPrint},
1033   POC_CPFSLT,
1034   "CPFSLT",
1035   2,
1036   NULL, // from branch
1037   NULL, // to branch
1038   NULL, // label
1039   NULL, // operand
1040   NULL, // flow block
1041   NULL, // C source 
1042   2,    // num ops
1043   1,0,  // dest, bit instruction
1044   1,1,  // branch, skip
1045   0,    // literal operand
1046   1,    // RAM access bit
1047   0,    // fast call/return mode select bit
1048   0,    // second memory operand
1049   0,    // second literal operand
1050   POC_NOP,
1051   (PCC_W | PCC_REGISTER), // inCond
1052   PCC_NONE , // outCond
1053   PCI_MAGIC
1054 };
1055
1056 pCodeInstruction pic16_pciDAW = {
1057   {PC_OPCODE, NULL, NULL, 0, NULL, 
1058    //   genericAnalyze,
1059    genericDestruct,
1060    genericPrint},
1061   POC_DAW,
1062   "DAW",
1063   2,
1064   NULL, // from branch
1065   NULL, // to branch
1066   NULL, // label
1067   NULL, // operand
1068   NULL, // flow block
1069   NULL, // C source 
1070   0,    // num ops
1071   0,0,  // dest, bit instruction
1072   0,0,  // branch, skip
1073   0,    // literal operand
1074   0,    // RAM access bit
1075   0,    // fast call/return mode select bit
1076   0,    // second memory operand
1077   0,    // second literal operand
1078   POC_NOP,
1079   PCC_W, // inCond
1080   (PCC_W | PCC_C), // outCond
1081   PCI_MAGIC
1082 };
1083
1084 pCodeInstruction pic16_pciDCFSNZ = { // mdubuc - New
1085   {PC_OPCODE, NULL, NULL, 0, NULL, 
1086    //   genericAnalyze,
1087    genericDestruct,
1088    genericPrint},
1089   POC_DCFSNZ,
1090   "DCFSNZ",
1091   2,
1092   NULL, // from branch
1093   NULL, // to branch
1094   NULL, // label
1095   NULL, // operand
1096   NULL, // flow block
1097   NULL, // C source 
1098   3,    // num ops
1099   1,0,  // dest, bit instruction
1100   1,1,  // branch, skip
1101   0,    // literal operand
1102   1,    // RAM access bit
1103   0,    // fast call/return mode select bit
1104   0,    // second memory operand
1105   0,    // second literal operand
1106   POC_NOP,
1107   PCC_REGISTER, // inCond
1108   PCC_REGISTER , // outCond
1109   PCI_MAGIC
1110 };
1111
1112 pCodeInstruction pic16_pciDCFSNZW = { // mdubuc - New
1113   {PC_OPCODE, NULL, NULL, 0, NULL, 
1114    //   genericAnalyze,
1115    genericDestruct,
1116    genericPrint},
1117   POC_DCFSNZW,
1118   "DCFSNZ",
1119   2,
1120   NULL, // from branch
1121   NULL, // to branch
1122   NULL, // label
1123   NULL, // operand
1124   NULL, // flow block
1125   NULL, // C source 
1126   3,    // num ops
1127   0,0,  // dest, bit instruction
1128   1,1,  // branch, skip
1129   0,    // literal operand
1130   1,    // RAM access bit
1131   0,    // fast call/return mode select bit
1132   0,    // second memory operand
1133   0,    // second literal operand
1134   POC_NOP,
1135   PCC_REGISTER, // inCond
1136   PCC_W , // outCond
1137   PCI_MAGIC
1138 };
1139
1140 pCodeInstruction pic16_pciDECF = {
1141   {PC_OPCODE, NULL, NULL, 0, NULL, 
1142    //   genericAnalyze,
1143    genericDestruct,
1144    genericPrint},
1145   POC_DECF,
1146   "DECF",
1147   2,
1148   NULL, // from branch
1149   NULL, // to branch
1150   NULL, // label
1151   NULL, // operand
1152   NULL, // flow block
1153   NULL, // C source 
1154   3,    // num ops
1155   1,0,  // dest, bit instruction
1156   0,0,  // branch, skip
1157   0,    // literal operand
1158   1,    // RAM access bit
1159   0,    // fast call/return mode select bit
1160   0,    // second memory operand
1161   0,    // second literal operand
1162   POC_NOP,
1163   PCC_REGISTER,   // inCond
1164   (PCC_REGISTER | PCC_STATUS)  , // outCond
1165   PCI_MAGIC
1166 };
1167
1168 pCodeInstruction pic16_pciDECFW = {
1169   {PC_OPCODE, NULL, NULL, 0, NULL, 
1170    //   genericAnalyze,
1171    genericDestruct,
1172    genericPrint},
1173   POC_DECFW,
1174   "DECF",
1175   2,
1176   NULL, // from branch
1177   NULL, // to branch
1178   NULL, // label
1179   NULL, // operand
1180   NULL, // flow block
1181   NULL, // C source 
1182   3,    // num ops
1183   0,0,  // dest, bit instruction
1184   0,0,  // branch, skip
1185   0,    // literal operand
1186   1,    // RAM access bit
1187   0,    // fast call/return mode select bit
1188   0,    // second memory operand
1189   0,    // second literal operand
1190   POC_NOP,
1191   PCC_REGISTER,   // inCond
1192   (PCC_W | PCC_STATUS)  , // outCond
1193   PCI_MAGIC
1194 };
1195
1196 pCodeInstruction pic16_pciDECFSZ = {
1197   {PC_OPCODE, NULL, NULL, 0, NULL, 
1198    //   AnalyzeSKIP,
1199    genericDestruct,
1200    genericPrint},
1201   POC_DECFSZ,
1202   "DECFSZ",
1203   2,
1204   NULL, // from branch
1205   NULL, // to branch
1206   NULL, // label
1207   NULL, // operand
1208   NULL, // flow block
1209   NULL, // C source 
1210   3,    // num ops
1211   1,0,  // dest, bit instruction
1212   1,1,  // branch, skip
1213   0,    // literal operand
1214   1,    // RAM access bit
1215   0,    // fast call/return mode select bit
1216   0,    // second memory operand
1217   0,    // second literal operand
1218   POC_NOP,
1219   PCC_REGISTER,   // inCond
1220   PCC_REGISTER   , // outCond
1221   PCI_MAGIC
1222 };
1223
1224 pCodeInstruction pic16_pciDECFSZW = {
1225   {PC_OPCODE, NULL, NULL, 0, NULL, 
1226    //   AnalyzeSKIP,
1227    genericDestruct,
1228    genericPrint},
1229   POC_DECFSZW,
1230   "DECFSZ",
1231   2,
1232   NULL, // from branch
1233   NULL, // to branch
1234   NULL, // label
1235   NULL, // operand
1236   NULL, // flow block
1237   NULL, // C source 
1238   3,    // num ops
1239   0,0,  // dest, bit instruction
1240   1,1,  // branch, skip
1241   0,    // literal operand
1242   1,    // RAM access bit
1243   0,    // fast call/return mode select bit
1244   0,    // second memory operand
1245   0,    // second literal operand
1246   POC_NOP,
1247   PCC_REGISTER,   // inCond
1248   PCC_W          , // outCond
1249   PCI_MAGIC
1250 };
1251
1252 pCodeInstruction pic16_pciGOTO = {
1253   {PC_OPCODE, NULL, NULL, 0, NULL, 
1254    //   AnalyzeGOTO,
1255    genericDestruct,
1256    genericPrint},
1257   POC_GOTO,
1258   "GOTO",
1259   4,
1260   NULL, // from branch
1261   NULL, // to branch
1262   NULL, // label
1263   NULL, // operand
1264   NULL, // flow block
1265   NULL, // C source 
1266   1,    // num ops
1267   0,0,  // dest, bit instruction
1268   1,0,  // branch, skip
1269   0,    // literal operand
1270   0,    // RAM access bit
1271   0,    // fast call/return mode select bit
1272   0,    // second memory operand
1273   0,    // second literal operand
1274   POC_NOP,
1275   PCC_REL_ADDR,   // inCond
1276   PCC_NONE   , // outCond
1277   PCI_MAGIC
1278 };
1279
1280 pCodeInstruction pic16_pciINCF = {
1281   {PC_OPCODE, NULL, NULL, 0, NULL, 
1282    //   genericAnalyze,
1283    genericDestruct,
1284    genericPrint},
1285   POC_INCF,
1286   "INCF",
1287   2,
1288   NULL, // from branch
1289   NULL, // to branch
1290   NULL, // label
1291   NULL, // operand
1292   NULL, // flow block
1293   NULL, // C source 
1294   3,    // num ops
1295   1,0,  // dest, bit instruction
1296   0,0,  // branch, skip
1297   0,    // literal operand
1298   1,    // RAM access bit
1299   0,    // fast call/return mode select bit
1300   0,    // second memory operand
1301   0,    // second literal operand
1302   POC_NOP,
1303   PCC_REGISTER,   // inCond
1304   (PCC_REGISTER | PCC_STATUS), // outCond
1305   PCI_MAGIC
1306 };
1307
1308 pCodeInstruction pic16_pciINCFW = {
1309   {PC_OPCODE, NULL, NULL, 0, NULL, 
1310    //   genericAnalyze,
1311    genericDestruct,
1312    genericPrint},
1313   POC_INCFW,
1314   "INCF",
1315   2,
1316   NULL, // from branch
1317   NULL, // to branch
1318   NULL, // label
1319   NULL, // operand
1320   NULL, // flow block
1321   NULL, // C source 
1322   3,    // num ops
1323   0,0,  // dest, bit instruction
1324   0,0,  // branch, skip
1325   0,    // literal operand
1326   1,    // RAM access bit
1327   0,    // fast call/return mode select bit
1328   0,    // second memory operand
1329   0,    // second literal operand
1330   POC_NOP,
1331   PCC_REGISTER,   // inCond
1332   (PCC_W | PCC_STATUS)  , // outCond
1333   PCI_MAGIC
1334 };
1335
1336 pCodeInstruction pic16_pciINCFSZ = {
1337   {PC_OPCODE, NULL, NULL, 0, NULL, 
1338    //   AnalyzeSKIP,
1339    genericDestruct,
1340    genericPrint},
1341   POC_INCFSZ,
1342   "INCFSZ",
1343   2,
1344   NULL, // from branch
1345   NULL, // to branch
1346   NULL, // label
1347   NULL, // operand
1348   NULL, // flow block
1349   NULL, // C source 
1350   3,    // num ops
1351   1,0,  // dest, bit instruction
1352   1,1,  // branch, skip
1353   0,    // literal operand
1354   1,    // RAM access bit
1355   0,    // fast call/return mode select bit
1356   0,    // second memory operand
1357   0,    // second literal operand
1358   POC_INFSNZ,
1359   PCC_REGISTER,   // inCond
1360   PCC_REGISTER   , // outCond
1361   PCI_MAGIC
1362 };
1363
1364 pCodeInstruction pic16_pciINCFSZW = {
1365   {PC_OPCODE, NULL, NULL, 0, NULL, 
1366    //   AnalyzeSKIP,
1367    genericDestruct,
1368    genericPrint},
1369   POC_INCFSZW,
1370   "INCFSZ",
1371   2,
1372   NULL, // from branch
1373   NULL, // to branch
1374   NULL, // label
1375   NULL, // operand
1376   NULL, // flow block
1377   NULL, // C source 
1378   3,    // num ops
1379   0,0,  // dest, bit instruction
1380   1,1,  // branch, skip
1381   0,    // literal operand
1382   1,    // RAM access bit
1383   0,    // fast call/return mode select bit
1384   0,    // second memory operand
1385   0,    // second literal operand
1386   POC_INFSNZW,
1387   PCC_REGISTER,   // inCond
1388   PCC_W          , // outCond
1389   PCI_MAGIC
1390 };
1391
1392 pCodeInstruction pic16_pciINFSNZ = { // mdubuc - New
1393   {PC_OPCODE, NULL, NULL, 0, NULL, 
1394    //   AnalyzeSKIP,
1395    genericDestruct,
1396    genericPrint},
1397   POC_INFSNZ,
1398   "INFSNZ",
1399   2,
1400   NULL, // from branch
1401   NULL, // to branch
1402   NULL, // label
1403   NULL, // operand
1404   NULL, // flow block
1405   NULL, // C source 
1406   3,    // num ops
1407   1,0,  // dest, bit instruction
1408   1,1,  // branch, skip
1409   0,    // literal operand
1410   1,    // RAM access bit
1411   0,    // fast call/return mode select bit
1412   0,    // second memory operand
1413   0,    // second literal operand
1414   POC_INCFSZ,
1415   PCC_REGISTER,   // inCond
1416   PCC_REGISTER   , // outCond
1417   PCI_MAGIC
1418 };
1419
1420 pCodeInstruction pic16_pciINFSNZW = { // vrokas - New
1421   {PC_OPCODE, NULL, NULL, 0, NULL, 
1422    //   AnalyzeSKIP,
1423    genericDestruct,
1424    genericPrint},
1425   POC_INFSNZW,
1426   "INFSNZ",
1427   2,
1428   NULL, // from branch
1429   NULL, // to branch
1430   NULL, // label
1431   NULL, // operand
1432   NULL, // flow block
1433   NULL, // C source 
1434   3,    // num ops
1435   0,0,  // dest, bit instruction
1436   1,1,  // branch, skip
1437   0,    // literal operand
1438   1,    // RAM access bit
1439   0,    // fast call/return mode select bit
1440   0,    // second memory operand
1441   0,    // second literal operand
1442   POC_INCFSZW,
1443   PCC_REGISTER,   // inCond
1444   PCC_W          , // outCond
1445   PCI_MAGIC
1446 };
1447
1448 pCodeInstruction pic16_pciIORWF = {
1449   {PC_OPCODE, NULL, NULL, 0, NULL, 
1450    //   genericAnalyze,
1451    genericDestruct,
1452    genericPrint},
1453   POC_IORWF,
1454   "IORWF",
1455   2,
1456   NULL, // from branch
1457   NULL, // to branch
1458   NULL, // label
1459   NULL, // operand
1460   NULL, // flow block
1461   NULL, // C source 
1462   3,    // num ops
1463   1,0,  // dest, bit instruction
1464   0,0,  // branch, skip
1465   0,    // literal operand
1466   1,    // RAM access bit
1467   0,    // fast call/return mode select bit
1468   0,    // second memory operand
1469   0,    // second literal operand
1470   POC_NOP,
1471   (PCC_W | PCC_REGISTER),   // inCond
1472   (PCC_REGISTER | PCC_Z | PCC_N), // outCond
1473   PCI_MAGIC
1474 };
1475
1476 pCodeInstruction pic16_pciIORFW = {
1477   {PC_OPCODE, NULL, NULL, 0, NULL, 
1478    //   genericAnalyze,
1479    genericDestruct,
1480    genericPrint},
1481   POC_IORFW,
1482   "IORWF",
1483   2,
1484   NULL, // from branch
1485   NULL, // to branch
1486   NULL, // label
1487   NULL, // operand
1488   NULL, // flow block
1489   NULL, // C source 
1490   3,    // num ops
1491   0,0,  // dest, bit instruction
1492   0,0,  // branch, skip
1493   0,    // literal operand
1494   1,    // RAM access bit
1495   0,    // fast call/return mode select bit
1496   0,    // second memory operand
1497   0,    // second literal operand
1498   POC_NOP,
1499   (PCC_W | PCC_REGISTER),   // inCond
1500   (PCC_W | PCC_Z | PCC_N), // outCond
1501   PCI_MAGIC
1502 };
1503
1504 pCodeInstruction pic16_pciIORLW = {
1505   {PC_OPCODE, NULL, NULL, 0, NULL, 
1506    //   genericAnalyze,
1507    genericDestruct,
1508    genericPrint},
1509   POC_IORLW,
1510   "IORLW",
1511   2,
1512   NULL, // from branch
1513   NULL, // to branch
1514   NULL, // label
1515   NULL, // operand
1516   NULL, // flow block
1517   NULL, // C source 
1518   1,    // num ops
1519   0,0,  // dest, bit instruction
1520   0,0,  // branch, skip
1521   1,    // literal operand
1522   0,    // RAM access bit
1523   0,    // fast call/return mode select bit
1524   0,    // second memory operand
1525   0,    // second literal operand
1526   POC_NOP,
1527   (PCC_W | PCC_LITERAL),   // inCond
1528   (PCC_W | PCC_Z | PCC_N), // outCond
1529   PCI_MAGIC
1530 };
1531
1532 pCodeInstruction pic16_pciLFSR = { // mdubuc - New
1533   {PC_OPCODE, NULL, NULL, 0, NULL, 
1534    //   genericAnalyze,
1535    genericDestruct,
1536    genericPrint},
1537   POC_LFSR,
1538   "LFSR",
1539   4,
1540   NULL, // from branch
1541   NULL, // to branch
1542   NULL, // label
1543   NULL, // operand
1544   NULL, // flow block
1545   NULL, // C source 
1546   2,    // num ops
1547   0,0,  // dest, bit instruction
1548   0,0,  // branch, skip
1549   1,    // literal operand
1550   0,    // RAM access bit
1551   0,    // fast call/return mode select bit
1552   0,    // second memory operand
1553   1,    // second literal operand
1554   POC_NOP,
1555   PCC_LITERAL, // inCond
1556   PCC_NONE, // outCond
1557   PCI_MAGIC
1558 };
1559
1560 pCodeInstruction pic16_pciMOVF = {
1561   {PC_OPCODE, NULL, NULL, 0, NULL, 
1562    //   genericAnalyze,
1563    genericDestruct,
1564    genericPrint},
1565   POC_MOVF,
1566   "MOVF",
1567   2,
1568   NULL, // from branch
1569   NULL, // to branch
1570   NULL, // label
1571   NULL, // operand
1572   NULL, // flow block
1573   NULL, // C source 
1574   3,    // num ops
1575   1,0,  // dest, bit instruction
1576   0,0,  // branch, skip
1577   0,    // literal operand
1578   1,    // RAM access bit
1579   0,    // fast call/return mode select bit
1580   0,    // second memory operand
1581   0,    // second literal operand
1582   POC_NOP,
1583   PCC_REGISTER,   // inCond
1584   (PCC_Z | PCC_N), // outCond
1585   PCI_MAGIC
1586 };
1587
1588 pCodeInstruction pic16_pciMOVFW = {
1589   {PC_OPCODE, NULL, NULL, 0, NULL, 
1590    //   genericAnalyze,
1591    genericDestruct,
1592    genericPrint},
1593   POC_MOVFW,
1594   "MOVF",
1595   2,
1596   NULL, // from branch
1597   NULL, // to branch
1598   NULL, // label
1599   NULL, // operand
1600   NULL, // flow block
1601   NULL, // C source 
1602   3,    // num ops
1603   0,0,  // dest, bit instruction
1604   0,0,  // branch, skip
1605   0,    // literal operand
1606   1,    // RAM access bit
1607   0,    // fast call/return mode select bit
1608   0,    // second memory operand
1609   0,    // second literal operand
1610   POC_NOP,
1611   PCC_REGISTER,   // inCond
1612   (PCC_W | PCC_N | PCC_Z), // outCond
1613   PCI_MAGIC
1614 };
1615
1616 pCodeInstruction pic16_pciMOVFF = { // mdubuc - New
1617   {PC_OPCODE, NULL, NULL, 0, NULL, 
1618    //   genericAnalyze,
1619    genericDestruct,
1620    genericPrint},
1621   POC_MOVFF,
1622   "MOVFF",
1623   4,
1624   NULL, // from branch
1625   NULL, // to branch
1626   NULL, // label
1627   NULL, // operand
1628   NULL, // flow block
1629   NULL, // C source 
1630   2,    // num ops
1631   0,0,  // dest, bit instruction
1632   0,0,  // branch, skip
1633   0,    // literal operand
1634   0,    // RAM access bit
1635   0,    // fast call/return mode select bit
1636   1,    // second memory operand
1637   0,    // second literal operand
1638   POC_NOP,
1639   PCC_REGISTER,   // inCond
1640   PCC_REGISTER2, // outCond
1641   PCI_MAGIC
1642 };
1643
1644 pCodeInstruction pic16_pciMOVLB = { // mdubuc - New
1645   {PC_OPCODE, NULL, NULL, 0, NULL, 
1646    genericDestruct,
1647    genericPrint},
1648   POC_MOVLB,
1649   "MOVLB",
1650   2,
1651   NULL, // from branch
1652   NULL, // to branch
1653   NULL, // label
1654   NULL, // operand
1655   NULL, // flow block
1656   NULL, // C source 
1657   1,    // num ops
1658   0,0,  // dest, bit instruction
1659   0,0,  // branch, skip
1660   1,    // literal operand
1661   0,    // RAM access bit
1662   0,    // fast call/return mode select bit
1663   0,    // second memory operand
1664   0,    // second literal operand
1665   POC_NOP,
1666   (PCC_NONE | PCC_LITERAL),   // inCond
1667   PCC_REGISTER, // outCond - BSR
1668   PCI_MAGIC
1669 };
1670
1671 pCodeInstruction pic16_pciMOVLW = {
1672   {PC_OPCODE, NULL, NULL, 0, NULL, 
1673    genericDestruct,
1674    genericPrint},
1675   POC_MOVLW,
1676   "MOVLW",
1677   2,
1678   NULL, // from branch
1679   NULL, // to branch
1680   NULL, // label
1681   NULL, // operand
1682   NULL, // flow block
1683   NULL, // C source 
1684   1,    // num ops
1685   0,0,  // dest, bit instruction
1686   0,0,  // branch, skip
1687   1,    // literal operand
1688   0,    // RAM access bit
1689   0,    // fast call/return mode select bit
1690   0,    // second memory operand
1691   0,    // second literal operand
1692   POC_NOP,
1693   (PCC_NONE | PCC_LITERAL),   // inCond
1694   PCC_W, // outCond
1695   PCI_MAGIC
1696 };
1697
1698 pCodeInstruction pic16_pciMOVWF = {
1699   {PC_OPCODE, NULL, NULL, 0, NULL, 
1700    //   genericAnalyze,
1701    genericDestruct,
1702    genericPrint},
1703   POC_MOVWF,
1704   "MOVWF",
1705   2,
1706   NULL, // from branch
1707   NULL, // to branch
1708   NULL, // label
1709   NULL, // operand
1710   NULL, // flow block
1711   NULL, // C source 
1712   2,    // num ops
1713   0,0,  // dest, bit instruction
1714   0,0,  // branch, skip
1715   0,    // literal operand
1716   1,    // RAM access bit
1717   0,    // fast call/return mode select bit
1718   0,    // second memory operand
1719   0,    // second literal operand
1720   POC_NOP,
1721   PCC_W,   // inCond
1722   PCC_REGISTER, // outCond
1723   PCI_MAGIC
1724 };
1725
1726 pCodeInstruction pic16_pciMULLW = { // mdubuc - New
1727   {PC_OPCODE, NULL, NULL, 0, NULL, 
1728    genericDestruct,
1729    genericPrint},
1730   POC_MULLW,
1731   "MULLW",
1732   2,
1733   NULL, // from branch
1734   NULL, // to branch
1735   NULL, // label
1736   NULL, // operand
1737   NULL, // flow block
1738   NULL, // C source 
1739   1,    // num ops
1740   0,0,  // dest, bit instruction
1741   0,0,  // branch, skip
1742   1,    // literal operand
1743   0,    // RAM access bit
1744   0,    // fast call/return mode select bit
1745   0,    // second memory operand
1746   0,    // second literal operand
1747   POC_NOP,
1748   (PCC_W | PCC_LITERAL),   // inCond
1749   PCC_NONE, // outCond - PROD
1750   PCI_MAGIC
1751 };
1752
1753 pCodeInstruction pic16_pciMULWF = { // mdubuc - New
1754   {PC_OPCODE, NULL, NULL, 0, NULL, 
1755    genericDestruct,
1756    genericPrint},
1757   POC_MULWF,
1758   "MULWF",
1759   2,
1760   NULL, // from branch
1761   NULL, // to branch
1762   NULL, // label
1763   NULL, // operand
1764   NULL, // flow block
1765   NULL, // C source 
1766   2,    // num ops
1767   0,0,  // dest, bit instruction
1768   0,0,  // branch, skip
1769   0,    // literal operand
1770   1,    // RAM access bit
1771   0,    // fast call/return mode select bit
1772   0,    // second memory operand
1773   0,    // second literal operand
1774   POC_NOP,
1775   (PCC_W | PCC_REGISTER),   // inCond
1776   PCC_REGISTER, // outCond - PROD
1777   PCI_MAGIC
1778 };
1779
1780 pCodeInstruction pic16_pciNEGF = { // mdubuc - New
1781   {PC_OPCODE, NULL, NULL, 0, NULL, 
1782    genericDestruct,
1783    genericPrint},
1784   POC_NEGF,
1785   "NEGF",
1786   2,
1787   NULL, // from branch
1788   NULL, // to branch
1789   NULL, // label
1790   NULL, // operand
1791   NULL, // flow block
1792   NULL, // C source 
1793   2,    // num ops
1794   0,0,  // dest, bit instruction
1795   0,0,  // branch, skip
1796   0,    // literal operand
1797   1,    // RAM access bit
1798   0,    // fast call/return mode select bit
1799   0,    // second memory operand
1800   0,    // second literal operand
1801   POC_NOP,
1802   PCC_REGISTER, // inCond
1803   (PCC_REGISTER | PCC_STATUS), // outCond
1804   PCI_MAGIC
1805 };
1806
1807 pCodeInstruction pic16_pciNOP = {
1808   {PC_OPCODE, NULL, NULL, 0, NULL, 
1809    genericDestruct,
1810    genericPrint},
1811   POC_NOP,
1812   "NOP",
1813   2,
1814   NULL, // from branch
1815   NULL, // to branch
1816   NULL, // label
1817   NULL, // operand
1818   NULL, // flow block
1819   NULL, // C source 
1820   0,    // num ops
1821   0,0,  // dest, bit instruction
1822   0,0,  // branch, skip
1823   0,    // literal operand
1824   0,    // RAM access bit
1825   0,    // fast call/return mode select bit
1826   0,    // second memory operand
1827   0,    // second literal operand
1828   POC_NOP,
1829   PCC_NONE,   // inCond
1830   PCC_NONE, // outCond
1831   PCI_MAGIC
1832 };
1833
1834 pCodeInstruction pic16_pciPOP = { // mdubuc - New
1835   {PC_OPCODE, NULL, NULL, 0, NULL, 
1836    genericDestruct,
1837    genericPrint},
1838   POC_POP,
1839   "POP",
1840   2,
1841   NULL, // from branch
1842   NULL, // to branch
1843   NULL, // label
1844   NULL, // operand
1845   NULL, // flow block
1846   NULL, // C source 
1847   0,    // num ops
1848   0,0,  // dest, bit instruction
1849   0,0,  // branch, skip
1850   0,    // literal operand
1851   0,    // RAM access bit
1852   0,    // fast call/return mode select bit
1853   0,    // second memory operand
1854   0,    // second literal operand
1855   POC_NOP,
1856   PCC_NONE,  // inCond
1857   PCC_NONE  , // outCond
1858   PCI_MAGIC
1859 };
1860
1861 pCodeInstruction pic16_pciPUSH = {
1862   {PC_OPCODE, NULL, NULL, 0, NULL, 
1863    genericDestruct,
1864    genericPrint},
1865   POC_PUSH,
1866   "PUSH",
1867   2,
1868   NULL, // from branch
1869   NULL, // to branch
1870   NULL, // label
1871   NULL, // operand
1872   NULL, // flow block
1873   NULL, // C source 
1874   0,    // num ops
1875   0,0,  // dest, bit instruction
1876   0,0,  // branch, skip
1877   0,    // literal operand
1878   0,    // RAM access bit
1879   0,    // fast call/return mode select bit
1880   0,    // second memory operand
1881   0,    // second literal operand
1882   POC_NOP,
1883   PCC_NONE,  // inCond
1884   PCC_NONE  , // outCond
1885   PCI_MAGIC
1886 };
1887
1888 pCodeInstruction pic16_pciRCALL = { // mdubuc - New
1889   {PC_OPCODE, NULL, NULL, 0, NULL, 
1890    genericDestruct,
1891    genericPrint},
1892   POC_RCALL,
1893   "RCALL",
1894   2,
1895   NULL, // from branch
1896   NULL, // to branch
1897   NULL, // label
1898   NULL, // operand
1899   NULL, // flow block
1900   NULL, // C source 
1901   1,    // num ops
1902   0,0,  // dest, bit instruction
1903   1,0,  // branch, skip
1904   0,    // literal operand
1905   0,    // RAM access bit
1906   0,    // fast call/return mode select bit
1907   0,    // second memory operand
1908   0,    // second literal operand
1909   POC_NOP,
1910   PCC_REL_ADDR,  // inCond
1911   PCC_NONE  , // outCond
1912   PCI_MAGIC
1913 };
1914
1915 pCodeInstruction pic16_pciRETFIE = {
1916   {PC_OPCODE, NULL, NULL, 0, NULL, 
1917    //   AnalyzeRETURN,
1918    genericDestruct,
1919    genericPrint},
1920   POC_RETFIE,
1921   "RETFIE",
1922   2,
1923   NULL, // from branch
1924   NULL, // to branch
1925   NULL, // label
1926   NULL, // operand
1927   NULL, // flow block
1928   NULL, // C source 
1929   1,    // num ops
1930   0,0,  // dest, bit instruction
1931   1,0,  // branch, skip
1932   0,    // literal operand
1933   0,    // RAM access bit
1934   1,    // fast call/return mode select bit
1935   0,    // second memory operand
1936   0,    // second literal operand
1937   POC_NOP,
1938   PCC_NONE,   // inCond
1939   PCC_NONE,    // outCond (not true... affects the GIE bit too)
1940   PCI_MAGIC
1941 };
1942
1943 pCodeInstruction pic16_pciRETLW = {
1944   {PC_OPCODE, NULL, NULL, 0, NULL, 
1945    //   AnalyzeRETURN,
1946    genericDestruct,
1947    genericPrint},
1948   POC_RETLW,
1949   "RETLW",
1950   2,
1951   NULL, // from branch
1952   NULL, // to branch
1953   NULL, // label
1954   NULL, // operand
1955   NULL, // flow block
1956   NULL, // C source 
1957   1,    // num ops
1958   0,0,  // dest, bit instruction
1959   1,0,  // branch, skip
1960   1,    // literal operand
1961   0,    // RAM access bit
1962   0,    // fast call/return mode select bit
1963   0,    // second memory operand
1964   0,    // second literal operand
1965   POC_NOP,
1966   PCC_LITERAL,   // inCond
1967   PCC_W, // outCond
1968   PCI_MAGIC
1969 };
1970
1971 pCodeInstruction pic16_pciRETURN = {
1972   {PC_OPCODE, NULL, NULL, 0, NULL, 
1973    //   AnalyzeRETURN,
1974    genericDestruct,
1975    genericPrint},
1976   POC_RETURN,
1977   "RETURN",
1978   2,
1979   NULL, // from branch
1980   NULL, // to branch
1981   NULL, // label
1982   NULL, // operand
1983   NULL, // flow block
1984   NULL, // C source 
1985   1,    // num ops
1986   0,0,  // dest, bit instruction
1987   1,0,  // branch, skip
1988   0,    // literal operand
1989   0,    // RAM access bit
1990   1,    // fast call/return mode select bit
1991   0,    // second memory operand
1992   0,    // second literal operand
1993   POC_NOP,
1994   PCC_NONE,   // inCond
1995   PCC_NONE, // outCond
1996   PCI_MAGIC
1997 };
1998 pCodeInstruction pic16_pciRLCF = { // mdubuc - New
1999   {PC_OPCODE, NULL, NULL, 0, NULL, 
2000    //   genericAnalyze,
2001    genericDestruct,
2002    genericPrint},
2003   POC_RLCF,
2004   "RLCF",
2005   2,
2006   NULL, // from branch
2007   NULL, // to branch
2008   NULL, // label
2009   NULL, // operand
2010   NULL, // flow block
2011   NULL, // C source 
2012   3,    // num ops
2013   1,0,  // dest, bit instruction
2014   0,0,  // branch, skip
2015   0,    // literal operand
2016   1,    // RAM access bit
2017   0,    // fast call/return mode select bit
2018   0,    // second memory operand
2019   0,    // second literal operand
2020   POC_NOP,
2021   (PCC_C | PCC_REGISTER),   // inCond
2022   (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
2023   PCI_MAGIC
2024 };
2025
2026 pCodeInstruction pic16_pciRLCFW = { // mdubuc - New
2027   {PC_OPCODE, NULL, NULL, 0, NULL, 
2028    //   genericAnalyze,
2029    genericDestruct,
2030    genericPrint},
2031   POC_RLCFW,
2032   "RLCF",
2033   2,
2034   NULL, // from branch
2035   NULL, // to branch
2036   NULL, // label
2037   NULL, // operand
2038   NULL, // flow block
2039   NULL, // C source 
2040   3,    // num ops
2041   0,0,  // dest, bit instruction
2042   0,0,  // branch, skip
2043   0,    // literal operand
2044   1,    // RAM access bit
2045   0,    // fast call/return mode select bit
2046   0,    // second memory operand
2047   0,    // second literal operand
2048   POC_NOP,
2049   (PCC_C | PCC_REGISTER),   // inCond
2050   (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2051   PCI_MAGIC
2052 };
2053
2054 pCodeInstruction pic16_pciRLNCF = { // mdubuc - New
2055   {PC_OPCODE, NULL, NULL, 0, NULL, 
2056    //   genericAnalyze,
2057    genericDestruct,
2058    genericPrint},
2059   POC_RLNCF,
2060   "RLNCF",
2061   2,
2062   NULL, // from branch
2063   NULL, // to branch
2064   NULL, // label
2065   NULL, // operand
2066   NULL, // flow block
2067   NULL, // C source 
2068   3,    // num ops
2069   1,0,  // dest, bit instruction
2070   0,0,  // branch, skip
2071   0,    // literal operand
2072   1,    // RAM access bit
2073   0,    // fast call/return mode select bit
2074   0,    // second memory operand
2075   0,    // second literal operand
2076   POC_NOP,
2077   PCC_REGISTER,   // inCond
2078   (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2079   PCI_MAGIC
2080 };
2081 pCodeInstruction pic16_pciRLNCFW = { // mdubuc - New
2082   {PC_OPCODE, NULL, NULL, 0, NULL, 
2083    //   genericAnalyze,
2084    genericDestruct,
2085    genericPrint},
2086   POC_RLNCFW,
2087   "RLNCF",
2088   2,
2089   NULL, // from branch
2090   NULL, // to branch
2091   NULL, // label
2092   NULL, // operand
2093   NULL, // flow block
2094   NULL, // C source 
2095   3,    // num ops
2096   0,0,  // dest, bit instruction
2097   0,0,  // branch, skip
2098   0,    // literal operand
2099   1,    // RAM access bit
2100   0,    // fast call/return mode select bit
2101   0,    // second memory operand
2102   0,    // second literal operand
2103   POC_NOP,
2104   PCC_REGISTER,   // inCond
2105   (PCC_W | PCC_Z | PCC_N), // outCond
2106   PCI_MAGIC
2107 };
2108 pCodeInstruction pic16_pciRRCF = { // mdubuc - New
2109   {PC_OPCODE, NULL, NULL, 0, NULL, 
2110    //   genericAnalyze,
2111    genericDestruct,
2112    genericPrint},
2113   POC_RRCF,
2114   "RRCF",
2115   2,
2116   NULL, // from branch
2117   NULL, // to branch
2118   NULL, // label
2119   NULL, // operand
2120   NULL, // flow block
2121   NULL, // C source 
2122   3,    // num ops
2123   1,0,  // dest, bit instruction
2124   0,0,  // branch, skip
2125   0,    // literal operand
2126   1,    // RAM access bit
2127   0,    // fast call/return mode select bit
2128   0,    // second memory operand
2129   0,    // second literal operand
2130   POC_NOP,
2131   (PCC_C | PCC_REGISTER),   // inCond
2132   (PCC_REGISTER | PCC_C | PCC_Z | PCC_N), // outCond
2133   PCI_MAGIC
2134 };
2135 pCodeInstruction pic16_pciRRCFW = { // mdubuc - New
2136   {PC_OPCODE, NULL, NULL, 0, NULL, 
2137    //   genericAnalyze,
2138    genericDestruct,
2139    genericPrint},
2140   POC_RRCFW,
2141   "RRCF",
2142   2,
2143   NULL, // from branch
2144   NULL, // to branch
2145   NULL, // label
2146   NULL, // operand
2147   NULL, // flow block
2148   NULL, // C source 
2149   3,    // num ops
2150   0,0,  // dest, bit instruction
2151   0,0,  // branch, skip
2152   0,    // literal operand
2153   1,    // RAM access bit
2154   0,    // fast call/return mode select bit
2155   0,    // second memory operand
2156   0,    // second literal operand
2157   POC_NOP,
2158   (PCC_C | PCC_REGISTER),   // inCond
2159   (PCC_W | PCC_C | PCC_Z | PCC_N), // outCond
2160   PCI_MAGIC
2161 };
2162 pCodeInstruction pic16_pciRRNCF = { // mdubuc - New
2163   {PC_OPCODE, NULL, NULL, 0, NULL, 
2164    //   genericAnalyze,
2165    genericDestruct,
2166    genericPrint},
2167   POC_RRNCF,
2168   "RRNCF",
2169   2,
2170   NULL, // from branch
2171   NULL, // to branch
2172   NULL, // label
2173   NULL, // operand
2174   NULL, // flow block
2175   NULL, // C source 
2176   3,    // num ops
2177   1,0,  // dest, bit instruction
2178   0,0,  // branch, skip
2179   0,    // literal operand
2180   1,    // RAM access bit
2181   0,    // fast call/return mode select bit
2182   0,    // second memory operand
2183   0,    // second literal operand
2184   POC_NOP,
2185   PCC_REGISTER,   // inCond
2186   (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2187   PCI_MAGIC
2188 };
2189
2190 pCodeInstruction pic16_pciRRNCFW = { // mdubuc - New
2191   {PC_OPCODE, NULL, NULL, 0, NULL, 
2192    //   genericAnalyze,
2193    genericDestruct,
2194    genericPrint},
2195   POC_RRNCFW,
2196   "RRNCF",
2197   2,
2198   NULL, // from branch
2199   NULL, // to branch
2200   NULL, // label
2201   NULL, // operand
2202   NULL, // flow block
2203   NULL, // C source 
2204   3,    // num ops
2205   0,0,  // dest, bit instruction
2206   0,0,  // branch, skip
2207   0,    // literal operand
2208   1,    // RAM access bit
2209   0,    // fast call/return mode select bit
2210   0,    // second memory operand
2211   0,    // second literal operand
2212   POC_NOP,
2213   PCC_REGISTER,   // inCond
2214   (PCC_W | PCC_Z | PCC_N), // outCond
2215   PCI_MAGIC
2216 };
2217
2218 pCodeInstruction pic16_pciSETF = { // mdubuc - New
2219   {PC_OPCODE, NULL, NULL, 0, NULL, 
2220    //   genericAnalyze,
2221    genericDestruct,
2222    genericPrint},
2223   POC_SETF,
2224   "SETF",
2225   2,
2226   NULL, // from branch
2227   NULL, // to branch
2228   NULL, // label
2229   NULL, // operand
2230   NULL, // flow block
2231   NULL, // C source 
2232   2,    // num ops
2233   0,0,  // dest, bit instruction
2234   0,0,  // branch, skip
2235   0,    // literal operand
2236   1,    // RAM access bit
2237   0,    // fast call/return mode select bit
2238   0,    // second memory operand
2239   0,    // second literal operand
2240   POC_NOP,
2241   PCC_NONE,  // inCond
2242   PCC_REGISTER  , // outCond
2243   PCI_MAGIC
2244 };
2245
2246 pCodeInstruction pic16_pciSUBLW = {
2247   {PC_OPCODE, NULL, NULL, 0, NULL, 
2248    //   genericAnalyze,
2249    genericDestruct,
2250    genericPrint},
2251   POC_SUBLW,
2252   "SUBLW",
2253   2,
2254   NULL, // from branch
2255   NULL, // to branch
2256   NULL, // label
2257   NULL, // operand
2258   NULL, // flow block
2259   NULL, // C source 
2260   1,    // num ops
2261   0,0,  // dest, bit instruction
2262   0,0,  // branch, skip
2263   1,    // literal operand
2264   0,    // RAM access bit
2265   0,    // fast call/return mode select bit
2266   0,    // second memory operand
2267   0,    // second literal operand
2268   POC_NOP,
2269   (PCC_W | PCC_LITERAL),   // inCond
2270   (PCC_W | PCC_STATUS), // outCond
2271   PCI_MAGIC
2272 };
2273
2274 pCodeInstruction pic16_pciSUBFWB = {
2275   {PC_OPCODE, NULL, NULL, 0, NULL, 
2276    //   genericAnalyze,
2277    genericDestruct,
2278    genericPrint},
2279   POC_SUBFWB,
2280   "SUBFWB",
2281   2,
2282   NULL, // from branch
2283   NULL, // to branch
2284   NULL, // label
2285   NULL, // operand
2286   NULL, // flow block
2287   NULL, // C source 
2288   3,    // num ops
2289   1,0,  // dest, bit instruction
2290   0,0,  // branch, skip
2291   0,    // literal operand
2292   1,    // RAM access bit
2293   0,    // fast call/return mode select bit
2294   0,    // second memory operand
2295   0,    // second literal operand
2296   POC_NOP,
2297   (PCC_W | PCC_REGISTER | PCC_C),   // inCond
2298   (PCC_W | PCC_STATUS), // outCond
2299   PCI_MAGIC
2300 };
2301
2302 pCodeInstruction pic16_pciSUBWF = {
2303   {PC_OPCODE, NULL, NULL, 0, NULL, 
2304    //   genericAnalyze,
2305    genericDestruct,
2306    genericPrint},
2307   POC_SUBWF,
2308   "SUBWF",
2309   2,
2310   NULL, // from branch
2311   NULL, // to branch
2312   NULL, // label
2313   NULL, // operand
2314   NULL, // flow block
2315   NULL, // C source 
2316   3,    // num ops
2317   1,0,  // dest, bit instruction
2318   0,0,  // branch, skip
2319   0,    // literal operand
2320   1,    // RAM access bit
2321   0,    // fast call/return mode select bit
2322   0,    // second memory operand
2323   0,    // second literal operand
2324   POC_NOP,
2325   (PCC_W | PCC_REGISTER),   // inCond
2326   (PCC_REGISTER | PCC_STATUS), // outCond
2327   PCI_MAGIC
2328 };
2329
2330 pCodeInstruction pic16_pciSUBFW = {
2331   {PC_OPCODE, NULL, NULL, 0, NULL, 
2332    //   genericAnalyze,
2333    genericDestruct,
2334    genericPrint},
2335   POC_SUBFW,
2336   "SUBWF",
2337   2,
2338   NULL, // from branch
2339   NULL, // to branch
2340   NULL, // label
2341   NULL, // operand
2342   NULL, // flow block
2343   NULL, // C source 
2344   3,    // num ops
2345   0,0,  // dest, bit instruction
2346   0,0,  // branch, skip
2347   0,    // literal operand
2348   1,    // RAM access bit
2349   0,    // fast call/return mode select bit
2350   0,    // second memory operand
2351   0,    // second literal operand
2352   POC_NOP,
2353   (PCC_W | PCC_REGISTER),   // inCond
2354   (PCC_W | PCC_STATUS), // outCond
2355   PCI_MAGIC
2356 };
2357
2358 pCodeInstruction pic16_pciSUBFWB_D1 = { // mdubuc - New
2359   {PC_OPCODE, NULL, NULL, 0, NULL, 
2360    //   genericAnalyze,
2361    genericDestruct,
2362    genericPrint},
2363   POC_SUBFWB_D1,
2364   "SUBFWB",
2365   2,
2366   NULL, // from branch
2367   NULL, // to branch
2368   NULL, // label
2369   NULL, // operand
2370   NULL, // flow block
2371   NULL, // C source 
2372   3,    // num ops
2373   1,0,  // dest, bit instruction
2374   0,0,  // branch, skip
2375   0,    // literal operand
2376   1,    // RAM access bit
2377   0,    // fast call/return mode select bit
2378   0,    // second memory operand
2379   0,    // second literal operand
2380   POC_NOP,
2381   (PCC_W | PCC_REGISTER | PCC_C),   // inCond
2382   (PCC_REGISTER | PCC_STATUS), // outCond
2383   PCI_MAGIC
2384 };
2385
2386 pCodeInstruction pic16_pciSUBFWB_D0 = { // mdubuc - New
2387   {PC_OPCODE, NULL, NULL, 0, NULL, 
2388    //   genericAnalyze,
2389    genericDestruct,
2390    genericPrint},
2391   POC_SUBFWB_D0,
2392   "SUBFWB",
2393   2,
2394   NULL, // from branch
2395   NULL, // to branch
2396   NULL, // label
2397   NULL, // operand
2398   NULL, // flow block
2399   NULL, // C source 
2400   3,    // num ops
2401   0,0,  // dest, bit instruction
2402   0,0,  // branch, skip
2403   0,    // literal operand
2404   1,    // RAM access bit
2405   0,    // fast call/return mode select bit
2406   0,    // second memory operand
2407   0,    // second literal operand
2408   POC_NOP,
2409   (PCC_W | PCC_REGISTER | PCC_C),   // inCond
2410   (PCC_W | PCC_STATUS), // outCond
2411   PCI_MAGIC
2412 };
2413
2414 pCodeInstruction pic16_pciSUBWFB_D1 = { // mdubuc - New
2415   {PC_OPCODE, NULL, NULL, 0, NULL, 
2416    //   genericAnalyze,
2417    genericDestruct,
2418    genericPrint},
2419   POC_SUBWFB_D1,
2420   "SUBWFB",
2421   2,
2422   NULL, // from branch
2423   NULL, // to branch
2424   NULL, // label
2425   NULL, // operand
2426   NULL, // flow block
2427   NULL, // C source 
2428   3,    // num ops
2429   1,0,  // dest, bit instruction
2430   0,0,  // branch, skip
2431   0,    // literal operand
2432   1,    // RAM access bit
2433   0,    // fast call/return mode select bit
2434   0,    // second memory operand
2435   0,    // second literal operand
2436   POC_NOP,
2437   (PCC_W | PCC_REGISTER | PCC_C),   // inCond
2438   (PCC_REGISTER | PCC_STATUS), // outCond
2439   PCI_MAGIC
2440 };
2441
2442 pCodeInstruction pic16_pciSUBWFB_D0 = { // mdubuc - New
2443   {PC_OPCODE, NULL, NULL, 0, NULL, 
2444    //   genericAnalyze,
2445    genericDestruct,
2446    genericPrint},
2447   POC_SUBWFB_D0,
2448   "SUBWFB",
2449   2,
2450   NULL, // from branch
2451   NULL, // to branch
2452   NULL, // label
2453   NULL, // operand
2454   NULL, // flow block
2455   NULL, // C source 
2456   3,    // num ops
2457   0,0,  // dest, bit instruction
2458   0,0,  // branch, skip
2459   0,    // literal operand
2460   1,    // RAM access bit
2461   0,    // fast call/return mode select bit
2462   0,    // second memory operand
2463   0,    // second literal operand
2464   POC_NOP,
2465   (PCC_W | PCC_REGISTER | PCC_C),   // inCond
2466   (PCC_W | PCC_STATUS), // outCond
2467   PCI_MAGIC
2468 };
2469
2470 pCodeInstruction pic16_pciSWAPF = {
2471   {PC_OPCODE, NULL, NULL, 0, NULL, 
2472    //   genericAnalyze,
2473    genericDestruct,
2474    genericPrint},
2475   POC_SWAPF,
2476   "SWAPF",
2477   2,
2478   NULL, // from branch
2479   NULL, // to branch
2480   NULL, // label
2481   NULL, // operand
2482   NULL, // flow block
2483   NULL, // C source 
2484   3,    // num ops
2485   1,0,  // dest, bit instruction
2486   0,0,  // branch, skip
2487   0,    // literal operand
2488   1,    // RAM access bit
2489   0,    // fast call/return mode select bit
2490   0,    // second memory operand
2491   0,    // second literal operand
2492   POC_NOP,
2493   (PCC_REGISTER),   // inCond
2494   (PCC_REGISTER), // outCond
2495   PCI_MAGIC
2496 };
2497
2498 pCodeInstruction pic16_pciSWAPFW = {
2499   {PC_OPCODE, NULL, NULL, 0, NULL, 
2500    //   genericAnalyze,
2501    genericDestruct,
2502    genericPrint},
2503   POC_SWAPFW,
2504   "SWAPF",
2505   2,
2506   NULL, // from branch
2507   NULL, // to branch
2508   NULL, // label
2509   NULL, // operand
2510   NULL, // flow block
2511   NULL, // C source 
2512   3,    // num ops
2513   0,0,  // dest, bit instruction
2514   0,0,  // branch, skip
2515   0,    // literal operand
2516   1,    // RAM access bit
2517   0,    // fast call/return mode select bit
2518   0,    // second memory operand
2519   0,    // second literal operand
2520   POC_NOP,
2521   (PCC_REGISTER),   // inCond
2522   (PCC_W), // outCond
2523   PCI_MAGIC
2524 };
2525
2526 pCodeInstruction pic16_pciTBLRD = {     // patch 15
2527   {PC_OPCODE, NULL, NULL, 0, NULL, 
2528    genericDestruct,
2529    genericPrint},
2530   POC_TBLRD,
2531   "TBLRD*",
2532   2,
2533   NULL, // from branch
2534   NULL, // to branch
2535   NULL, // label
2536   NULL, // operand
2537   NULL, // flow block
2538   NULL, // C source 
2539   0,    // num ops
2540   0,0,  // dest, bit instruction
2541   0,0,  // branch, skip
2542   0,    // literal operand
2543   0,    // RAM access bit
2544   0,    // fast call/return mode select bit
2545   0,    // second memory operand
2546   0,    // second literal operand
2547   POC_NOP,
2548   PCC_NONE,  // inCond
2549   PCC_NONE  , // outCond
2550   PCI_MAGIC
2551 };
2552
2553 pCodeInstruction pic16_pciTBLRD_POSTINC = {     // patch 15
2554   {PC_OPCODE, NULL, NULL, 0, NULL, 
2555    genericDestruct,
2556    genericPrint},
2557   POC_TBLRD_POSTINC,
2558   "TBLRD*+",
2559   2,
2560   NULL, // from branch
2561   NULL, // to branch
2562   NULL, // label
2563   NULL, // operand
2564   NULL, // flow block
2565   NULL, // C source 
2566   0,    // num ops
2567   0,0,  // dest, bit instruction
2568   0,0,  // branch, skip
2569   0,    // literal operand
2570   0,    // RAM access bit
2571   0,    // fast call/return mode select bit
2572   0,    // second memory operand
2573   0,    // second literal operand
2574   POC_NOP,
2575   PCC_NONE,  // inCond
2576   PCC_NONE  , // outCond
2577   PCI_MAGIC
2578 };
2579
2580 pCodeInstruction pic16_pciTBLRD_POSTDEC = {     // patch 15
2581   {PC_OPCODE, NULL, NULL, 0, NULL, 
2582    genericDestruct,
2583    genericPrint},
2584   POC_TBLRD_POSTDEC,
2585   "TBLRD*-",
2586   2,
2587   NULL, // from branch
2588   NULL, // to branch
2589   NULL, // label
2590   NULL, // operand
2591   NULL, // flow block
2592   NULL, // C source 
2593   0,    // num ops
2594   0,0,  // dest, bit instruction
2595   0,0,  // branch, skip
2596   0,    // literal operand
2597   0,    // RAM access bit
2598   0,    // fast call/return mode select bit
2599   0,    // second memory operand
2600   0,    // second literal operand
2601   POC_NOP,
2602   PCC_NONE,  // inCond
2603   PCC_NONE  , // outCond
2604   PCI_MAGIC
2605 };
2606
2607 pCodeInstruction pic16_pciTBLRD_PREINC = {      // patch 15
2608   {PC_OPCODE, NULL, NULL, 0, NULL, 
2609    genericDestruct,
2610    genericPrint},
2611   POC_TBLRD_PREINC,
2612   "TBLRD+*",
2613   2,
2614   NULL, // from branch
2615   NULL, // to branch
2616   NULL, // label
2617   NULL, // operand
2618   NULL, // flow block
2619   NULL, // C source 
2620   0,    // num ops
2621   0,0,  // dest, bit instruction
2622   0,0,  // branch, skip
2623   0,    // literal operand
2624   0,    // RAM access bit
2625   0,    // fast call/return mode select bit
2626   0,    // second memory operand
2627   0,    // second literal operand
2628   POC_NOP,
2629   PCC_NONE,  // inCond
2630   PCC_NONE  , // outCond
2631   PCI_MAGIC
2632 };
2633
2634 pCodeInstruction pic16_pciTBLWT = {     // patch 15
2635   {PC_OPCODE, NULL, NULL, 0, NULL, 
2636    genericDestruct,
2637    genericPrint},
2638   POC_TBLWT,
2639   "TBLWT*",
2640   2,
2641   NULL, // from branch
2642   NULL, // to branch
2643   NULL, // label
2644   NULL, // operand
2645   NULL, // flow block
2646   NULL, // C source 
2647   0,    // num ops
2648   0,0,  // dest, bit instruction
2649   0,0,  // branch, skip
2650   0,    // literal operand
2651   0,    // RAM access bit
2652   0,    // fast call/return mode select bit
2653   0,    // second memory operand
2654   0,    // second literal operand
2655   POC_NOP,
2656   PCC_NONE,  // inCond
2657   PCC_NONE  , // outCond
2658   PCI_MAGIC
2659 };
2660
2661 pCodeInstruction pic16_pciTBLWT_POSTINC = {     // patch 15
2662   {PC_OPCODE, NULL, NULL, 0, NULL, 
2663    genericDestruct,
2664    genericPrint},
2665   POC_TBLWT_POSTINC,
2666   "TBLWT*+",
2667   2,
2668   NULL, // from branch
2669   NULL, // to branch
2670   NULL, // label
2671   NULL, // operand
2672   NULL, // flow block
2673   NULL, // C source 
2674   0,    // num ops
2675   0,0,  // dest, bit instruction
2676   0,0,  // branch, skip
2677   0,    // literal operand
2678   0,    // RAM access bit
2679   0,    // fast call/return mode select bit
2680   0,    // second memory operand
2681   0,    // second literal operand
2682   POC_NOP,
2683   PCC_NONE,  // inCond
2684   PCC_NONE  , // outCond
2685   PCI_MAGIC
2686 };
2687
2688 pCodeInstruction pic16_pciTBLWT_POSTDEC = {     // patch 15
2689   {PC_OPCODE, NULL, NULL, 0, NULL, 
2690    genericDestruct,
2691    genericPrint},
2692   POC_TBLWT_POSTDEC,
2693   "TBLWT*-",
2694   2,
2695   NULL, // from branch
2696   NULL, // to branch
2697   NULL, // label
2698   NULL, // operand
2699   NULL, // flow block
2700   NULL, // C source 
2701   0,    // num ops
2702   0,0,  // dest, bit instruction
2703   0,0,  // branch, skip
2704   0,    // literal operand
2705   0,    // RAM access bit
2706   0,    // fast call/return mode select bit
2707   0,    // second memory operand
2708   0,    // second literal operand
2709   POC_NOP,
2710   PCC_NONE,  // inCond
2711   PCC_NONE  , // outCond
2712   PCI_MAGIC
2713 };
2714
2715 pCodeInstruction pic16_pciTBLWT_PREINC = {      // patch 15
2716   {PC_OPCODE, NULL, NULL, 0, NULL, 
2717    genericDestruct,
2718    genericPrint},
2719   POC_TBLWT_PREINC,
2720   "TBLWT+*",
2721   2,
2722   NULL, // from branch
2723   NULL, // to branch
2724   NULL, // label
2725   NULL, // operand
2726   NULL, // flow block
2727   NULL, // C source 
2728   0,    // num ops
2729   0,0,  // dest, bit instruction
2730   0,0,  // branch, skip
2731   0,    // literal operand
2732   0,    // RAM access bit
2733   0,    // fast call/return mode select bit
2734   0,    // second memory operand
2735   0,    // second literal operand
2736   POC_NOP,
2737   PCC_NONE,  // inCond
2738   PCC_NONE  , // outCond
2739   PCI_MAGIC
2740 };
2741
2742 pCodeInstruction pic16_pciTSTFSZ = { // mdubuc - New
2743   {PC_OPCODE, NULL, NULL, 0, NULL, 
2744    //   genericAnalyze,
2745    genericDestruct,
2746    genericPrint},
2747   POC_TSTFSZ,
2748   "TSTFSZ",
2749   2,
2750   NULL, // from branch
2751   NULL, // to branch
2752   NULL, // label
2753   NULL, // operand
2754   NULL, // flow block
2755   NULL, // C source 
2756   2,    // num ops
2757   0,0,  // dest, bit instruction
2758   1,1,  // branch, skip
2759   0,    // literal operand
2760   1,    // RAM access bit
2761   0,    // fast call/return mode select bit
2762   0,    // second memory operand
2763   0,    // second literal operand
2764   POC_NOP,
2765   PCC_REGISTER,   // inCond
2766   PCC_NONE, // outCond
2767   PCI_MAGIC
2768 };
2769
2770 pCodeInstruction pic16_pciXORWF = {
2771   {PC_OPCODE, NULL, NULL, 0, NULL, 
2772    //   genericAnalyze,
2773    genericDestruct,
2774    genericPrint},
2775   POC_XORWF,
2776   "XORWF",
2777   2,
2778   NULL, // from branch
2779   NULL, // to branch
2780   NULL, // label
2781   NULL, // operand
2782   NULL, // flow block
2783   NULL, // C source 
2784   3,    // num ops
2785   1,0,  // dest, bit instruction
2786   0,0,  // branch, skip
2787   0,    // literal operand
2788   1,    // RAM access bit
2789   0,    // fast call/return mode select bit
2790   0,    // second memory operand
2791   0,    // second literal operand
2792   POC_NOP,
2793   (PCC_W | PCC_REGISTER),   // inCond
2794   (PCC_REGISTER | PCC_Z | PCC_N), // outCond
2795   PCI_MAGIC
2796 };
2797
2798 pCodeInstruction pic16_pciXORFW = {
2799   {PC_OPCODE, NULL, NULL, 0, NULL, 
2800    //   genericAnalyze,
2801    genericDestruct,
2802    genericPrint},
2803   POC_XORFW,
2804   "XORWF",
2805   2,
2806   NULL, // from branch
2807   NULL, // to branch
2808   NULL, // label
2809   NULL, // operand
2810   NULL, // flow block
2811   NULL, // C source 
2812   3,    // num ops
2813   0,0,  // dest, bit instruction
2814   0,0,  // branch, skip
2815   0,    // literal operand
2816   1,    // RAM access bit
2817   0,    // fast call/return mode select bit
2818   0,    // second memory operand
2819   0,    // second literal operand
2820   POC_NOP,
2821   (PCC_W | PCC_REGISTER),   // inCond
2822   (PCC_W | PCC_Z | PCC_N), // outCond
2823   PCI_MAGIC
2824 };
2825
2826 pCodeInstruction pic16_pciXORLW = {
2827   {PC_OPCODE, NULL, NULL, 0, NULL, 
2828    //   genericAnalyze,
2829    genericDestruct,
2830    genericPrint},
2831   POC_XORLW,
2832   "XORLW",
2833   2,
2834   NULL, // from branch
2835   NULL, // to branch
2836   NULL, // label
2837   NULL, // operand
2838   NULL, // flow block
2839   NULL, // C source 
2840   1,    // num ops
2841   0,0,  // dest, bit instruction
2842   0,0,  // branch, skip
2843   1,    // literal operand
2844   1,    // RAM access bit
2845   0,    // fast call/return mode select bit
2846   0,    // second memory operand
2847   0,    // second literal operand
2848   POC_NOP,
2849   (PCC_W | PCC_LITERAL),   // inCond
2850   (PCC_W | PCC_Z | PCC_N), // outCond
2851   PCI_MAGIC
2852 };
2853
2854
2855 pCodeInstruction pic16_pciBANKSEL = {
2856   {PC_OPCODE, NULL, NULL, 0, NULL, 
2857    genericDestruct,
2858    genericPrint},
2859   POC_BANKSEL,
2860   "BANKSEL",
2861   2,
2862   NULL, // from branch
2863   NULL, // to branch
2864   NULL, // label
2865   NULL, // operand
2866   NULL, // flow block
2867   NULL, // C source 
2868   0,    // num ops
2869   0,0,  // dest, bit instruction
2870   0,0,  // branch, skip
2871   0,    // literal operand
2872   0,    // RAM access bit
2873   0,    // fast call/return mode select bit
2874   0,    // second memory operand
2875   0,    // second literal operand
2876   POC_NOP,
2877   PCC_NONE,   // inCond
2878   PCC_NONE, // outCond
2879   PCI_MAGIC
2880 };
2881
2882
2883 #define MAX_PIC16MNEMONICS 100
2884 pCodeInstruction *pic16Mnemonics[MAX_PIC16MNEMONICS];
2885
2886 //#define USE_VSNPRINTF
2887 #if OPT_DISABLE_PIC
2888
2889 #ifdef USE_VSNPRINTF
2890   // Alas, vsnprintf is not ANSI standard, and does not exist
2891   // on Solaris (and probably other non-Gnu flavored Unixes).
2892
2893 /*-----------------------------------------------------------------*/
2894 /* SAFE_snprintf - like snprintf except the string pointer is      */
2895 /*                 after the string has been printed to. This is   */
2896 /*                 useful for printing to string as though if it   */
2897 /*                 were a stream.                                  */
2898 /*-----------------------------------------------------------------*/
2899 void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
2900 {
2901   va_list val;
2902   int len;
2903
2904   if(!str || !*str)
2905     return;
2906
2907   va_start(val, format);
2908
2909   vsnprintf(*str, *size, format, val);
2910
2911   va_end (val);
2912
2913   len = strlen(*str);
2914   if(len > *size) {
2915     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2916     fprintf(stderr,"len = %d is > str size %d\n",len,*size);
2917   }
2918
2919   *str += len;
2920   *size -= len;
2921
2922 }
2923
2924 #else
2925 // This version is *not* safe, despite the name.
2926
2927 void SAFE_snprintf(char **str, size_t *size, const  char  *format, ...)
2928 {
2929   va_list val;
2930   int len;
2931   static char buffer[1024]; /* grossly conservative, but still not inherently safe */
2932
2933   if(!str || !*str)
2934     return;
2935
2936   va_start(val, format);
2937
2938   vsprintf(buffer, format, val);
2939   va_end (val);
2940
2941   len = strlen(buffer);
2942   if(len > *size) {
2943     fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
2944     fprintf(stderr,"len = %d is > str size %d\n",len, (int) *size);
2945   }
2946
2947   strcpy(*str, buffer);
2948   *str += len;
2949   *size -= len;
2950
2951 }
2952
2953 #endif    //  USE_VSNPRINTF
2954 #endif
2955
2956 extern set *externs;
2957 extern  void pic16_initStack(int base_address, int size);
2958 extern regs *pic16_allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
2959 extern regs *pic16_allocInternalRegister(int rIdx, char * name, short po_type, int alias);
2960 extern void pic16_init_pic(char *);
2961
2962 void  pic16_pCodeInitRegisters(void)
2963 {
2964   static int initialized=0;
2965
2966         if(initialized)
2967                 return;
2968         
2969         initialized = 1;
2970
2971 //      pic16_initStack(0xfff, 8);
2972         pic16_init_pic(port->processor);
2973
2974         pic16_pc_status.r = pic16_allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x80);
2975         pic16_pc_pcl.r = pic16_allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
2976         pic16_pc_pclath.r = pic16_allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x80);
2977         pic16_pc_pclatu.r = pic16_allocProcessorRegister(IDX_PCLATU,"PCLATU", PO_PCLATU, 0x80);
2978         pic16_pc_intcon.r = pic16_allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x80);
2979         pic16_pc_wreg.r = pic16_allocProcessorRegister(IDX_WREG,"WREG", PO_WREG, 0x80);
2980         pic16_pc_bsr.r = pic16_allocProcessorRegister(IDX_BSR,"BSR", PO_BSR, 0x80);
2981
2982         pic16_pc_tosl.r = pic16_allocProcessorRegister(IDX_TOSL,"TOSL", PO_SFR_REGISTER, 0x80);
2983         pic16_pc_tosh.r = pic16_allocProcessorRegister(IDX_TOSH,"TOSH", PO_SFR_REGISTER, 0x80);
2984         pic16_pc_tosu.r = pic16_allocProcessorRegister(IDX_TOSU,"TOSU", PO_SFR_REGISTER, 0x80);
2985
2986         pic16_pc_tblptrl.r = pic16_allocProcessorRegister(IDX_TBLPTRL,"TBLPTRL", PO_SFR_REGISTER, 0x80);
2987         pic16_pc_tblptrh.r = pic16_allocProcessorRegister(IDX_TBLPTRH,"TBLPTRH", PO_SFR_REGISTER, 0x80);
2988         pic16_pc_tblptru.r = pic16_allocProcessorRegister(IDX_TBLPTRU,"TBLPTRU", PO_SFR_REGISTER, 0x80);
2989         pic16_pc_tablat.r = pic16_allocProcessorRegister(IDX_TABLAT,"TABLAT", PO_SFR_REGISTER, 0x80);
2990
2991         pic16_pc_fsr0l.r = pic16_allocProcessorRegister(IDX_FSR0L, "FSR0L", PO_FSR0, 0x80);
2992         pic16_pc_fsr0h.r = pic16_allocProcessorRegister(IDX_FSR0H, "FSR0H", PO_FSR0, 0x80);
2993         pic16_pc_fsr1l.r = pic16_allocProcessorRegister(IDX_FSR1L, "FSR1L", PO_FSR0, 0x80);
2994         pic16_pc_fsr1h.r = pic16_allocProcessorRegister(IDX_FSR1H, "FSR1H", PO_FSR0, 0x80);
2995         pic16_pc_fsr2l.r = pic16_allocProcessorRegister(IDX_FSR2L, "FSR2L", PO_FSR0, 0x80);
2996         pic16_pc_fsr2h.r = pic16_allocProcessorRegister(IDX_FSR2H, "FSR2H", PO_FSR0, 0x80);
2997
2998         pic16_stackpnt_lo = &pic16_pc_fsr1l;
2999         pic16_stackpnt_hi = &pic16_pc_fsr1h;
3000         pic16_stack_postdec = &pic16_pc_postdec1;
3001         pic16_stack_postinc = &pic16_pc_postinc1;
3002         pic16_stack_preinc = &pic16_pc_preinc1;
3003         pic16_stack_plusw = &pic16_pc_plusw1;
3004         
3005         pic16_framepnt_lo = &pic16_pc_fsr2l;
3006         pic16_framepnt_hi = &pic16_pc_fsr2h;
3007         pic16_frame_postdec = &pic16_pc_postdec2;
3008         pic16_frame_postinc = &pic16_pc_postinc2;
3009         pic16_frame_preinc = &pic16_pc_preinc2;
3010         pic16_frame_plusw = &pic16_pc_plusw2;
3011
3012         pic16_pc_indf0.r = pic16_allocProcessorRegister(IDX_INDF0,"INDF0", PO_INDF0, 0x80);
3013         pic16_pc_postinc0.r = pic16_allocProcessorRegister(IDX_POSTINC0, "POSTINC0", PO_INDF0, 0x80);
3014         pic16_pc_postdec0.r = pic16_allocProcessorRegister(IDX_POSTDEC0, "POSTDEC0", PO_INDF0, 0x80);
3015         pic16_pc_preinc0.r = pic16_allocProcessorRegister(IDX_PREINC0, "PREINC0", PO_INDF0, 0x80);
3016         pic16_pc_plusw0.r = pic16_allocProcessorRegister(IDX_PLUSW0, "PLUSW0", PO_INDF0, 0x80);
3017         
3018         pic16_pc_indf1.r = pic16_allocProcessorRegister(IDX_INDF1,"INDF1", PO_INDF0, 0x80);
3019         pic16_pc_postinc1.r = pic16_allocProcessorRegister(IDX_POSTINC1, "POSTINC1", PO_INDF0, 0x80);
3020         pic16_pc_postdec1.r = pic16_allocProcessorRegister(IDX_POSTDEC1, "POSTDEC1", PO_INDF0, 0x80);
3021         pic16_pc_preinc1.r = pic16_allocProcessorRegister(IDX_PREINC1, "PREINC1", PO_INDF0, 0x80);
3022         pic16_pc_plusw1.r = pic16_allocProcessorRegister(IDX_PLUSW1, "PLUSW1", PO_INDF0, 0x80);
3023
3024         pic16_pc_indf2.r = pic16_allocProcessorRegister(IDX_INDF2,"INDF2", PO_INDF0, 0x80);
3025         pic16_pc_postinc2.r = pic16_allocProcessorRegister(IDX_POSTINC2, "POSTINC2", PO_INDF0, 0x80);
3026         pic16_pc_postdec2.r = pic16_allocProcessorRegister(IDX_POSTDEC2, "POSTDEC2", PO_INDF0, 0x80);
3027         pic16_pc_preinc2.r = pic16_allocProcessorRegister(IDX_PREINC2, "PREINC2", PO_INDF0, 0x80);
3028         pic16_pc_plusw2.r = pic16_allocProcessorRegister(IDX_PLUSW2, "PLUSW2", PO_INDF0, 0x80);
3029         
3030         pic16_pc_prodl.r = pic16_allocProcessorRegister(IDX_PRODL, "PRODL", PO_PRODL, 0x80);
3031         pic16_pc_prodh.r = pic16_allocProcessorRegister(IDX_PRODH, "PRODH", PO_PRODH, 0x80);
3032
3033
3034         pic16_pc_eecon1.r = pic16_allocProcessorRegister(IDX_EECON1, "EECON1", PO_SFR_REGISTER, 0x80);
3035         pic16_pc_eecon2.r = pic16_allocProcessorRegister(IDX_EECON2, "EECON2", PO_SFR_REGISTER, 0x80);
3036         pic16_pc_eedata.r = pic16_allocProcessorRegister(IDX_EEDATA, "EEDATA", PO_SFR_REGISTER, 0x80);
3037         pic16_pc_eeadr.r = pic16_allocProcessorRegister(IDX_EEADR, "EEADR", PO_SFR_REGISTER, 0x80);
3038
3039         
3040         pic16_pc_status.rIdx = IDX_STATUS;
3041         pic16_pc_intcon.rIdx = IDX_INTCON;
3042         pic16_pc_pcl.rIdx = IDX_PCL;
3043         pic16_pc_pclath.rIdx = IDX_PCLATH;
3044         pic16_pc_pclatu.rIdx = IDX_PCLATU;
3045         pic16_pc_wreg.rIdx = IDX_WREG;
3046         pic16_pc_bsr.rIdx = IDX_BSR;
3047
3048         pic16_pc_tosl.rIdx = IDX_TOSL;
3049         pic16_pc_tosh.rIdx = IDX_TOSH;
3050         pic16_pc_tosu.rIdx = IDX_TOSU;
3051
3052         pic16_pc_tblptrl.rIdx = IDX_TBLPTRL;
3053         pic16_pc_tblptrh.rIdx = IDX_TBLPTRH;
3054         pic16_pc_tblptru.rIdx = IDX_TBLPTRU;
3055         pic16_pc_tablat.rIdx = IDX_TABLAT;
3056
3057         pic16_pc_fsr0l.rIdx = IDX_FSR0L;
3058         pic16_pc_fsr0h.rIdx = IDX_FSR0H;
3059         pic16_pc_fsr1l.rIdx = IDX_FSR1L;
3060         pic16_pc_fsr1h.rIdx = IDX_FSR1H;
3061         pic16_pc_fsr2l.rIdx = IDX_FSR2L;
3062         pic16_pc_fsr2h.rIdx = IDX_FSR2H;
3063         pic16_pc_indf0.rIdx = IDX_INDF0;
3064         pic16_pc_postinc0.rIdx = IDX_POSTINC0;
3065         pic16_pc_postdec0.rIdx = IDX_POSTDEC0;
3066         pic16_pc_preinc0.rIdx = IDX_PREINC0;
3067         pic16_pc_plusw0.rIdx = IDX_PLUSW0;
3068         pic16_pc_indf1.rIdx = IDX_INDF1;
3069         pic16_pc_postinc1.rIdx = IDX_POSTINC1;
3070         pic16_pc_postdec1.rIdx = IDX_POSTDEC1;
3071         pic16_pc_preinc1.rIdx = IDX_PREINC1;
3072         pic16_pc_plusw1.rIdx = IDX_PLUSW1;
3073         pic16_pc_indf2.rIdx = IDX_INDF2;
3074         pic16_pc_postinc2.rIdx = IDX_POSTINC2;
3075         pic16_pc_postdec2.rIdx = IDX_POSTDEC2;
3076         pic16_pc_preinc2.rIdx = IDX_PREINC2;
3077         pic16_pc_plusw2.rIdx = IDX_PLUSW2;
3078         pic16_pc_prodl.rIdx = IDX_PRODL;
3079         pic16_pc_prodh.rIdx = IDX_PRODH;
3080         
3081         pic16_pc_kzero.r = pic16_allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0);
3082         pic16_pc_ssave.r = pic16_allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0);
3083         pic16_pc_wsave.r = pic16_allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0);
3084         
3085         pic16_pc_kzero.rIdx = IDX_KZ;
3086         pic16_pc_wsave.rIdx = IDX_WSAVE;
3087         pic16_pc_ssave.rIdx = IDX_SSAVE;
3088
3089         pic16_pc_eecon1.rIdx = IDX_EECON1;
3090         pic16_pc_eecon2.rIdx = IDX_EECON2;
3091         pic16_pc_eedata.rIdx = IDX_EEDATA;
3092         pic16_pc_eeadr.rIdx = IDX_EEADR;
3093         
3094         
3095         pic16_pc_gpsimio.r = pic16_allocProcessorRegister(IDX_GPSIMIO, "GPSIMIO", PO_GPR_REGISTER, 0x80);
3096         pic16_pc_gpsimio2.r = pic16_allocProcessorRegister(IDX_GPSIMIO2, "GPSIMIO2", PO_GPR_REGISTER, 0x80);
3097
3098         pic16_pc_gpsimio.rIdx = IDX_GPSIMIO;
3099         pic16_pc_gpsimio2.rIdx = IDX_GPSIMIO2;
3100
3101         /* probably should put this in a separate initialization routine */
3102         pb_dead_pcodes = newpBlock();
3103
3104 }
3105
3106 #if OPT_DISABLE_PIC
3107 /*-----------------------------------------------------------------*/
3108 /*  mnem2key - convert a pic mnemonic into a hash key              */
3109 /*   (BTW - this spreads the mnemonics quite well)                 */
3110 /*                                                                 */
3111 /*-----------------------------------------------------------------*/
3112
3113 int mnem2key(unsigned char const *mnem)
3114 {
3115   int key = 0;
3116
3117   if(!mnem)
3118     return 0;
3119
3120   while(*mnem) {
3121
3122     key += toupper(*mnem++) +1;
3123
3124   }
3125
3126   return (key & 0x1f);
3127
3128 }
3129 #endif
3130
3131 void pic16initMnemonics(void)
3132 {
3133   int i = 0;
3134   int key;
3135   //  char *str;
3136   pCodeInstruction *pci;
3137
3138   if(mnemonics_initialized)
3139     return;
3140
3141   // NULL out the array before making the assignments
3142   // since we check the array contents below this initialization.
3143
3144   for (i = 0; i < MAX_PIC16MNEMONICS; i++) {
3145     pic16Mnemonics[i] = NULL;
3146   }
3147
3148   pic16Mnemonics[POC_ADDLW] = &pic16_pciADDLW;
3149   pic16Mnemonics[POC_ADDWF] = &pic16_pciADDWF;
3150   pic16Mnemonics[POC_ADDFW] = &pic16_pciADDFW;
3151   pic16Mnemonics[POC_ADDWFC] = &pic16_pciADDWFC;
3152   pic16Mnemonics[POC_ADDFWC] = &pic16_pciADDFWC;
3153   pic16Mnemonics[POC_ANDLW] = &pic16_pciANDLW;
3154   pic16Mnemonics[POC_ANDWF] = &pic16_pciANDWF;
3155   pic16Mnemonics[POC_ANDFW] = &pic16_pciANDFW;
3156   pic16Mnemonics[POC_BC] = &pic16_pciBC;
3157   pic16Mnemonics[POC_BCF] = &pic16_pciBCF;
3158   pic16Mnemonics[POC_BN] = &pic16_pciBN;
3159   pic16Mnemonics[POC_BNC] = &pic16_pciBNC;
3160   pic16Mnemonics[POC_BNN] = &pic16_pciBNN;
3161   pic16Mnemonics[POC_BNOV] = &pic16_pciBNOV;
3162   pic16Mnemonics[POC_BNZ] = &pic16_pciBNZ;
3163   pic16Mnemonics[POC_BOV] = &pic16_pciBOV;
3164   pic16Mnemonics[POC_BRA] = &pic16_pciBRA;
3165   pic16Mnemonics[POC_BSF] = &pic16_pciBSF;
3166   pic16Mnemonics[POC_BTFSC] = &pic16_pciBTFSC;
3167   pic16Mnemonics[POC_BTFSS] = &pic16_pciBTFSS;
3168   pic16Mnemonics[POC_BTG] = &pic16_pciBTG;
3169   pic16Mnemonics[POC_BZ] = &pic16_pciBZ;
3170   pic16Mnemonics[POC_CALL] = &pic16_pciCALL;
3171   pic16Mnemonics[POC_CLRF] = &pic16_pciCLRF;
3172   pic16Mnemonics[POC_CLRWDT] = &pic16_pciCLRWDT;
3173   pic16Mnemonics[POC_COMF] = &pic16_pciCOMF;
3174   pic16Mnemonics[POC_COMFW] = &pic16_pciCOMFW;
3175   pic16Mnemonics[POC_CPFSEQ] = &pic16_pciCPFSEQ;
3176   pic16Mnemonics[POC_CPFSGT] = &pic16_pciCPFSGT;
3177   pic16Mnemonics[POC_CPFSLT] = &pic16_pciCPFSLT;
3178   pic16Mnemonics[POC_DAW] = &pic16_pciDAW;
3179   pic16Mnemonics[POC_DCFSNZ] = &pic16_pciDCFSNZ;
3180   pic16Mnemonics[POC_DECF] = &pic16_pciDECF;
3181   pic16Mnemonics[POC_DECFW] = &pic16_pciDECFW;
3182   pic16Mnemonics[POC_DECFSZ] = &pic16_pciDECFSZ;
3183   pic16Mnemonics[POC_DECFSZW] = &pic16_pciDECFSZW;
3184   pic16Mnemonics[POC_GOTO] = &pic16_pciGOTO;
3185   pic16Mnemonics[POC_INCF] = &pic16_pciINCF;
3186   pic16Mnemonics[POC_INCFW] = &pic16_pciINCFW;
3187   pic16Mnemonics[POC_INCFSZ] = &pic16_pciINCFSZ;
3188   pic16Mnemonics[POC_INCFSZW] = &pic16_pciINCFSZW;
3189   pic16Mnemonics[POC_INFSNZ] = &pic16_pciINFSNZ;
3190   pic16Mnemonics[POC_INFSNZW] = &pic16_pciINFSNZW;
3191   pic16Mnemonics[POC_IORWF] = &pic16_pciIORWF;
3192   pic16Mnemonics[POC_IORFW] = &pic16_pciIORFW;
3193   pic16Mnemonics[POC_IORLW] = &pic16_pciIORLW;
3194   pic16Mnemonics[POC_LFSR] = &pic16_pciLFSR;
3195   pic16Mnemonics[POC_MOVF] = &pic16_pciMOVF;
3196   pic16Mnemonics[POC_MOVFW] = &pic16_pciMOVFW;
3197   pic16Mnemonics[POC_MOVFF] = &pic16_pciMOVFF;
3198   pic16Mnemonics[POC_MOVLB] = &pic16_pciMOVLB;
3199   pic16Mnemonics[POC_MOVLW] = &pic16_pciMOVLW;
3200   pic16Mnemonics[POC_MOVWF] = &pic16_pciMOVWF;
3201   pic16Mnemonics[POC_MULLW] = &pic16_pciMULLW;
3202   pic16Mnemonics[POC_MULWF] = &pic16_pciMULWF;
3203   pic16Mnemonics[POC_NEGF] = &pic16_pciNEGF;
3204   pic16Mnemonics[POC_NOP] = &pic16_pciNOP;
3205   pic16Mnemonics[POC_POP] = &pic16_pciPOP;
3206   pic16Mnemonics[POC_PUSH] = &pic16_pciPUSH;
3207   pic16Mnemonics[POC_RCALL] = &pic16_pciRCALL;
3208   pic16Mnemonics[POC_RETFIE] = &pic16_pciRETFIE;
3209   pic16Mnemonics[POC_RETLW] = &pic16_pciRETLW;
3210   pic16Mnemonics[POC_RETURN] = &pic16_pciRETURN;
3211   pic16Mnemonics[POC_RLCF] = &pic16_pciRLCF;
3212   pic16Mnemonics[POC_RLCFW] = &pic16_pciRLCFW;
3213   pic16Mnemonics[POC_RLNCF] = &pic16_pciRLNCF;
3214   pic16Mnemonics[POC_RLNCFW] = &pic16_pciRLNCFW;
3215   pic16Mnemonics[POC_RRCF] = &pic16_pciRRCF;
3216   pic16Mnemonics[POC_RRCFW] = &pic16_pciRRCFW;
3217   pic16Mnemonics[POC_RRNCF] = &pic16_pciRRNCF;
3218   pic16Mnemonics[POC_RRNCFW] = &pic16_pciRRNCFW;
3219   pic16Mnemonics[POC_SETF] = &pic16_pciSETF;
3220   pic16Mnemonics[POC_SUBLW] = &pic16_pciSUBLW;
3221   pic16Mnemonics[POC_SUBWF] = &pic16_pciSUBWF;
3222   pic16Mnemonics[POC_SUBFW] = &pic16_pciSUBFW;
3223   pic16Mnemonics[POC_SUBWFB_D0] = &pic16_pciSUBWFB_D0;
3224   pic16Mnemonics[POC_SUBWFB_D1] = &pic16_pciSUBWFB_D1;
3225   pic16Mnemonics[POC_SUBFWB_D0] = &pic16_pciSUBFWB_D0;
3226   pic16Mnemonics[POC_SUBFWB_D1] = &pic16_pciSUBFWB_D1;
3227   pic16Mnemonics[POC_SWAPF] = &pic16_pciSWAPF;
3228   pic16Mnemonics[POC_SWAPFW] = &pic16_pciSWAPFW;
3229   pic16Mnemonics[POC_TBLRD] = &pic16_pciTBLRD;
3230   pic16Mnemonics[POC_TBLRD_POSTINC] = &pic16_pciTBLRD_POSTINC;
3231   pic16Mnemonics[POC_TBLRD_POSTDEC] = &pic16_pciTBLRD_POSTDEC;
3232   pic16Mnemonics[POC_TBLRD_PREINC] = &pic16_pciTBLRD_PREINC;
3233   pic16Mnemonics[POC_TBLWT] = &pic16_pciTBLWT;
3234   pic16Mnemonics[POC_TBLWT_POSTINC] = &pic16_pciTBLWT_POSTINC;
3235   pic16Mnemonics[POC_TBLWT_POSTDEC] = &pic16_pciTBLWT_POSTDEC;
3236   pic16Mnemonics[POC_TBLWT_PREINC] = &pic16_pciTBLWT_PREINC;
3237   pic16Mnemonics[POC_TSTFSZ] = &pic16_pciTSTFSZ;
3238   pic16Mnemonics[POC_XORLW] = &pic16_pciXORLW;
3239   pic16Mnemonics[POC_XORWF] = &pic16_pciXORWF;
3240   pic16Mnemonics[POC_XORFW] = &pic16_pciXORFW;
3241   pic16Mnemonics[POC_BANKSEL] = &pic16_pciBANKSEL;
3242
3243   for(i=0; i<MAX_PIC16MNEMONICS; i++)
3244     if(pic16Mnemonics[i])
3245       hTabAddItem(&pic16MnemonicsHash, mnem2key((const unsigned char *)pic16Mnemonics[i]->mnemonic), pic16Mnemonics[i]);
3246   pci = hTabFirstItem(pic16MnemonicsHash, &key);
3247
3248   while(pci) {
3249     DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
3250     pci = hTabNextItem(pic16MnemonicsHash, &key);
3251   }
3252
3253   mnemonics_initialized = 1;
3254 }
3255
3256 int pic16_getpCodePeepCommand(char *cmd);
3257
3258 int pic16_getpCode(char *mnem,unsigned dest)
3259 {
3260
3261   pCodeInstruction *pci;
3262   int key = mnem2key((unsigned char *)mnem);
3263
3264   if(!mnemonics_initialized)
3265     pic16initMnemonics();
3266
3267   pci = hTabFirstItemWK(pic16MnemonicsHash, key);
3268
3269   while(pci) {
3270
3271     if(STRCASECMP(pci->mnemonic, mnem) == 0) {
3272       if((pci->num_ops <= 1)
3273         || (pci->isModReg == dest)
3274         || (pci->isBitInst)
3275         || (pci->num_ops <= 2 && pci->isAccess)
3276         || (pci->num_ops <= 2 && pci->isFastCall)
3277         || (pci->num_ops <= 2 && pci->is2MemOp)
3278         || (pci->num_ops <= 2 && pci->is2LitOp) )
3279         return(pci->op);
3280     }
3281
3282     pci = hTabNextItemWK (pic16MnemonicsHash);
3283   
3284   }
3285
3286   return -1;
3287 }
3288
3289 /*-----------------------------------------------------------------*
3290  * pic16initpCodePeepCommands
3291  *
3292  *-----------------------------------------------------------------*/
3293 void pic16initpCodePeepCommands(void)
3294 {
3295
3296   int key, i;
3297   peepCommand *pcmd;
3298
3299   i = 0;
3300   do {
3301     hTabAddItem(&pic16pCodePeepCommandsHash, 
3302                 mnem2key((const unsigned char *)peepCommands[i].cmd), &peepCommands[i]);
3303     i++;
3304   } while (peepCommands[i].cmd);
3305
3306   pcmd = hTabFirstItem(pic16pCodePeepCommandsHash, &key);
3307
3308   while(pcmd) {
3309     //fprintf(stderr, "peep command %s  key %d\n",pcmd->cmd,pcmd->id);
3310     pcmd = hTabNextItem(pic16pCodePeepCommandsHash, &key);
3311   }
3312
3313 }
3314
3315 /*-----------------------------------------------------------------
3316  *
3317  *
3318  *-----------------------------------------------------------------*/
3319
3320 int pic16_getpCodePeepCommand(char *cmd)
3321 {
3322
3323   peepCommand *pcmd;
3324   int key = mnem2key((unsigned char *)cmd);
3325
3326
3327   pcmd = hTabFirstItemWK(pic16pCodePeepCommandsHash, key);
3328
3329   while(pcmd) {
3330     // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
3331     if(STRCASECMP(pcmd->cmd, cmd) == 0) {
3332       return pcmd->id;
3333     }
3334
3335     pcmd = hTabNextItemWK (pic16pCodePeepCommandsHash);
3336   
3337   }
3338
3339   return -1;
3340 }
3341
3342 static char getpBlock_dbName(pBlock *pb)
3343 {
3344   if(!pb)
3345     return 0;
3346
3347   if(pb->cmemmap)
3348     return pb->cmemmap->dbName;
3349
3350   return pb->dbName;
3351 }
3352 void pic16_pBlockConvert2ISR(pBlock *pb)
3353 {
3354         if(!pb)return;
3355
3356         if(pb->cmemmap)pb->cmemmap = NULL;
3357
3358         pb->dbName = 'I';
3359
3360         if(pic16_pcode_verbose)
3361                 fprintf(stderr, "%s:%d converting to 'I'interrupt pBlock\n", __FILE__, __LINE__);
3362 }
3363
3364 void pic16_pBlockConvert2Absolute(pBlock *pb)
3365 {
3366         if(!pb)return;
3367         if(pb->cmemmap)pb->cmemmap = NULL;
3368         
3369         pb->dbName = 'A';
3370         
3371         if(pic16_pcode_verbose)
3372                 fprintf(stderr, "%s:%d converting to 'A'bsolute pBlock\n", __FILE__, __LINE__);
3373 }
3374   
3375 /*-----------------------------------------------------------------*/
3376 /* pic16_movepBlock2Head - given the dbname of a pBlock, move all  */
3377 /*                   instances to the front of the doubly linked   */
3378 /*                   list of pBlocks                               */
3379 /*-----------------------------------------------------------------*/
3380
3381 void pic16_movepBlock2Head(char dbName)
3382 {
3383   pBlock *pb;
3384
3385
3386   /* this can happen in sources without code,
3387    * only variable definitions */
3388   if(!the_pFile)return;
3389
3390   pb = the_pFile->pbHead;
3391
3392   while(pb) {
3393
3394     if(getpBlock_dbName(pb) == dbName) {
3395       pBlock *pbn = pb->next;
3396       pb->next = the_pFile->pbHead;
3397       the_pFile->pbHead->prev = pb;
3398       the_pFile->pbHead = pb;
3399
3400       if(pb->prev)
3401         pb->prev->next = pbn;
3402
3403       // If the pBlock that we just moved was the last
3404       // one in the link of all of the pBlocks, then we
3405       // need to point the tail to the block just before
3406       // the one we moved.
3407       // Note: if pb->next is NULL, then pb must have 
3408       // been the last pBlock in the chain.
3409
3410       if(pbn)
3411         pbn->prev = pb->prev;
3412       else
3413         the_pFile->pbTail = pb->prev;
3414
3415       pb = pbn;
3416
3417     } else
3418       pb = pb->next;
3419
3420   }
3421
3422 }
3423
3424 void pic16_copypCode(FILE *of, char dbName)
3425 {
3426   pBlock *pb;
3427
3428         if(!of || !the_pFile)
3429                 return;
3430
3431         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3432                 if(getpBlock_dbName(pb) == dbName) {
3433 //                      fprintf(stderr, "%s:%d: output of pb= 0x%p\n", __FILE__, __LINE__, pb);
3434                         pBlockStats(of,pb);
3435                         pic16_printpBlock(of,pb);
3436                 }
3437         }
3438
3439 }
3440 void pic16_pcode_test(void)
3441 {
3442
3443   DFPRINTF((stderr,"pcode is alive!\n"));
3444
3445   //initMnemonics();
3446
3447   if(the_pFile) {
3448
3449     pBlock *pb;
3450     FILE *pFile;
3451     char buffer[100];
3452
3453     /* create the file name */
3454     strcpy(buffer,dstFileName);
3455     strcat(buffer,".p");
3456
3457     if( !(pFile = fopen(buffer, "w" ))) {
3458       werror(E_FILE_OPEN_ERR,buffer);
3459       exit(1);
3460     }
3461
3462     fprintf(pFile,"pcode dump\n\n");
3463
3464     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3465       fprintf(pFile,"\n\tNew pBlock\n\n");
3466       if(pb->cmemmap)
3467         fprintf(pFile,"%s",pb->cmemmap->sname);
3468       else
3469         fprintf(pFile,"internal pblock");
3470
3471       fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
3472       pic16_printpBlock(pFile,pb);
3473     }
3474   }
3475 }
3476
3477
3478 unsigned long pic16_countInstructions(void)
3479 {
3480   pBlock *pb;
3481   pCode *pc;
3482   unsigned long isize=0;
3483
3484     if(!the_pFile)return -1;
3485     
3486     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3487       for(pc = pb->pcHead; pc; pc = pc->next) {
3488         if(isPCI(pc) || isPCAD(pc))isize += PCI(pc)->isize;
3489       }
3490     }
3491   return (isize);
3492 }
3493
3494
3495 /*-----------------------------------------------------------------*/
3496 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg-  */
3497 /*      ister, RegCond will return the bit being referenced.       */
3498 /*                                                                 */
3499 /* fixme - why not just OR in the pcop bit field                   */
3500 /*-----------------------------------------------------------------*/
3501
3502 static int RegCond(pCodeOp *pcop)
3503 {
3504
3505   if(!pcop)
3506     return 0;
3507
3508   if(!pcop->name)return 0;
3509
3510   if(pcop->type == PO_GPR_BIT  && !strcmp(pcop->name, pic16_pc_status.pcop.name)) {
3511     switch(PCORB(pcop)->bit) {
3512     case PIC_C_BIT:
3513       return PCC_C;
3514     case PIC_DC_BIT:
3515         return PCC_DC;
3516     case PIC_Z_BIT:
3517       return PCC_Z;
3518     }
3519
3520   }
3521
3522   return 0;
3523 }
3524
3525
3526 /*-----------------------------------------------------------------*/
3527 /* pic16_newpCode - create and return a newly initialized pCode          */
3528 /*                                                                 */
3529 /*  fixme - rename this                                            */
3530 /*                                                                 */
3531 /* The purpose of this routine is to create a new Instruction      */
3532 /* pCode. This is called by gen.c while the assembly code is being */
3533 /* generated.                                                      */
3534 /*                                                                 */
3535 /* Inouts:                                                         */
3536 /*  PIC_OPCODE op - the assembly instruction we wish to create.    */
3537 /*                  (note that the op is analogous to but not the  */
3538 /*                  same thing as the opcode of the instruction.)  */
3539 /*  pCdoeOp *pcop - pointer to the operand of the instruction.     */
3540 /*                                                                 */
3541 /* Outputs:                                                        */
3542 /*  a pointer to the new malloc'd pCode is returned.               */
3543 /*                                                                 */
3544 /*                                                                 */
3545 /*                                                                 */
3546 /*-----------------------------------------------------------------*/
3547 pCode *pic16_newpCode (PIC_OPCODE op, pCodeOp *pcop)
3548 {
3549   pCodeInstruction *pci ;
3550
3551   if(!mnemonics_initialized)
3552     pic16initMnemonics();
3553     
3554   pci = Safe_calloc(1, sizeof(pCodeInstruction));
3555
3556   if((op>=0) && (op < MAX_PIC16MNEMONICS) && pic16Mnemonics[op]) {
3557     memcpy(pci, pic16Mnemonics[op], sizeof(pCodeInstruction));
3558     pci->pcop = pcop;
3559
3560     if(pci->inCond & PCC_EXAMINE_PCOP)
3561       pci->inCond  |= RegCond(pcop);
3562
3563     if(pci->outCond & PCC_EXAMINE_PCOP)
3564       pci->outCond  |= RegCond(pcop);
3565
3566     pci->pc.prev = pci->pc.next = NULL;
3567     return (pCode *)pci;
3568   }
3569
3570   fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
3571   exit(1);
3572
3573   return NULL;
3574 }       
3575
3576 /*-----------------------------------------------------------------*/
3577 /* pic16_newpCodeWild - create a "wild" as in wild card pCode            */
3578 /*                                                                 */
3579 /* Wild pcodes are used during the peep hole optimizer to serve    */
3580 /* as place holders for any instruction. When a snippet of code is */
3581 /* compared to a peep hole rule, the wild card opcode will match   */
3582 /* any instruction. However, the optional operand and label are    */
3583 /* additional qualifiers that must also be matched before the      */
3584 /* line (of assembly code) is declared matched. Note that the      */
3585 /* operand may be wild too.                                        */
3586 /*                                                                 */
3587 /*   Note, a wild instruction is specified just like a wild var:   */
3588 /*      %4     ; A wild instruction,                               */
3589 /*  See the peeph.def file for additional examples                 */
3590 /*                                                                 */
3591 /*-----------------------------------------------------------------*/
3592
3593 pCode *pic16_newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
3594 {
3595
3596   pCodeWild *pcw;
3597     
3598   pcw = Safe_calloc(1,sizeof(pCodeWild));
3599
3600   pcw->pci.pc.type = PC_WILD;
3601   pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
3602   pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
3603   pcw->pci.pc.pb = NULL;
3604
3605   //  pcw->pci.pc.analyze = genericAnalyze;
3606   pcw->pci.pc.destruct = genericDestruct;
3607   pcw->pci.pc.print = genericPrint;
3608
3609   pcw->id = pCodeID;              // this is the 'n' in %n
3610   pcw->operand = optional_operand;
3611   pcw->label   = optional_label;
3612
3613   pcw->mustBeBitSkipInst = 0;
3614   pcw->mustNotBeBitSkipInst = 0;
3615   pcw->invertBitSkipInst = 0;
3616
3617   return ( (pCode *)pcw);
3618   
3619 }
3620
3621  /*-----------------------------------------------------------------*/
3622 /* newPcodeInlineP - create a new pCode from a char string           */
3623 /*-----------------------------------------------------------------*/
3624
3625
3626 pCode *pic16_newpCodeInlineP(char *cP)
3627 {
3628
3629   pCodeComment *pcc ;
3630     
3631   pcc = Safe_calloc(1,sizeof(pCodeComment));
3632
3633   pcc->pc.type = PC_INLINE;
3634   pcc->pc.prev = pcc->pc.next = NULL;
3635   //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3636   pcc->pc.pb = NULL;
3637
3638   //  pcc->pc.analyze = genericAnalyze;
3639   pcc->pc.destruct = genericDestruct;
3640   pcc->pc.print = genericPrint;
3641
3642   if(cP)
3643     pcc->comment = Safe_strdup(cP);
3644   else
3645     pcc->comment = NULL;
3646
3647   return ( (pCode *)pcc);
3648
3649 }
3650
3651 /*-----------------------------------------------------------------*/
3652 /* newPcodeCharP - create a new pCode from a char string           */
3653 /*-----------------------------------------------------------------*/
3654
3655 pCode *pic16_newpCodeCharP(char *cP)
3656 {
3657
3658   pCodeComment *pcc ;
3659     
3660   pcc = Safe_calloc(1,sizeof(pCodeComment));
3661
3662   pcc->pc.type = PC_COMMENT;
3663   pcc->pc.prev = pcc->pc.next = NULL;
3664   //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
3665   pcc->pc.pb = NULL;
3666
3667   //  pcc->pc.analyze = genericAnalyze;
3668   pcc->pc.destruct = genericDestruct;
3669   pcc->pc.print = genericPrint;
3670
3671   if(cP)
3672     pcc->comment = Safe_strdup(cP);
3673   else
3674     pcc->comment = NULL;
3675
3676   return ( (pCode *)pcc);
3677
3678 }
3679
3680 /*-----------------------------------------------------------------*/
3681 /* pic16_newpCodeFunction -                                              */
3682 /*-----------------------------------------------------------------*/
3683
3684
3685 pCode *pic16_newpCodeFunction(char *mod,char *f)
3686 {
3687   pCodeFunction *pcf;
3688
3689   pcf = Safe_calloc(1,sizeof(pCodeFunction));
3690
3691   pcf->pc.type = PC_FUNCTION;
3692   pcf->pc.prev = pcf->pc.next = NULL;
3693   //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
3694   pcf->pc.pb = NULL;
3695
3696   //  pcf->pc.analyze = genericAnalyze;
3697   pcf->pc.destruct = genericDestruct;
3698   pcf->pc.print = pCodePrintFunction;
3699
3700   pcf->ncalled = 0;
3701   pcf->absblock = 0;
3702   
3703   if(mod) {
3704     pcf->modname = Safe_calloc(1,strlen(mod)+1);
3705     strcpy(pcf->modname,mod);
3706   } else
3707     pcf->modname = NULL;
3708
3709   if(f) {
3710     pcf->fname = Safe_calloc(1,strlen(f)+1);
3711     strcpy(pcf->fname,f);
3712   } else
3713     pcf->fname = NULL;
3714
3715   pcf->stackusage = 0;
3716
3717   return ( (pCode *)pcf);
3718 }
3719
3720 /*-----------------------------------------------------------------*/
3721 /* pic16_newpCodeFlow                                                    */
3722 /*-----------------------------------------------------------------*/
3723 static void destructpCodeFlow(pCode *pc)
3724 {
3725   if(!pc || !isPCFL(pc))
3726     return;
3727
3728 /*
3729   if(PCFL(pc)->from)
3730   if(PCFL(pc)->to)
3731 */
3732   pic16_unlinkpCode(pc);
3733
3734   deleteSet(&PCFL(pc)->registers);
3735   deleteSet(&PCFL(pc)->from);
3736   deleteSet(&PCFL(pc)->to);
3737
3738   /* Instead of deleting the memory used by this pCode, mark
3739    * the object as bad so that if there's a pointer to this pCode
3740    * dangling around somewhere then (hopefully) when the type is
3741    * checked we'll catch it.
3742    */
3743
3744   pc->type = PC_BAD;
3745   pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3746
3747 //  Safe_free(pc);
3748
3749 }
3750
3751 pCode *pic16_newpCodeFlow(void )
3752 {
3753   pCodeFlow *pcflow;
3754
3755   //_ALLOC(pcflow,sizeof(pCodeFlow));
3756   pcflow = Safe_calloc(1,sizeof(pCodeFlow));
3757
3758   pcflow->pc.type = PC_FLOW;
3759   pcflow->pc.prev = pcflow->pc.next = NULL;
3760   pcflow->pc.pb = NULL;
3761
3762   //  pcflow->pc.analyze = genericAnalyze;
3763   pcflow->pc.destruct = destructpCodeFlow;
3764   pcflow->pc.print = genericPrint;
3765
3766   pcflow->pc.seq = GpcFlowSeq++;
3767
3768   pcflow->from = pcflow->to = NULL;
3769
3770   pcflow->inCond = PCC_NONE;
3771   pcflow->outCond = PCC_NONE;
3772
3773   pcflow->firstBank = -1;
3774   pcflow->lastBank = -1;
3775
3776   pcflow->FromConflicts = 0;
3777   pcflow->ToConflicts = 0;
3778
3779   pcflow->end = NULL;
3780
3781   pcflow->registers = newSet();
3782
3783   return ( (pCode *)pcflow);
3784
3785 }
3786
3787 /*-----------------------------------------------------------------*/
3788 /*-----------------------------------------------------------------*/
3789 pCodeFlowLink *pic16_newpCodeFlowLink(pCodeFlow *pcflow)
3790 {
3791   pCodeFlowLink *pcflowLink;
3792
3793   pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
3794
3795   pcflowLink->pcflow = pcflow;
3796   pcflowLink->bank_conflict = 0;
3797
3798   return pcflowLink;
3799 }
3800
3801 /*-----------------------------------------------------------------*/
3802 /* pic16_newpCodeCSource - create a new pCode Source Symbol        */
3803 /*-----------------------------------------------------------------*/
3804
3805 pCode *pic16_newpCodeCSource(int ln, char *f, char *l)
3806 {
3807
3808   pCodeCSource *pccs;
3809     
3810   pccs = Safe_calloc(1,sizeof(pCodeCSource));
3811
3812   pccs->pc.type = PC_CSOURCE;
3813   pccs->pc.prev = pccs->pc.next = NULL;
3814   pccs->pc.pb = NULL;
3815
3816   pccs->pc.destruct = genericDestruct;
3817   pccs->pc.print = genericPrint;
3818
3819   pccs->line_number = ln;
3820   if(l)
3821     pccs->line = Safe_strdup(l);
3822   else
3823     pccs->line = NULL;
3824
3825   if(f)
3826     pccs->file_name = Safe_strdup(f);
3827   else
3828     pccs->file_name = NULL;
3829
3830   return ( (pCode *)pccs);
3831
3832 }
3833
3834
3835 /*******************************************************************/
3836 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive   */
3837 /*                      added by VR 6-Jun-2003                     */
3838 /*******************************************************************/
3839
3840 pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...)
3841 {
3842   pCodeAsmDir *pcad;
3843   va_list ap;
3844   char buffer[512];
3845   char *lbp=buffer;
3846   
3847         pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
3848         pcad->pci.pc.type = PC_ASMDIR;
3849         pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
3850         pcad->pci.pc.pb = NULL;
3851         pcad->pci.isize = 2;
3852         pcad->pci.pc.destruct = genericDestruct;
3853         pcad->pci.pc.print = genericPrint;
3854
3855         if(asdir && *asdir) {
3856                 
3857                 while(isspace((unsigned char)*asdir))asdir++;   // strip any white space from the beginning
3858                 
3859                 pcad->directive = Safe_strdup( asdir );
3860         }
3861         
3862         va_start(ap, argfmt);
3863         
3864         memset(buffer, 0, sizeof(buffer));
3865         if(argfmt && *argfmt)
3866                 vsprintf(buffer, argfmt, ap);
3867         
3868         va_end(ap);
3869         
3870         while(isspace((unsigned char)*lbp))lbp++;
3871         
3872         if(lbp && *lbp)
3873                 pcad->arg = Safe_strdup( lbp );
3874
3875   return ((pCode *)pcad);
3876 }
3877
3878 /*-----------------------------------------------------------------*/
3879 /* pCodeLabelDestruct - free memory used by a label.               */
3880 /*-----------------------------------------------------------------*/
3881 static void pCodeLabelDestruct(pCode *pc)
3882 {
3883
3884   if(!pc)
3885     return;
3886
3887 //  if((pc->type == PC_LABEL) && PCL(pc)->label)
3888 //    Safe_free(PCL(pc)->label);
3889
3890   /* Instead of deleting the memory used by this pCode, mark
3891    * the object as bad so that if there's a pointer to this pCode
3892    * dangling around somewhere then (hopefully) when the type is
3893    * checked we'll catch it.
3894    */
3895
3896   pc->type = PC_BAD;
3897   pic16_addpCode2pBlock(pb_dead_pcodes, pc);
3898
3899 //  Safe_free(pc);
3900
3901 }
3902
3903 pCode *pic16_newpCodeLabel(char *name, int key)
3904 {
3905
3906   char *s = buffer;
3907   pCodeLabel *pcl;
3908     
3909   pcl = Safe_calloc(1,sizeof(pCodeLabel) );
3910
3911   pcl->pc.type = PC_LABEL;
3912   pcl->pc.prev = pcl->pc.next = NULL;
3913   //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
3914   pcl->pc.pb = NULL;
3915
3916   //  pcl->pc.analyze = genericAnalyze;
3917   pcl->pc.destruct = pCodeLabelDestruct;
3918   pcl->pc.print = pCodePrintLabel;
3919
3920   pcl->key = key;
3921   pcl->force = 0;
3922   
3923   pcl->label = NULL;
3924   if(key>0) {
3925     sprintf(s,"_%05d_DS_",key);
3926   } else
3927     s = name;
3928
3929   if(s)
3930     pcl->label = Safe_strdup(s);
3931
3932 //  if(pic16_pcode_verbose)
3933 //      fprintf(stderr, "%s:%d label name: %s\n", __FILE__, __LINE__, pcl->label);
3934
3935
3936   return ( (pCode *)pcl);
3937
3938 }
3939
3940 pCode *pic16_newpCodeLabelFORCE(char *name, int key)
3941 {
3942   pCodeLabel *pcl = (pCodeLabel *)pic16_newpCodeLabel(name, key);
3943   
3944         pcl->force = 1;
3945   
3946   return ( (pCode *)pcl );
3947 }
3948
3949 pCode *pic16_newpCodeInfo(INFO_TYPE type, pCodeOp *pcop)
3950 {
3951   pCodeInfo *pci;
3952
3953     pci = Safe_calloc(1, sizeof(pCodeInfo));
3954     pci->pci.pc.type = PC_INFO;
3955     pci->pci.pc.prev = pci->pci.pc.next = NULL;
3956     pci->pci.pc.pb = NULL;
3957     pci->pci.label = NULL;
3958         
3959     pci->pci.pc.destruct = genericDestruct;
3960     pci->pci.pc.print = genericPrint;
3961     
3962     pci->type = type;
3963     pci->oper1 = pcop;
3964   
3965   return ((pCode *)pci);
3966 }
3967
3968
3969 /*-----------------------------------------------------------------*/
3970 /* newpBlock - create and return a pointer to a new pBlock         */
3971 /*-----------------------------------------------------------------*/
3972 static pBlock *newpBlock(void)
3973 {
3974
3975   pBlock *PpB;
3976
3977   PpB = Safe_calloc(1,sizeof(pBlock) );
3978   PpB->next = PpB->prev = NULL;
3979
3980   PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
3981   PpB->tregisters = NULL;
3982   PpB->visited = 0;
3983   PpB->FlowTree = NULL;
3984
3985   return PpB;
3986
3987 }
3988
3989 /*-----------------------------------------------------------------*/
3990 /* pic16_newpCodeChain - create a new chain of pCodes                    */
3991 /*-----------------------------------------------------------------*
3992  *
3993  *  This function will create a new pBlock and the pointer to the
3994  *  pCode that is passed in will be the first pCode in the block.
3995  *-----------------------------------------------------------------*/
3996
3997
3998 pBlock *pic16_newpCodeChain(memmap *cm,char c, pCode *pc)
3999 {
4000
4001   pBlock *pB  = newpBlock();
4002
4003   pB->pcHead  = pB->pcTail = pc;
4004   pB->cmemmap = cm;
4005   pB->dbName  = c;
4006
4007   return pB;
4008 }
4009
4010
4011
4012 /*-----------------------------------------------------------------*/
4013 /* pic16_newpCodeOpLabel - Create a new label given the key              */
4014 /*  Note, a negative key means that the label is part of wild card */
4015 /*  (and hence a wild card label) used in the pCodePeep            */
4016 /*   optimizations).                                               */
4017 /*-----------------------------------------------------------------*/
4018
4019 pCodeOp *pic16_newpCodeOpLabel(char *name, int key)
4020 {
4021   char *s=NULL;
4022   static int label_key=-1;
4023
4024   pCodeOp *pcop;
4025
4026   pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
4027   pcop->type = PO_LABEL;
4028
4029   pcop->name = NULL;
4030
4031   if(key>0)
4032     sprintf(s=buffer,"_%05d_DS_",key);
4033   else 
4034     s = name, key = label_key--;
4035
4036   if(s)
4037     pcop->name = Safe_strdup(s);
4038
4039   ((pCodeOpLabel *)pcop)->key = key;
4040
4041   //fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4042   return pcop;
4043 }
4044
4045 /*-----------------------------------------------------------------*/
4046 /*-----------------------------------------------------------------*/
4047 pCodeOp *pic16_newpCodeOpLit(int lit)
4048 {
4049   char *s = buffer;
4050   pCodeOp *pcop;
4051
4052
4053   pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
4054   pcop->type = PO_LITERAL;
4055
4056   pcop->name = NULL;
4057   //if(lit>=0)
4058     sprintf(s,"0x%02hhx", (unsigned char)lit);
4059   //else
4060   //  sprintf(s, "%i", lit);
4061   
4062   if(s)
4063     pcop->name = Safe_strdup(s);
4064
4065   ((pCodeOpLit *)pcop)->lit = lit;
4066
4067   return pcop;
4068 }
4069
4070 /* Allow for 12 bit literals, required for LFSR */
4071 pCodeOp *pic16_newpCodeOpLit12(int lit)
4072 {
4073   char *s = buffer;
4074   pCodeOp *pcop;
4075
4076
4077   pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
4078   pcop->type = PO_LITERAL;
4079
4080   pcop->name = NULL;
4081   //if(lit>=0)
4082     sprintf(s,"0x%03x", ((unsigned int)lit) & 0x0fff);
4083   //else
4084   //  sprintf(s, "%i", lit);
4085   
4086   if(s)
4087     pcop->name = Safe_strdup(s);
4088
4089   ((pCodeOpLit *)pcop)->lit = lit;
4090
4091   return pcop;
4092 }
4093
4094 /*-----------------------------------------------------------------*/
4095 /*-----------------------------------------------------------------*/
4096 pCodeOp *pic16_newpCodeOpLit2(int lit, pCodeOp *arg2)
4097 {
4098   char *s = buffer, tbuf[256], *tb=tbuf;
4099   pCodeOp *pcop;
4100
4101
4102   tb = pic16_get_op(arg2, NULL, 0);
4103   pcop = Safe_calloc(1,sizeof(pCodeOpLit2) );
4104   pcop->type = PO_LITERAL;
4105
4106   pcop->name = NULL;
4107   //if(lit>=0) {
4108     sprintf(s,"0x%02x, %s", (unsigned char)lit, tb);
4109     if(s)
4110       pcop->name = Safe_strdup(s);
4111   //}
4112
4113   ((pCodeOpLit2 *)pcop)->lit = lit;
4114   ((pCodeOpLit2 *)pcop)->arg2 = arg2;
4115
4116   return pcop;
4117 }
4118
4119 /*-----------------------------------------------------------------*/
4120 /*-----------------------------------------------------------------*/
4121 pCodeOp *pic16_newpCodeOpImmd(char *name, int offset, int index, int code_space)
4122 {
4123   pCodeOp *pcop;
4124
4125         pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
4126         pcop->type = PO_IMMEDIATE;
4127         if(name) {
4128                 regs *r = pic16_dirregWithName(name);
4129                 pcop->name = Safe_strdup(name);
4130                 PCOI(pcop)->r = r;
4131                 
4132                 if(r) {
4133 //                      fprintf(stderr, "%s:%d %s reg %s exists (r: %p)\n",__FILE__, __LINE__, __FUNCTION__, name, r);
4134                         PCOI(pcop)->rIdx = r->rIdx;
4135                 } else {
4136 //                      fprintf(stderr, "%s:%d %s reg %s doesn't exist\n", __FILE__, __LINE__, __FUNCTION__, name);
4137                         PCOI(pcop)->rIdx = -1;
4138                 }
4139 //                      fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
4140         } else {
4141                 pcop->name = NULL;
4142                 PCOI(pcop)->rIdx = -1;
4143         }
4144
4145         PCOI(pcop)->index = index;
4146         PCOI(pcop)->offset = offset;
4147         PCOI(pcop)->_const = code_space;
4148
4149   return pcop;
4150 }
4151
4152 /*-----------------------------------------------------------------*/
4153 /*-----------------------------------------------------------------*/
4154 pCodeOp *pic16_newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
4155 {
4156   char *s = buffer;
4157   pCodeOp *pcop;
4158
4159
4160   if(!pcwb || !subtype) {
4161     fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
4162     exit(1);
4163   }
4164
4165   pcop = Safe_calloc(1,sizeof(pCodeOpWild));
4166   pcop->type = PO_WILD;
4167   sprintf(s,"%%%d",id);
4168   pcop->name = Safe_strdup(s);
4169
4170   PCOW(pcop)->id = id;
4171   PCOW(pcop)->pcwb = pcwb;
4172   PCOW(pcop)->subtype = subtype;
4173   PCOW(pcop)->matched = NULL;
4174
4175   PCOW(pcop)->pcop2 = NULL;
4176   
4177   return pcop;
4178 }
4179
4180 /*-----------------------------------------------------------------*/
4181 /*-----------------------------------------------------------------*/
4182 pCodeOp *pic16_newpCodeOpWild2(int id, int id2, pCodeWildBlock *pcwb, pCodeOp *subtype, pCodeOp *subtype2)
4183 {
4184   char *s = buffer;
4185   pCodeOp *pcop;
4186
4187
4188         if(!pcwb || !subtype || !subtype2) {
4189                 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
4190                 exit(1);
4191         }
4192
4193         pcop = Safe_calloc(1,sizeof(pCodeOpWild));
4194         pcop->type = PO_WILD;
4195         sprintf(s,"%%%d",id);
4196         pcop->name = Safe_strdup(s);
4197
4198         PCOW(pcop)->id = id;
4199         PCOW(pcop)->pcwb = pcwb;
4200         PCOW(pcop)->subtype = subtype;
4201         PCOW(pcop)->matched = NULL;
4202
4203         PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4204
4205         if(!subtype2->name) {
4206                 PCOW(pcop)->pcop2 = Safe_calloc(1, sizeof(pCodeOpWild));
4207                 PCOW2(pcop)->pcop.type = PO_WILD;
4208                 sprintf(s, "%%%d", id2);
4209                 PCOW2(pcop)->pcop.name = Safe_strdup(s);
4210                 PCOW2(pcop)->id = id2;
4211                 PCOW2(pcop)->subtype = subtype2;
4212
4213 //              fprintf(stderr, "%s:%d %s [wild,wild] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4214 //                              pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4215         } else {
4216                 PCOW2(pcop)->pcop2 = pic16_pCodeOpCopy( subtype2 );
4217
4218 //              fprintf(stderr, "%s:%d %s [wild,str] for name: %s (%d)\tname2: %s (%d)\n", __FILE__, __LINE__, __FUNCTION__,
4219 //                              pcop->name, id, PCOW2(pcop)->pcop.name, id2);
4220         }
4221   
4222
4223
4224   return pcop;
4225 }
4226
4227
4228 /*-----------------------------------------------------------------*/
4229 /*-----------------------------------------------------------------*/
4230 pCodeOp *pic16_newpCodeOpBit(char *s, int bit, int inBitSpace, PIC_OPTYPE subt)
4231 {
4232   pCodeOp *pcop;
4233   
4234   pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
4235   pcop->type = PO_GPR_BIT;
4236   if(s)
4237     pcop->name = Safe_strdup(s);   
4238   else
4239     pcop->name = NULL;
4240
4241   PCORB(pcop)->bit = bit;
4242   PCORB(pcop)->inBitSpace = inBitSpace;
4243   PCORB(pcop)->subtype = subt;
4244
4245   /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */
4246   PCOR(pcop)->r = pic16_regWithName(s); //NULL;
4247 //  fprintf(stderr, "%s:%d %s for reg: %s\treg= %p\n", __FILE__, __LINE__, __FUNCTION__, s, PCOR(pcop)->r);
4248 //  PCOR(pcop)->rIdx = 0;
4249   return pcop;
4250 }
4251
4252 pCodeOp *pic16_newpCodeOpBit_simple (struct asmop *op, int offs, int bit)
4253 {
4254   return pic16_newpCodeOpBit (pic16_aopGet(op,offs,FALSE,FALSE),
4255                                 bit, 0, PO_GPR_REGISTER);
4256 }
4257
4258
4259 /*-----------------------------------------------------------------*
4260  * pCodeOp *pic16_newpCodeOpReg(int rIdx) - allocate a new register
4261  *
4262  * If rIdx >=0 then a specific register from the set of registers
4263  * will be selected. If rIdx <0, then a new register will be searched
4264  * for.
4265  *-----------------------------------------------------------------*/
4266
4267 pCodeOp *pic16_newpCodeOpReg(int rIdx)
4268 {
4269   pCodeOp *pcop;
4270   regs *r;
4271
4272   pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4273
4274   pcop->name = NULL;
4275
4276   if(rIdx >= 0) {
4277         r = pic16_regWithIdx(rIdx);
4278         if(!r)
4279                 r = pic16_allocWithIdx(rIdx);
4280   } else {
4281     r = pic16_findFreeReg(REG_GPR);
4282
4283     if(!r) {
4284         fprintf(stderr, "%s:%d Could not find a free GPR register\n",
4285                 __FUNCTION__, __LINE__);
4286         exit(EXIT_FAILURE);
4287     }
4288   }
4289
4290   PCOR(pcop)->rIdx = rIdx;
4291   PCOR(pcop)->r = r;
4292   pcop->type = PCOR(pcop)->r->pc_type;
4293
4294   return pcop;
4295 }
4296
4297 pCodeOp *pic16_newpCodeOpRegNotVect(bitVect *bv)
4298 {
4299   pCodeOp *pcop;
4300   regs *r;
4301   
4302     pcop = Safe_calloc(1, sizeof(pCodeOpReg));
4303     pcop->name = NULL;
4304     
4305     r = pic16_findFreeReg(REG_GPR);
4306
4307     while(r) {
4308       if(!bitVectBitValue(bv, r->rIdx)) {
4309         PCOR(pcop)->r = r;
4310         PCOR(pcop)->rIdx = r->rIdx;
4311         pcop->type = r->pc_type;
4312         return (pcop);
4313       }
4314       
4315       r = pic16_findFreeRegNext(REG_GPR, r);
4316     }
4317   
4318   return NULL;
4319 }
4320
4321       
4322
4323 pCodeOp *pic16_newpCodeOpRegFromStr(char *name)
4324 {
4325   pCodeOp *pcop;
4326   regs *r;
4327
4328         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
4329         PCOR(pcop)->r = r = pic16_allocRegByName(name, 1, NULL);
4330         PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
4331         pcop->type = PCOR(pcop)->r->pc_type;
4332         pcop->name = PCOR(pcop)->r->name;
4333
4334 //      if(pic16_pcode_verbose) {
4335 //              fprintf(stderr, "%s:%d %s allocates register %s rIdx:0x%02x\n",
4336 //                      __FILE__, __LINE__, __FUNCTION__, r->name, r->rIdx);
4337 //      }
4338
4339   return pcop;
4340 }
4341
4342 /*-----------------------------------------------------------------*/
4343 /*-----------------------------------------------------------------*/
4344 pCodeOp *pic16_newpCodeOpOpt(OPT_TYPE type, char *key)
4345 {
4346   pCodeOpOpt *pcop;
4347
4348         pcop = Safe_calloc(1, sizeof(pCodeOpOpt));
4349         
4350         pcop->type = type;
4351         pcop->key = Safe_strdup( key );
4352
4353   return (PCOP(pcop));
4354 }
4355
4356 /*-----------------------------------------------------------------*/
4357 /*-----------------------------------------------------------------*/
4358 pCodeOp *pic16_newpCodeOpLocalRegs(LR_TYPE type)
4359 {
4360   pCodeOpLocalReg *pcop;
4361
4362         pcop = Safe_calloc(1, sizeof(pCodeOpLocalReg));
4363         
4364         pcop->type = type;
4365
4366   return (PCOP(pcop));
4367 }
4368
4369
4370 /*-----------------------------------------------------------------*/
4371 /*-----------------------------------------------------------------*/
4372
4373 pCodeOp *pic16_newpCodeOp(char *name, PIC_OPTYPE type)
4374 {
4375   pCodeOp *pcop;
4376
4377   switch(type) {
4378   case PO_BIT:
4379   case PO_GPR_BIT:
4380     pcop = pic16_newpCodeOpBit(name, -1,0, type);
4381     break;
4382
4383   case PO_LITERAL:
4384     pcop = pic16_newpCodeOpLit(-1);
4385     break;
4386
4387   case PO_LABEL:
4388     pcop = pic16_newpCodeOpLabel(NULL,-1);
4389     break;
4390   case PO_GPR_TEMP:
4391     pcop = pic16_newpCodeOpReg(-1);
4392     break;
4393
4394   case PO_GPR_REGISTER:
4395     if(name)
4396       pcop = pic16_newpCodeOpRegFromStr(name);
4397     else
4398       pcop = pic16_newpCodeOpReg(-1);
4399     break;
4400     
4401   case PO_TWO_OPS:
4402     assert( !"Cannot create PO_TWO_OPS from string!" );
4403     pcop = NULL;
4404     break;
4405
4406   default:
4407     pcop = Safe_calloc(1,sizeof(pCodeOp) );
4408     pcop->type = type;
4409     if(name)
4410       pcop->name = Safe_strdup(name);   
4411     else
4412       pcop->name = NULL;
4413   }
4414
4415   return pcop;
4416 }
4417
4418 pCodeOp *pic16_newpCodeOp2(pCodeOp *src, pCodeOp *dst)
4419 {
4420   pCodeOp2 *pcop2 = Safe_calloc(1, sizeof(pCodeOp2));
4421   pcop2->pcop.type = PO_TWO_OPS;
4422   pcop2->pcopL = src;
4423   pcop2->pcopR = dst;
4424   return PCOP(pcop2);
4425 }
4426
4427 /* This is a multiple of two as gpasm pads DB directives to even length,
4428  * thus the data would be interleaved with \0 bytes...
4429  * This is a multiple of three in order to have arrays of 3-byte pointers
4430  * continuously in memory (without 0-padding at the lines' end).
4431  * This is rather 12 than 6 in order not to split up 4-byte data types
4432  * in arrays right in the middle of a 4-byte word. */
4433 #define DB_ITEMS_PER_LINE       12
4434
4435 typedef struct DBdata
4436   {
4437     int count;
4438     char buffer[512];
4439   } DBdata;
4440
4441 struct DBdata DBd;
4442 static int DBd_init = -1;
4443
4444 /*-----------------------------------------------------------------*/
4445 /*    Initialiase "DB" data buffer                                 */
4446 /*-----------------------------------------------------------------*/
4447 void pic16_initDB(void)
4448 {
4449         DBd_init = -1;
4450 }
4451
4452
4453 /*-----------------------------------------------------------------*/
4454 /*    Flush pending "DB" data to a pBlock                          */
4455 /*                                                                 */
4456 /* ptype - type of p pointer, 'f' file pointer, 'p' pBlock pointer */
4457 /*-----------------------------------------------------------------*/
4458 void pic16_flushDB(char ptype, void *p)
4459 {
4460         if (DBd.count>0) {
4461                 if(ptype == 'p')
4462                         pic16_addpCode2pBlock(((pBlock *)p),pic16_newpCodeAsmDir("DB", "%s", DBd.buffer));
4463                 else
4464                 if(ptype == 'f')
4465                         fprintf(((FILE *)p), "\tdb\t%s\n", DBd.buffer);
4466                 else {
4467                         /* sanity check */
4468                         fprintf(stderr, "PIC16 port error: could not emit initial value data\n");
4469                 }
4470
4471                 DBd.count = 0;
4472                 DBd.buffer[0] = '\0';
4473         }
4474 }
4475
4476
4477 /*-----------------------------------------------------------------*/
4478 /*    Add "DB" directives to a pBlock                              */
4479 /*-----------------------------------------------------------------*/
4480 void pic16_emitDB(int c, char ptype, void *p)
4481 {
4482   int l;
4483
4484         if (DBd_init<0) {
4485          // we need to initialize
4486                 DBd_init = 0;
4487                 DBd.count = 0;
4488                 DBd.buffer[0] = '\0';
4489         }
4490
4491         l = strlen(DBd.buffer);
4492         sprintf(DBd.buffer+l,"%s0x%02x", (DBd.count>0?", ":""), c & 0xff);
4493
4494 //      fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4495         
4496         DBd.count++;
4497         if (DBd.count>= DB_ITEMS_PER_LINE)
4498                 pic16_flushDB(ptype, p);
4499 }
4500
4501 void pic16_emitDS(char *s, char ptype, void *p)
4502 {
4503   int l;
4504
4505         if (DBd_init<0) {
4506          // we need to initialize
4507                 DBd_init = 0;
4508                 DBd.count = 0;
4509                 DBd.buffer[0] = '\0';
4510         }
4511
4512         l = strlen(DBd.buffer);
4513         sprintf(DBd.buffer+l,"%s%s", (DBd.count>0?", ":""), s);
4514
4515 //      fprintf(stderr, "%s:%d DBbuffer: '%s'\n", __FILE__, __LINE__, DBd.buffer);
4516
4517         DBd.count++;    //=strlen(s);
4518         if (DBd.count>=DB_ITEMS_PER_LINE)
4519                 pic16_flushDB(ptype, p);
4520 }
4521
4522
4523 /*-----------------------------------------------------------------*/
4524 /*-----------------------------------------------------------------*/
4525 void pic16_pCodeConstString(char *name, char *value)
4526 {
4527   pBlock *pb;
4528   char *item;
4529   static set *emittedSymbols = NULL;
4530
4531   if(!name || !value)
4532     return;
4533
4534   /* keep track of emitted symbols to avoid multiple definition of str_<nr> */
4535   if (emittedSymbols) {
4536     /* scan set for name */
4537     for (item = setFirstItem (emittedSymbols); item; item = setNextItem (emittedSymbols))
4538     {
4539       if (!strcmp (item,name)) {
4540         //fprintf (stderr, "%s already emitted\n", name);
4541         return;
4542       } // if
4543     } // for
4544   } // if
4545   addSet (&emittedSymbols, Safe_strdup (name));
4546
4547   //fprintf(stderr, " %s  %s  %s\n",__FUNCTION__,name,value);
4548
4549   pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4550
4551   pic16_addpBlock(pb);
4552
4553 //  sprintf(buffer,"; %s = ", name);
4554 //  strcat(buffer, value);
4555 //  fputs(buffer, stderr);
4556
4557 //  pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(buffer));
4558   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(name,-1));
4559
4560   do {
4561         pic16_emitDB(*value, 'p', (void *)pb);
4562   }while (*value++);
4563   pic16_flushDB('p', (void *)pb);
4564 }
4565
4566 /*-----------------------------------------------------------------*/
4567 /*-----------------------------------------------------------------*/
4568 #if 0
4569 static void pCodeReadCodeTable(void)
4570 {
4571   pBlock *pb;
4572
4573   fprintf(stderr, " %s\n",__FUNCTION__);
4574
4575   pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block"));
4576
4577   pic16_addpBlock(pb);
4578
4579   pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; ReadCodeTable - built in function"));
4580   pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
4581   pic16_addpCode2pBlock(pb,pic16_newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
4582   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("ReadCodeTable:",-1));
4583
4584   pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp2")));
4585   pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCLATH")));
4586   pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVFW,pic16_newpCodeOpRegFromStr("temp1")));
4587   pic16_addpCode2pBlock(pb,pic16_newpCode(POC_MOVWF,pic16_newpCodeOpRegFromStr("PCL")));
4588
4589
4590 }
4591 #endif
4592 /*-----------------------------------------------------------------*/
4593 /* pic16_addpCode2pBlock - place the pCode into the pBlock linked list   */
4594 /*-----------------------------------------------------------------*/
4595 void pic16_addpCode2pBlock(pBlock *pb, pCode *pc)
4596 {
4597
4598   if(!pc)
4599     return;
4600
4601   if(!pb->pcHead) {
4602     /* If this is the first pcode to be added to a block that
4603      * was initialized with a NULL pcode, then go ahead and
4604      * make this pcode the head and tail */
4605     pb->pcHead  = pb->pcTail = pc;
4606   } else {
4607     //    if(pb->pcTail)
4608     pb->pcTail->next = pc;
4609
4610     pc->prev = pb->pcTail;
4611     pc->pb = pb;
4612
4613     pb->pcTail = pc;
4614   }
4615 }
4616
4617 /*-----------------------------------------------------------------*/
4618 /* pic16_addpBlock - place a pBlock into the pFile                 */
4619 /*-----------------------------------------------------------------*/
4620 void pic16_addpBlock(pBlock *pb)
4621 {
4622   // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
4623
4624   if(!the_pFile) {
4625     /* First time called, we'll pass through here. */
4626     //_ALLOC(the_pFile,sizeof(pFile));
4627     the_pFile = Safe_calloc(1,sizeof(pFile));
4628     the_pFile->pbHead = the_pFile->pbTail = pb;
4629     the_pFile->functions = NULL;
4630     return;
4631   }
4632
4633   the_pFile->pbTail->next = pb;
4634   pb->prev = the_pFile->pbTail;
4635   pb->next = NULL;
4636   the_pFile->pbTail = pb;
4637 }
4638
4639 /*-----------------------------------------------------------------*/
4640 /* removepBlock - remove a pBlock from the pFile                   */
4641 /*-----------------------------------------------------------------*/
4642 static void removepBlock(pBlock *pb)
4643 {
4644   pBlock *pbs;
4645
4646   if(!the_pFile)
4647     return;
4648
4649
4650   //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
4651
4652   for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
4653     if(pbs == pb) {
4654
4655       if(pbs == the_pFile->pbHead)
4656         the_pFile->pbHead = pbs->next;
4657
4658       if (pbs == the_pFile->pbTail) 
4659         the_pFile->pbTail = pbs->prev;
4660
4661       if(pbs->next)
4662         pbs->next->prev = pbs->prev;
4663
4664       if(pbs->prev)
4665         pbs->prev->next = pbs->next;
4666
4667       return;
4668
4669     }
4670   }
4671
4672   fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
4673
4674 }
4675
4676 /*-----------------------------------------------------------------*/
4677 /* printpCode - write the contents of a pCode to a file            */
4678 /*-----------------------------------------------------------------*/
4679 static void printpCode(FILE *of, pCode *pc)
4680 {
4681
4682   if(!pc || !of)
4683     return;
4684
4685   if(pc->print) {
4686     pc->print(of,pc);
4687     return;
4688   }
4689
4690   fprintf(of,"warning - unable to print pCode\n");
4691 }
4692
4693 /*-----------------------------------------------------------------*/
4694 /* pic16_printpBlock - write the contents of a pBlock to a file    */
4695 /*-----------------------------------------------------------------*/
4696 void pic16_printpBlock(FILE *of, pBlock *pb)
4697 {
4698   pCode *pc;
4699
4700         if(!pb)return;
4701
4702         if(!of)of=stderr;
4703
4704         for(pc = pb->pcHead; pc; pc = pc->next) {
4705                 if(isPCF(pc) && PCF(pc)->fname) {
4706                         fprintf(of, "S_%s_%s\tcode", PCF(pc)->modname, PCF(pc)->fname);
4707                         if(pb->dbName == 'A') {
4708                           absSym *ab;
4709                                 for(ab=setFirstItem(absSymSet); ab; ab=setNextItem(absSymSet)) {
4710 //                                      fprintf(stderr, "%s:%d testing %s <-> %s\n", __FILE__, __LINE__, PCF(pc)->fname, ab->name);
4711                                         if(!strcmp(ab->name, PCF(pc)->fname)) {
4712 //                                              fprintf(stderr, "%s:%d address = %x\n", __FILE__, __LINE__, ab->address);
4713                                                 if(ab->address != -1)
4714                                                   fprintf(of, "\t0X%06X", ab->address);
4715                                                 break;
4716                                         }
4717                                 }
4718                         }
4719                         fprintf(of, "\n");
4720                 }
4721                 printpCode(of,pc);
4722         }
4723 }
4724
4725 /*-----------------------------------------------------------------*/
4726 /*                                                                 */
4727 /*       pCode processing                                          */
4728 /*                                                                 */
4729 /*                                                                 */
4730 /*                                                                 */
4731 /*-----------------------------------------------------------------*/
4732 pCode * pic16_findNextInstruction(pCode *pci);
4733 pCode * pic16_findPrevInstruction(pCode *pci);
4734
4735 void pic16_unlinkpCode(pCode *pc)
4736 {
4737   pCode *prev;
4738
4739   if(pc) {
4740 #ifdef PCODE_DEBUG
4741     fprintf(stderr,"Unlinking: ");
4742     printpCode(stderr, pc);
4743 #endif
4744     if(pc->prev) 
4745       pc->prev->next = pc->next;
4746     if(pc->next)
4747       pc->next->prev = pc->prev;
4748
4749     /* move C source line down (or up) */
4750     if (isPCI(pc) && PCI(pc)->cline) {
4751       prev = pic16_findNextInstruction (pc->next);
4752       if (prev && isPCI(prev) && !PCI(prev)->cline) {
4753         PCI(prev)->cline = PCI(pc)->cline;
4754       } else {
4755         prev = pic16_findPrevInstruction (pc->prev);
4756         if (prev && isPCI(prev) && !PCI(prev)->cline)
4757           PCI(prev)->cline = PCI(pc)->cline;
4758       }
4759     }
4760     pc->prev = pc->next = NULL;
4761   }
4762 }
4763
4764 /*-----------------------------------------------------------------*/
4765 /*-----------------------------------------------------------------*/
4766
4767 static void genericDestruct(pCode *pc)
4768 {
4769
4770   pic16_unlinkpCode(pc);
4771
4772   if(isPCI(pc)) {
4773     /* For instructions, tell the register (if there's one used)
4774      * that it's no longer needed */
4775     regs *reg = pic16_getRegFromInstruction(pc);
4776     if(reg)
4777       deleteSetItem (&(reg->reglives.usedpCodes),pc);
4778
4779         if(PCI(pc)->is2MemOp) {
4780                 reg = pic16_getRegFromInstruction2(pc);
4781                 if(reg)
4782                         deleteSetItem(&(reg->reglives.usedpCodes), pc);
4783         }
4784   }
4785
4786   /* Instead of deleting the memory used by this pCode, mark
4787    * the object as bad so that if there's a pointer to this pCode
4788    * dangling around somewhere then (hopefully) when the type is
4789    * checked we'll catch it.
4790    */
4791
4792   pc->type = PC_BAD;
4793   pic16_addpCode2pBlock(pb_dead_pcodes, pc);
4794
4795   //Safe_free(pc);
4796 }
4797
4798
4799 void DEBUGpic16_emitcode (char *inst,char *fmt, ...);
4800 /*-----------------------------------------------------------------*/
4801 /*-----------------------------------------------------------------*/
4802 /* modifiers for constant immediate */
4803 const char *immdmod[3]={"LOW", "HIGH", "UPPER"};
4804
4805 char *pic16_get_op(pCodeOp *pcop,char *buffer, size_t size)
4806 {
4807   regs *r;
4808   static char b[128];
4809   char *s;
4810   int use_buffer = 1;    // copy the string to the passed buffer pointer
4811
4812         if(!buffer) {
4813                 buffer = b;
4814                 size = sizeof(b);
4815                 use_buffer = 0;     // Don't bother copying the string to the buffer.
4816         } 
4817
4818         if(pcop) {
4819
4820                 switch(pcop->type) {
4821                         case PO_W:
4822                         case PO_WREG:
4823                         case PO_PRODL:
4824                         case PO_PRODH:
4825                         case PO_INDF0:
4826                         case PO_FSR0:
4827                                 if(use_buffer) {
4828                                         SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
4829                                         return (buffer);
4830                                 }
4831                                 return (PCOR(pcop)->r->name);
4832                                 break;
4833                         case PO_GPR_TEMP:
4834                                 r = pic16_regWithIdx(PCOR(pcop)->r->rIdx);
4835                                 if(use_buffer) {
4836                                         SAFE_snprintf(&buffer,&size,"%s",r->name);
4837                                         return (buffer);
4838                                 }
4839                                 return (r->name);
4840
4841                         case PO_IMMEDIATE:
4842                                 s = buffer;
4843                                 if(PCOI(pcop)->offset && PCOI(pcop)->offset<4) {
4844                                         if(PCOI(pcop)->index) {
4845                                                 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4846                                                         immdmod[ PCOI(pcop)->offset ],
4847                                                         pcop->name,
4848                                                         PCOI(pcop)->index);
4849                                         } else {
4850                                                 SAFE_snprintf(&s,&size,"%s(%s)",
4851                                                         immdmod[ PCOI(pcop)->offset ],
4852                                                         pcop->name);
4853                                         }
4854                                 } else {
4855                                         if(PCOI(pcop)->index) {
4856                                                 SAFE_snprintf(&s,&size, "%s(%s + %d)",
4857                                                         immdmod[ 0 ],
4858                                                         pcop->name,
4859                                                         PCOI(pcop)->index);
4860                                         } else {
4861                                                 SAFE_snprintf(&s,&size, "%s(%s)",
4862                                                         immdmod[ 0 ],
4863                                                         pcop->name);
4864                                         }
4865                                 }
4866                                 return (buffer);
4867
4868                         case PO_GPR_REGISTER:
4869                         case PO_DIR:
4870                                 s = buffer;
4871 //                              size = sizeof(buffer);
4872                                 if( PCOR(pcop)->instance) {
4873                                         SAFE_snprintf(&s,&size,"(%s + %d)",
4874                                                 pcop->name,
4875                                                 PCOR(pcop)->instance );
4876                                 } else {
4877                                         SAFE_snprintf(&s,&size,"%s",pcop->name);
4878                                 }
4879                                 return (buffer);
4880                         case PO_GPR_BIT:
4881                                 s = buffer;
4882                                 if(PCORB(pcop)->subtype == PO_GPR_TEMP) {
4883                                         SAFE_snprintf(&s, &size, "%s", pcop->name);
4884                                 } else {
4885                                         if(PCORB(pcop)->pcor.instance)
4886                                                 SAFE_snprintf(&s, &size, "(%s + %d)", pcop->name, PCORB(pcop)->pcor.instance);
4887                                         else
4888                                                 SAFE_snprintf(&s, &size, "%s", pcop->name);
4889                                 }
4890
4891                                 return (buffer);
4892                         case PO_TWO_OPS:
4893                                 return (pic16_get_op( PCOP2(pcop)->pcopL, use_buffer ? buffer : NULL, size ));
4894                                 
4895                         default:
4896                                 if(pcop->name) {
4897                                         if(use_buffer) {
4898                                                 SAFE_snprintf(&buffer,&size,"%s",pcop->name);
4899                                                 return (buffer);
4900                                         }
4901                                 return (pcop->name);
4902                                 }
4903
4904                 }
4905                 return ("unhandled type for op1");
4906         }
4907
4908   return ("NO operand1");
4909 }
4910
4911 /*-----------------------------------------------------------------*/
4912 /* pic16_get_op2 - variant to support two memory operand commands  */
4913 /*-----------------------------------------------------------------*/
4914 char *pic16_get_op2(pCodeOp *pcop,char *buffer, size_t size)
4915 {
4916
4917   if(pcop && pcop->type == PO_TWO_OPS) {
4918     return pic16_get_op( PCOP2(pcop)->pcopR, buffer, size );
4919   }
4920
4921   return "NO operand2";
4922 }
4923
4924 /*-----------------------------------------------------------------*/
4925 /*-----------------------------------------------------------------*/
4926 static char *pic16_get_op_from_instruction( pCodeInstruction *pcc)
4927 {
4928
4929   if(pcc )
4930     return pic16_get_op(pcc->pcop,NULL,0);
4931
4932   /* gcc 3.2:  warning: concatenation of string literals with __FUNCTION__ is deprecated 
4933    *   return ("ERROR Null: "__FUNCTION__);
4934    */
4935   return ("ERROR Null: pic16_get_op_from_instruction");
4936
4937 }
4938
4939 /*-----------------------------------------------------------------*/
4940 /*-----------------------------------------------------------------*/
4941 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
4942 {
4943
4944   fprintf(of,"pcodeopprint- not implemented\n");
4945 }
4946
4947 /*-----------------------------------------------------------------*/
4948 /* pic16_pCode2str - convert a pCode instruction to string               */
4949 /*-----------------------------------------------------------------*/
4950 char *pic16_pCode2str(char *str, size_t size, pCode *pc)
4951 {
4952   char *s = str;
4953   regs *r;
4954
4955 #if 0
4956         if(isPCI(pc) && (PCI(pc)->pci_magic != PCI_MAGIC)) {
4957                 fprintf(stderr, "%s:%d: pCodeInstruction initialization error in instruction %s, magic is %x (defaut: %x)\n",
4958                         __FILE__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pci_magic, PCI_MAGIC);
4959 //              exit(EXIT_FAILURE);
4960         }
4961 #endif
4962
4963   switch(pc->type) {
4964
4965   case PC_OPCODE:
4966     SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
4967
4968     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
4969
4970         //if(PCI(pc)->is2MemOp)
4971         if (PCI(pc)->pcop->type == PO_TWO_OPS)
4972         {
4973                 /* split into two phases due to static buffer in pic16_get_op() */
4974                 SAFE_snprintf(&s,&size, "%s", 
4975                         pic16_get_op((PCI(pc)->pcop), NULL, 0));
4976                 SAFE_snprintf(&s, &size, ", %s",
4977                         pic16_get_op2((PCI(pc)->pcop), NULL, 0));
4978                 break;
4979         }
4980
4981         if(PCI(pc)->is2LitOp) {
4982                 SAFE_snprintf(&s,&size, "%s", PCOP(PCI(pc)->pcop)->name);
4983                 break;
4984         }
4985
4986       if(PCI(pc)->isBitInst) {
4987         if(PCI(pc)->pcop->type != PO_GPR_BIT) {
4988           if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
4989             SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", 
4990                           PCI(pc)->pcop->name ,
4991                           PCI(pc)->pcop->name );
4992           else
4993             SAFE_snprintf(&s,&size,"%s,%d", pic16_get_op_from_instruction(PCI(pc)),
4994 //                        (((pCodeOpRegBit *)(PCI(pc)->pcop))->pcor.instance),
4995                           (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit ));
4996                           
4997         } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
4998           SAFE_snprintf(&s,&size,"%s, %d", pic16_get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
4999         } else
5000           SAFE_snprintf(&s,&size,"%s,0 ; ?bug", pic16_get_op_from_instruction(PCI(pc)));
5001         //PCI(pc)->pcop->t.bit );
5002       } else {
5003
5004         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
5005           if( PCI(pc)->num_ops == 3)
5006             SAFE_snprintf(&s,&size,"(%s >> 3),%c",pic16_get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
5007           else
5008             SAFE_snprintf(&s,&size,"(1 << (%s & 7))",pic16_get_op_from_instruction(PCI(pc)));
5009
5010         }
5011         else 
5012         {
5013           SAFE_snprintf(&s,&size,"%s", pic16_get_op_from_instruction(PCI(pc)));
5014         }
5015       }
5016         if( PCI(pc)->num_ops == 3 || ((PCI(pc)->num_ops == 2) && (PCI(pc)->isAccess))) {
5017           if(PCI(pc)->num_ops == 3 && !PCI(pc)->isBitInst)
5018             SAFE_snprintf(&s,&size,", %c", ( (PCI(pc)->isModReg) ? 'F':'W'));
5019
5020           r = pic16_getRegFromInstruction(pc);
5021 //              fprintf(stderr, "%s:%d reg = %p\tname= %s, accessBank= %d\n",
5022 //                      __FUNCTION__, __LINE__, r, (r)?r->name:"<null>", (r)?isACCESS_BANK(r):-1);
5023
5024           if(PCI(pc)->isAccess) {
5025             static char *bank_spec[2][2] = {
5026               { "", ", ACCESS" },  /* gpasm uses access bank by default */
5027               { ", B", ", BANKED" }/* MPASM (should) use BANKED by default */
5028             };
5029              
5030             SAFE_snprintf(&s,&size,"%s", bank_spec[(r && !isACCESS_BANK(r)) ? 1 : 0][pic16_mplab_comp ? 1 : 0]);
5031           }
5032         }
5033 //      
5034
5035     }
5036     break;
5037
5038   case PC_COMMENT:
5039     /* assuming that comment ends with a \n */
5040     SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
5041     break;
5042
5043   case PC_INFO:
5044     SAFE_snprintf(&s,&size,"; info ==>");
5045     switch( PCINF(pc)->type ) {
5046       case INF_OPTIMIZATION:
5047           SAFE_snprintf(&s,&size, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
5048           break;
5049       case INF_LOCALREGS:
5050           SAFE_snprintf(&s,&size, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
5051           break;
5052     }; break;
5053
5054   case PC_INLINE:
5055     /* assuming that inline code ends with a \n */
5056     SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
5057     break;
5058
5059   case PC_LABEL:
5060     SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
5061     break;
5062   case PC_FUNCTION:
5063     SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
5064     break;
5065   case PC_WILD:
5066     SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
5067     break;
5068   case PC_FLOW:
5069     SAFE_snprintf(&s,&size,";\t--FLOW change\n");
5070     break;
5071   case PC_CSOURCE:
5072 //    SAFE_snprintf(&s,&size,";#CSRC\t%s %d\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
5073       SAFE_snprintf(&s,&size,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
5074         PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
5075     break;
5076   case PC_ASMDIR:
5077         if(PCAD(pc)->directive) {
5078                 SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
5079         } else
5080         if(PCAD(pc)->arg) {
5081                 /* special case to handle inline labels without a tab */
5082                 SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
5083         }
5084         break;
5085
5086   case PC_BAD:
5087     SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
5088     break;
5089   }
5090
5091   return str;
5092
5093 }
5094
5095 /*-----------------------------------------------------------------*/
5096 /* genericPrint - the contents of a pCode to a file                */
5097 /*-----------------------------------------------------------------*/
5098 static void genericPrint(FILE *of, pCode *pc)
5099 {
5100
5101   if(!pc || !of)
5102     return;
5103
5104   switch(pc->type) {
5105   case PC_COMMENT:
5106 //    fputs(((pCodeComment *)pc)->comment, of);
5107     fprintf(of,"; %s\n", ((pCodeComment *)pc)->comment);
5108     break;
5109
5110   case PC_INFO:
5111     {
5112       pBranch *pbl = PCI(pc)->label;
5113       while(pbl && pbl->pc) {
5114         if(pbl->pc->type == PC_LABEL)
5115           pCodePrintLabel(of, pbl->pc);
5116         pbl = pbl->next;
5117       }
5118     }
5119           
5120     if(pic16_pcode_verbose) {
5121       fprintf(of, "; info ==>");
5122       switch(((pCodeInfo *)pc)->type) {
5123         case INF_OPTIMIZATION:
5124               fprintf(of, " [optimization] %s\n", OPT_TYPE_STR[ PCOO(PCINF(pc)->oper1)->type ]);
5125               break;
5126         case INF_LOCALREGS:
5127               fprintf(of, " [localregs] %s\n", LR_TYPE_STR[ PCOLR(PCINF(pc)->oper1)->type ]);
5128               break;
5129         }
5130     };
5131     
5132     break;
5133
5134   case PC_INLINE:
5135     fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
5136      break;
5137
5138   case PC_OPCODE:
5139     // If the opcode has a label, print that first
5140     {
5141       pBranch *pbl = PCI(pc)->label;
5142       while(pbl && pbl->pc) {
5143         if(pbl->pc->type == PC_LABEL)
5144           pCodePrintLabel(of, pbl->pc);
5145         pbl = pbl->next;
5146       }
5147     }
5148
5149     if(PCI(pc)->cline) 
5150       genericPrint(of,PCODE(PCI(pc)->cline));
5151
5152     {
5153       char str[256];
5154       
5155       pic16_pCode2str(str, 256, pc);
5156
5157       fprintf(of,"%s",str);
5158       /* Debug */
5159       if(pic16_debug_verbose) {
5160         fprintf(of, "\t;key=%03x",pc->seq);
5161         if(PCI(pc)->pcflow)
5162           fprintf(of,", flow seq=%03x",PCI(pc)->pcflow->pc.seq);
5163       }
5164     }
5165     fprintf(of, "\n");
5166     break;
5167       
5168   case PC_WILD:
5169     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
5170     if(PCW(pc)->pci.label)
5171       pCodePrintLabel(of, PCW(pc)->pci.label->pc);
5172
5173     if(PCW(pc)->operand) {
5174       fprintf(of,";\toperand  ");
5175       pCodeOpPrint(of,PCW(pc)->operand );
5176     }
5177     break;
5178
5179   case PC_FLOW:
5180     if(pic16_debug_verbose) {
5181       fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
5182       if(PCFL(pc)->ancestor)
5183         fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
5184       fprintf(of,"\n");
5185
5186     }
5187     break;
5188
5189   case PC_CSOURCE:
5190 //    fprintf(of,";#CSRC\t%s %d\t\t%s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
5191     fprintf(of,"%s\t.line\t%d; %s\t%s\n", ((pic16_mplab_comp || !options.debug)?";":""),
5192         PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
5193          
5194     break;
5195
5196   case PC_ASMDIR:
5197         {
5198           pBranch *pbl = PCAD(pc)->pci.label;
5199                 while(pbl && pbl->pc) {
5200                         if(pbl->pc->type == PC_LABEL)
5201                                 pCodePrintLabel(of, pbl->pc);
5202                         pbl = pbl->next;
5203                 }
5204         }
5205         if(PCAD(pc)->directive) {
5206                 fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
5207         } else
5208         if(PCAD(pc)->arg) {
5209                 /* special case to handle inline labels without tab */
5210                 fprintf(of, "%s\n", PCAD(pc)->arg);
5211         }
5212         break;
5213         
5214   case PC_LABEL:
5215   default:
5216     fprintf(of,"unknown pCode type %d\n",pc->type);
5217   }
5218
5219 }
5220
5221 /*-----------------------------------------------------------------*/
5222 /* pCodePrintFunction - prints function begin/end                  */
5223 /*-----------------------------------------------------------------*/
5224
5225 static void pCodePrintFunction(FILE *of, pCode *pc)
5226 {
5227
5228   if(!pc || !of)
5229     return;
5230
5231 #if 0
5232   if( ((pCodeFunction *)pc)->modname) 
5233     fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
5234 #endif
5235
5236   if(!PCF(pc)->absblock) {
5237       if(PCF(pc)->fname) {
5238       pBranch *exits = PCF(pc)->to;
5239       int i=0;
5240
5241       fprintf(of,"%s:", PCF(pc)->fname);
5242     
5243       if(pic16_pcode_verbose)
5244         fprintf(of, "\t;Function start");
5245     
5246       fprintf(of, "\n");
5247     
5248       while(exits) {
5249         i++;
5250         exits = exits->next;
5251       }
5252       //if(i) i--;
5253
5254       if(pic16_pcode_verbose)
5255         fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
5256     
5257     } else {
5258         if((PCF(pc)->from && 
5259                 PCF(pc)->from->pc->type == PC_FUNCTION &&
5260                 PCF(PCF(pc)->from->pc)->fname) ) {
5261
5262                 if(pic16_pcode_verbose)
5263                         fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
5264         } else {
5265                 if(pic16_pcode_verbose)
5266                         fprintf(of,"; exit point [can't find entry point]\n");
5267         }
5268         fprintf(of, "\n");
5269     }
5270   }
5271 }
5272 /*-----------------------------------------------------------------*/
5273 /* pCodePrintLabel - prints label                                  */
5274 /*-----------------------------------------------------------------*/
5275
5276 static void pCodePrintLabel(FILE *of, pCode *pc)
5277 {
5278
5279   if(!pc || !of)
5280     return;
5281
5282   if(PCL(pc)->label) 
5283     fprintf(of,"%s:\n",PCL(pc)->label);
5284   else if (PCL(pc)->key >=0) 
5285     fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
5286   else
5287     fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
5288
5289 }
5290 /*-----------------------------------------------------------------*/
5291 /* unlinkpCodeFromBranch - Search for a label in a pBranch and     */
5292 /*                         remove it if it is found.               */
5293 /*-----------------------------------------------------------------*/
5294 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
5295 {
5296   pBranch *b, *bprev;
5297
5298
5299   bprev = NULL;
5300
5301   if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
5302     b = PCI(pcl)->label;
5303   else {
5304     fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
5305     exit(1);
5306
5307   }
5308
5309   //fprintf (stderr, "%s \n",__FUNCTION__);
5310   //pcl->print(stderr,pcl);
5311   //pc->print(stderr,pc);
5312   while(b) {
5313     if(b->pc == pc) {
5314       //fprintf (stderr, "found label\n");
5315       //pc->print(stderr, pc);
5316
5317       /* Found a label */
5318       if(bprev) {
5319         bprev->next = b->next;  /* Not first pCode in chain */
5320 //      Safe_free(b);
5321       } else {
5322         pc->destruct(pc);
5323         PCI(pcl)->label = b->next;   /* First pCode in chain */
5324 //      Safe_free(b);
5325       }
5326       return;  /* A label can't occur more than once */
5327     }
5328     bprev = b;
5329     b = b->next;
5330   }
5331
5332 }
5333
5334 /*-----------------------------------------------------------------*/
5335 /*-----------------------------------------------------------------*/
5336 pBranch * pic16_pBranchAppend(pBranch *h, pBranch *n)
5337 {
5338   pBranch *b;
5339
5340   if(!h)
5341     return n;
5342
5343   if(h == n)
5344     return n;
5345
5346   b = h;
5347   while(b->next)
5348     b = b->next;
5349
5350   b->next = n;
5351
5352   return h;
5353   
5354 }  
5355 /*-----------------------------------------------------------------*/
5356 /* pBranchLink - given two pcodes, this function will link them    */
5357 /*               together through their pBranches                  */
5358 /*-----------------------------------------------------------------*/
5359 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
5360 {
5361   pBranch *b;
5362
5363   // Declare a new branch object for the 'from' pCode.
5364
5365   //_ALLOC(b,sizeof(pBranch));
5366   b = Safe_calloc(1,sizeof(pBranch));
5367   b->pc = PCODE(t);             // The link to the 'to' pCode.
5368   b->next = NULL;
5369
5370   f->to = pic16_pBranchAppend(f->to,b);
5371
5372   // Now do the same for the 'to' pCode.
5373
5374   //_ALLOC(b,sizeof(pBranch));
5375   b = Safe_calloc(1,sizeof(pBranch));
5376   b->pc = PCODE(f);
5377   b->next = NULL;
5378
5379   t->from = pic16_pBranchAppend(t->from,b);
5380   
5381 }
5382
5383 #if 1
5384 /*-----------------------------------------------------------------*/
5385 /* pBranchFind - find the pBranch in a pBranch chain that contains */
5386 /*               a pCode                                           */
5387 /*-----------------------------------------------------------------*/
5388 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
5389 {
5390   while(pb) {
5391
5392     if(pb->pc == pc)
5393       return pb;
5394
5395     pb = pb->next;
5396   }
5397
5398   return NULL;
5399 }
5400
5401 /*-----------------------------------------------------------------*/
5402 /* pic16_pCodeUnlink - Unlink the given pCode from its pCode chain.      */
5403 /*-----------------------------------------------------------------*/
5404 void pic16_pCodeUnlink(pCode *pc)
5405 {
5406   pBranch *pb1,*pb2;
5407   pCode *pc1;
5408
5409   if(!pc->prev || !pc->next) {
5410     fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
5411     exit(1);
5412   }
5413   
5414   /* move C source line down (or up) */
5415   if (isPCI(pc) && PCI(pc)->cline) {
5416     pc1 = pic16_findNextInstruction (pc->next);
5417     if (pc1 && isPCI(pc1) && !PCI(pc1)->cline) {
5418       PCI(pc1)->cline = PCI(pc)->cline;
5419     } else {
5420       pc1 = pic16_findPrevInstruction (pc->prev);
5421       if (pc1 && isPCI(pc1) && !PCI(pc1)->cline)
5422         PCI(pc1)->cline = PCI(pc)->cline;
5423     }
5424   }
5425
5426   /* first remove the pCode from the chain */
5427   pc->prev->next = pc->next;
5428   pc->next->prev = pc->prev;
5429
5430   pc->prev = pc->next = NULL;
5431
5432   /* Now for the hard part... */
5433
5434   /* Remove the branches */
5435
5436   pb1 = PCI(pc)->from;
5437   while(pb1) {
5438     pc1 = pb1->pc;    /* Get the pCode that branches to the
5439                        * one we're unlinking */
5440
5441     /* search for the link back to this pCode (the one we're
5442      * unlinking) */
5443     if((pb2 = pBranchFind(PCI(pc1)->to,pc))) {
5444       pb2->pc = PCI(pc)->to->pc;  // make the replacement
5445
5446       /* if the pCode we're unlinking contains multiple 'to'
5447        * branches (e.g. this a skip instruction) then we need
5448        * to copy these extra branches to the chain. */
5449       if(PCI(pc)->to->next)
5450         pic16_pBranchAppend(pb2, PCI(pc)->to->next);
5451     }
5452     
5453     pb1 = pb1->next;
5454   }
5455
5456
5457 }
5458 #endif
5459 /*-----------------------------------------------------------------*/
5460 /*-----------------------------------------------------------------*/
5461 #if 0
5462 static void genericAnalyze(pCode *pc)
5463 {
5464   switch(pc->type) {
5465   case PC_WILD:
5466   case PC_COMMENT:
5467     return;
5468   case PC_LABEL:
5469   case PC_FUNCTION:
5470   case PC_OPCODE:
5471     {
5472       // Go through the pCodes that are in pCode chain and link
5473       // them together through the pBranches. Note, the pCodes
5474       // are linked together as a contiguous stream like the 
5475       // assembly source code lines. The linking here mimics this
5476       // except that comments are not linked in.
5477       // 
5478       pCode *npc = pc->next;
5479       while(npc) {
5480         if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
5481           pBranchLink(pc,npc);
5482           return;
5483         } else
5484           npc = npc->next;
5485       }
5486       /* reached the end of the pcode chain without finding
5487        * an instruction we could link to. */
5488     }
5489     break;
5490   case PC_FLOW:
5491     fprintf(stderr,"analyze PC_FLOW\n");
5492
5493     return;
5494   case PC_BAD:
5495     fprintf(stderr,,";A bad pCode is being used\n");
5496
5497   }
5498 }
5499 #endif
5500
5501 /*-----------------------------------------------------------------*/
5502 /*-----------------------------------------------------------------*/
5503 static int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
5504 {
5505   pBranch *pbr;
5506
5507   if(pc->type == PC_LABEL) {
5508     if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
5509       return TRUE;
5510   }
5511   if((pc->type == PC_OPCODE)
5512         || (pc->type == PC_ASMDIR)
5513         ) {
5514     pbr = PCI(pc)->label;
5515     while(pbr) {
5516       if(pbr->pc->type == PC_LABEL) {
5517         if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
5518           return TRUE;
5519       }
5520       pbr = pbr->next;
5521     }
5522   }
5523
5524   return FALSE;
5525 }
5526
5527 /*-----------------------------------------------------------------*/
5528 /*-----------------------------------------------------------------*/
5529 static int checkLabel(pCode *pc)
5530 {
5531   pBranch *pbr;
5532
5533   if(pc && isPCI(pc)) {
5534     pbr = PCI(pc)->label;
5535     while(pbr) {
5536       if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
5537         return TRUE;
5538
5539       pbr = pbr->next;
5540     }
5541   }
5542
5543   return FALSE;
5544 }
5545
5546 /*-----------------------------------------------------------------*/
5547 /* findLabelinpBlock - Search the pCode for a particular label     */
5548 /*-----------------------------------------------------------------*/
5549 static pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
5550 {
5551   pCode  *pc;
5552
5553   if(!pb)
5554     return NULL;
5555
5556   for(pc = pb->pcHead; pc; pc = pc->next) 
5557     if(compareLabel(pc,pcop_label))
5558       return pc;
5559     
5560   return NULL;
5561 }
5562 #if 0
5563 /*-----------------------------------------------------------------*/
5564 /* findLabel - Search the pCode for a particular label             */
5565 /*-----------------------------------------------------------------*/
5566 static pCode * findLabel(pCodeOpLabel *pcop_label)
5567 {
5568   pBlock *pb;
5569   pCode  *pc;
5570
5571   if(!the_pFile)
5572     return NULL;
5573
5574   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5575     if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
5576       return pc;
5577   }
5578
5579   fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name);
5580   return NULL;
5581 }
5582 #endif
5583 /*-----------------------------------------------------------------*/
5584 /* pic16_findNextpCode - given a pCode, find the next of type 'pct'      */
5585 /*                 in the linked list                              */
5586 /*-----------------------------------------------------------------*/
5587 pCode * pic16_findNextpCode(pCode *pc, PC_TYPE pct)
5588 {
5589
5590   while(pc) {
5591     if(pc->type == pct)
5592       return pc;
5593
5594     pc = pc->next;
5595   }
5596
5597   return NULL;
5598 }
5599
5600 /*-----------------------------------------------------------------*/
5601 /* findPrevpCode - given a pCode, find the previous of type 'pct'  */
5602 /*                 in the linked list                              */
5603 /*-----------------------------------------------------------------*/
5604 static pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
5605 {
5606
5607   while(pc) {
5608     if(pc->type == pct)
5609       return pc;
5610
5611     pc = pc->prev;
5612   }
5613
5614   return NULL;
5615 }
5616
5617
5618 //#define PCODE_DEBUG
5619 /*-----------------------------------------------------------------*/
5620 /* pic16_findNextInstruction - given a pCode, find the next instruction  */
5621 /*                       in the linked list                        */
5622 /*-----------------------------------------------------------------*/
5623 pCode * pic16_findNextInstruction(pCode *pci)
5624 {
5625   pCode *pc = pci;
5626
5627   while(pc) {
5628     if((pc->type == PC_OPCODE)
5629         || (pc->type == PC_WILD)
5630         || (pc->type == PC_ASMDIR)
5631         )
5632       return pc;
5633
5634 #ifdef PCODE_DEBUG
5635     fprintf(stderr,"pic16_findNextInstruction:  ");
5636     printpCode(stderr, pc);
5637 #endif
5638     pc = pc->next;
5639   }
5640
5641   //fprintf(stderr,"Couldn't find instruction\n");
5642   return NULL;
5643 }
5644
5645 /*-----------------------------------------------------------------*/
5646 /* pic16_findPrevInstruction - given a pCode, find the next instruction  */
5647 /*                       in the linked list                        */
5648 /*-----------------------------------------------------------------*/
5649 pCode * pic16_findPrevInstruction(pCode *pci)
5650 {
5651   pCode *pc = pci;
5652
5653   while(pc) {
5654
5655     if((pc->type == PC_OPCODE)
5656         || (pc->type == PC_WILD)
5657         || (pc->type == PC_ASMDIR)
5658         )
5659       return pc;
5660       
5661
5662 #ifdef PCODE_DEBUG
5663     fprintf(stderr,"pic16_findPrevInstruction:  ");
5664     printpCode(stderr, pc);
5665 #endif
5666     pc = pc->prev;
5667   }
5668
5669   //fprintf(stderr,"Couldn't find instruction\n");
5670   return NULL;
5671 }
5672
5673 #undef PCODE_DEBUG
5674
5675 #if 0
5676 /*-----------------------------------------------------------------*/
5677 /* findFunctionEnd - given a pCode find the end of the function    */
5678 /*                   that contains it                              */
5679 /*-----------------------------------------------------------------*/
5680 static pCode * findFunctionEnd(pCode *pc)
5681 {
5682
5683   while(pc) {
5684     if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
5685       return pc;
5686
5687     pc = pc->next;
5688   }
5689
5690   fprintf(stderr,"Couldn't find function end\n");
5691   return NULL;
5692 }
5693 #endif
5694 #if 0
5695 /*-----------------------------------------------------------------*/
5696 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
5697 /*                instruction with which it is associated.         */
5698 /*-----------------------------------------------------------------*/
5699 static void AnalyzeLabel(pCode *pc)
5700 {
5701
5702   pic16_pCodeUnlink(pc);
5703
5704 }
5705 #endif
5706
5707 #if 0
5708 static void AnalyzeGOTO(pCode *pc)
5709 {
5710
5711   pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
5712
5713 }
5714
5715 static void AnalyzeSKIP(pCode *pc)
5716 {
5717
5718   pBranchLink(pc,pic16_findNextInstruction(pc->next));
5719   pBranchLink(pc,pic16_findNextInstruction(pc->next->next));
5720
5721 }
5722
5723 static void AnalyzeRETURN(pCode *pc)
5724 {
5725
5726   //  branch_link(pc,findFunctionEnd(pc->next));
5727
5728 }
5729
5730 #endif
5731
5732 /*-------------------------------------------------------------------*/
5733 /* pic16_getRegFrompCodeOp - extract the register from a pCodeOp     */
5734 /*                            if one is present. This is the common  */
5735 /*                            part of pic16_getRegFromInstruction(2) */
5736 /*-------------------------------------------------------------------*/
5737
5738 regs * pic16_getRegFrompCodeOp (pCodeOp *pcop) {
5739   if (!pcop) return NULL;
5740   
5741   switch(pcop->type) {
5742   case PO_PRODL:
5743   case PO_PRODH:
5744   case PO_INDF0:
5745   case PO_FSR0:
5746   case PO_W:
5747   case PO_WREG:
5748   case PO_STATUS:
5749   case PO_INTCON:
5750   case PO_PCL:
5751   case PO_PCLATH:
5752   case PO_PCLATU:
5753   case PO_BSR:
5754     return PCOR(pcop)->r;
5755
5756   case PO_SFR_REGISTER:
5757     //fprintf (stderr, "%s - SFR\n", __FUNCTION__);
5758     return PCOR(pcop)->r;
5759
5760   case PO_BIT:
5761   case PO_GPR_TEMP:
5762 //      fprintf(stderr, "pic16_getRegFromInstruction - bit or temp\n");
5763     return PCOR(pcop)->r;
5764
5765   case PO_IMMEDIATE:
5766 //    return pic16_dirregWithName(PCOI(pcop)->r->name);
5767
5768     if(PCOI(pcop)->r)
5769       return (PCOI(pcop)->r);
5770     else
5771       return NULL;
5772     
5773   case PO_GPR_BIT:
5774     return PCOR(pcop)->r;
5775
5776   case PO_GPR_REGISTER:
5777   case PO_DIR:
5778 //      fprintf(stderr, "pic16_getRegFromInstruction - dir\n");
5779     return PCOR(pcop)->r;
5780
5781   case PO_LITERAL:
5782     //fprintf(stderr, "pic16_getRegFromInstruction - literal\n");
5783     break;
5784
5785   case PO_REL_ADDR:
5786   case PO_LABEL:
5787     //fprintf (stderr, "%s - label or address: %d (%s)\n", __FUNCTION__, pcop->type, dumpPicOptype(pcop->type));
5788     break;
5789     
5790   case PO_CRY:
5791   case PO_STR:
5792     /* this should never turn up */
5793     //fprintf (stderr, "%s - unused pCodeOp->type: %d (%s)\n", __FUNCTION__, pcop->type, dumpPicOptype(pcop->type));
5794     break;
5795     
5796   case PO_WILD:
5797     break;
5798
5799   case PO_TWO_OPS:
5800     return pic16_getRegFrompCodeOp( PCOP2(pcop)->pcopL );
5801     break;
5802     
5803   default:
5804         fprintf(stderr, "pic16_getRegFrompCodeOp - unknown reg type %d (%s)\n",pcop->type, dumpPicOptype (pcop->type));
5805 //      assert( 0 );
5806         break;
5807   }
5808
5809   return NULL;
5810 }
5811
5812 /*-----------------------------------------------------------------*/
5813 /*-----------------------------------------------------------------*/
5814 regs * pic16_getRegFromInstruction(pCode *pc)
5815 {
5816   if(!pc                   || 
5817      !isPCI(pc)            ||
5818      !PCI(pc)->pcop        ||
5819      PCI(pc)->num_ops == 0 ||
5820      (PCI(pc)->num_ops == 1 && PCI(pc)->isFastCall))
5821     return NULL;
5822
5823 #if 0
5824   fprintf(stderr, "pic16_getRegFromInstruction - reg type %s (%d)\n",
5825         dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5826 #endif
5827
5828   return( pic16_getRegFrompCodeOp (PCI(pc)->pcop) );
5829 }
5830
5831 /*-------------------------------------------------------------------------------*/
5832 /* pic16_getRegFromInstruction2 - variant to support two memory operand commands */
5833 /*-------------------------------------------------------------------------------*/
5834 regs * pic16_getRegFromInstruction2(pCode *pc)
5835 {
5836
5837   if(!pc                   || 
5838      !isPCI(pc)            ||
5839      !PCI(pc)->pcop        ||
5840      PCI(pc)->num_ops == 0 ||
5841      (PCI(pc)->num_ops == 1))           // accept only 2 operand commands
5842     return NULL;
5843
5844   if (PCI(pc)->pcop->type != PO_TWO_OPS)
5845     return NULL;
5846
5847 #if 0
5848   fprintf(stderr, "pic16_getRegFromInstruction2 - reg type %s (%d)\n",
5849         dumpPicOptype( PCI(pc)->pcop->type), PCI(pc)->pcop->type);
5850 #endif
5851
5852   return pic16_getRegFrompCodeOp (PCOP2(PCI(pc)->pcop)->pcopR);
5853 }
5854
5855 /*-----------------------------------------------------------------*/
5856 /*-----------------------------------------------------------------*/
5857
5858 static void AnalyzepBlock(pBlock *pb)
5859 {
5860   pCode *pc;
5861
5862   if(!pb)
5863     return;
5864
5865   /* Find all of the registers used in this pBlock 
5866    * by looking at each instruction and examining it's
5867    * operands
5868    */
5869   for(pc = pb->pcHead; pc; pc = pc->next) {
5870
5871     /* Is this an instruction with operands? */
5872     if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
5873
5874       if(PCI(pc)->pcop->type == PO_GPR_TEMP) {
5875
5876         /* Loop through all of the registers declared so far in
5877            this block and see if we find this one there */
5878
5879         regs *r = setFirstItem(pb->tregisters);
5880
5881         while(r) {
5882           if(r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) {
5883             PCOR(PCI(pc)->pcop)->r = r;
5884             break;
5885           }
5886           r = setNextItem(pb->tregisters);
5887         }
5888
5889         if(!r) {
5890           /* register wasn't found */
5891           //r = Safe_calloc(1, sizeof(regs));
5892           //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
5893           //addSet(&pb->tregisters, r);
5894           addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
5895           //PCOR(PCI(pc)->pcop)->r = r;
5896           //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
5897         }/* else 
5898           fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
5899          */
5900       }
5901       if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
5902         if(PCOR(PCI(pc)->pcop)->r) {
5903           pic16_allocWithIdx(PCOR(PCI(pc)->pcop)->r->rIdx);                     /* FIXME! - VR */
5904           DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
5905         } else {
5906           if(PCI(pc)->pcop->name)
5907             fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
5908           else
5909             fprintf(stderr,"ERROR: NULL register\n");
5910         }
5911       }
5912     }
5913
5914
5915   }
5916 }
5917
5918 /*-----------------------------------------------------------------*/
5919 /* */
5920 /*-----------------------------------------------------------------*/
5921 #define PCI_HAS_LABEL(x) ((x) && (PCI(x)->label != NULL))
5922
5923 static void InsertpFlow(pCode *pc, pCode **pflow)
5924 {
5925   if(*pflow)
5926     PCFL(*pflow)->end = pc;
5927
5928   if(!pc || !pc->next)
5929     return;
5930
5931   *pflow = pic16_newpCodeFlow();
5932   pic16_pCodeInsertAfter(pc, *pflow);
5933 }
5934
5935 /*-----------------------------------------------------------------*/
5936 /* pic16_BuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
5937 /*                         the flow blocks.                        */
5938 /*
5939  * pic16_BuildFlow inserts pCodeFlow objects into the pCode chain at each
5940  * point the instruction flow changes. 
5941  */
5942 /*-----------------------------------------------------------------*/
5943 void pic16_BuildFlow(pBlock *pb)
5944 {
5945   pCode *pc;
5946   pCode *last_pci=NULL;
5947   pCode *pflow=NULL;
5948   int seq = 0;
5949
5950   if(!pb)
5951     return;
5952
5953   //fprintf (stderr,"build flow start seq %d  ",GpcFlowSeq);
5954   /* Insert a pCodeFlow object at the beginning of a pBlock */
5955
5956   InsertpFlow(pb->pcHead, &pflow);
5957
5958   //pflow = pic16_newpCodeFlow();    /* Create a new Flow object */
5959   //pflow->next = pb->pcHead;  /* Make the current head the next object */
5960   //pb->pcHead->prev = pflow;  /* let the current head point back to the flow object */
5961   //pb->pcHead = pflow;        /* Make the Flow object the head */
5962   //pflow->pb = pb;
5963
5964   for( pc = pic16_findNextInstruction(pb->pcHead);
5965        pc != NULL;
5966        pc=pic16_findNextInstruction(pc)) { 
5967
5968     pc->seq = seq++;
5969     PCI(pc)->pcflow = PCFL(pflow);
5970
5971     //fprintf(stderr," build: ");
5972     //pflow->print(stderr,pflow);
5973
5974     if (checkLabel(pc)) { 
5975
5976       /* This instruction marks the beginning of a
5977        * new flow segment */
5978
5979       pc->seq = 0;
5980       seq = 1;
5981
5982       /* If the previous pCode is not a flow object, then 
5983        * insert a new flow object. (This check prevents 
5984        * two consecutive flow objects from being insert in
5985        * the case where a skip instruction preceeds an
5986        * instruction containing a label.) */
5987
5988       if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
5989         InsertpFlow(pic16_findPrevInstruction(pc->prev), &pflow);
5990
5991       PCI(pc)->pcflow = PCFL(pflow);
5992       
5993     }
5994
5995     if( PCI(pc)->isSkip) {
5996
5997       /* The two instructions immediately following this one 
5998        * mark the beginning of a new flow segment */
5999
6000       while(pc && PCI(pc)->isSkip) {
6001
6002         PCI(pc)->pcflow = PCFL(pflow);
6003         pc->seq = seq-1;
6004         seq = 1;
6005
6006         InsertpFlow(pc, &pflow);
6007         pc=pic16_findNextInstruction(pc->next);
6008       }
6009
6010       seq = 0;
6011
6012       if(!pc)
6013         break;
6014
6015       PCI(pc)->pcflow = PCFL(pflow);
6016       pc->seq = 0;
6017       InsertpFlow(pc, &pflow);
6018
6019     } else if ( PCI(pc)->isBranch && !checkLabel(pic16_findNextInstruction(pc->next)))  {
6020
6021       InsertpFlow(pc, &pflow);
6022       seq = 0;
6023
6024     }
6025     last_pci = pc;
6026     pc = pc->next;
6027   }
6028
6029   //fprintf (stderr,",end seq %d",GpcFlowSeq);
6030   if(pflow)
6031     PCFL(pflow)->end = pb->pcTail;
6032 }
6033
6034 /*-------------------------------------------------------------------*/
6035 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
6036 /*                           the flow blocks.                        */
6037 /*
6038  * unBuildFlow removes pCodeFlow objects from a pCode chain
6039  */
6040 /*-----------------------------------------------------------------*/
6041 static void unBuildFlow(pBlock *pb)
6042 {
6043   pCode *pc,*pcnext;
6044
6045   if(!pb)
6046     return;
6047
6048   pc = pb->pcHead;
6049
6050   while(pc) {
6051     pcnext = pc->next;
6052
6053     if(isPCI(pc)) {
6054
6055       pc->seq = 0;
6056       if(PCI(pc)->pcflow) {
6057         //Safe_free(PCI(pc)->pcflow);
6058         PCI(pc)->pcflow = NULL;
6059       }
6060
6061     } else if(isPCFL(pc) )
6062       pc->destruct(pc);
6063
6064     pc = pcnext;
6065   }
6066
6067
6068 }
6069 #if 0
6070 /*-----------------------------------------------------------------*/
6071 /*-----------------------------------------------------------------*/
6072 static void dumpCond(int cond)
6073 {
6074
6075   static char *pcc_str[] = {
6076     //"PCC_NONE",
6077     "PCC_REGISTER",
6078     "PCC_C",
6079     "PCC_Z",
6080     "PCC_DC",
6081     "PCC_OV",
6082     "PCC_N",
6083     "PCC_W",
6084     "PCC_EXAMINE_PCOP",
6085     "PCC_LITERAL",
6086     "PCC_REL_ADDR"
6087   };
6088
6089   int ncond = sizeof(pcc_str) / sizeof(char *);
6090   int i,j;
6091
6092   fprintf(stderr, "0x%04X\n",cond);
6093
6094   for(i=0,j=1; i<ncond; i++, j<<=1)
6095     if(cond & j)
6096       fprintf(stderr, "  %s\n",pcc_str[i]);
6097
6098 }
6099 #endif
6100
6101 #if 0
6102 /*-----------------------------------------------------------------*/
6103 /*-----------------------------------------------------------------*/
6104 static void FlowStats(pCodeFlow *pcflow)
6105 {
6106
6107   pCode *pc;
6108
6109   if(!isPCFL(pcflow))
6110     return;
6111
6112   fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
6113
6114   pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE); 
6115
6116   if(!pc) {
6117     fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
6118     return;
6119   }
6120
6121
6122   fprintf(stderr, "  FlowStats inCond: ");
6123   dumpCond(pcflow->inCond);
6124   fprintf(stderr, "  FlowStats outCond: ");
6125   dumpCond(pcflow->outCond);
6126
6127 }
6128 #endif
6129 /*-----------------------------------------------------------------*
6130  * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
6131  *    if it affects the banking bits. 
6132  * 
6133  * return: -1 == Banking bits are unaffected by this pCode.
6134  *
6135  * return: > 0 == Banking bits are affected.
6136  *
6137  *  If the banking bits are affected, then the returned value describes
6138  * which bits are affected and how they're affected. The lower half
6139  * of the integer maps to the bits that are affected, the upper half
6140  * to whether they're set or cleared.
6141  *
6142  *-----------------------------------------------------------------*/
6143
6144 static int isBankInstruction(pCode *pc)
6145 {
6146   regs *reg;
6147   int bank = -1;
6148
6149   if(!isPCI(pc))
6150     return 0;
6151
6152   if( PCI(pc)->op == POC_MOVLB ||
6153       (( (reg = pic16_getRegFromInstruction(pc)) != NULL) && isBSR_REG(reg))) {
6154     bank = PCOL(pc)->lit;
6155   }
6156
6157   return 1;
6158 }
6159
6160
6161 /*-----------------------------------------------------------------*/
6162 /*-----------------------------------------------------------------*/
6163 static void FillFlow(pCodeFlow *pcflow)
6164 {
6165
6166   pCode *pc;
6167   int cur_bank;
6168
6169   if(!isPCFL(pcflow))
6170     return;
6171
6172   //  fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
6173
6174   pc = pic16_findNextpCode(PCODE(pcflow), PC_OPCODE); 
6175
6176   if(!pc) {
6177     //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
6178     return;
6179   }
6180
6181   cur_bank = -1;
6182
6183   do {
6184     isBankInstruction(pc);
6185     pc = pc->next;
6186   } while (pc && (pc != pcflow->end) && !isPCFL(pc));
6187
6188 /*
6189   if(!pc ) {
6190     fprintf(stderr, "  FillFlow - Bad end of flow\n");
6191   } else {
6192     fprintf(stderr, "  FillFlow - Ending flow with\n  ");
6193     pc->print(stderr,pc);
6194   }
6195
6196   fprintf(stderr, "  FillFlow inCond: ");
6197   dumpCond(pcflow->inCond);
6198   fprintf(stderr, "  FillFlow outCond: ");
6199   dumpCond(pcflow->outCond);
6200 */
6201 }
6202
6203 /*-----------------------------------------------------------------*/
6204 /*-----------------------------------------------------------------*/
6205 static void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
6206 {
6207   pCodeFlowLink *fromLink, *toLink;
6208
6209   if(!from || !to || !to->pcflow || !from->pcflow)
6210     return;
6211
6212   fromLink = pic16_newpCodeFlowLink(from->pcflow);
6213   toLink   = pic16_newpCodeFlowLink(to->pcflow);
6214
6215   addSetIfnotP(&(from->pcflow->to), toLink);   //to->pcflow);
6216   addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
6217
6218 }
6219
6220 pCode *pic16_getJumptabpCode (pCode *pc) {
6221   pCode *pcinf;
6222
6223   //fprintf (stderr, "%s - start for %p in %p", __FUNCTION__, pc, isPCI(pc) ? PCI(pc)->pcflow : NULL);
6224   //pc->print (stderr, pc);
6225   pcinf = pc;
6226   while (pcinf) {
6227     if (isPCI(pcinf) && PCI(pcinf)->op != POC_GOTO) return NULL;
6228     if (pcinf->type == PC_INFO && PCINF(pcinf)->type == INF_OPTIMIZATION) {
6229       switch (PCOO(PCINF(pcinf)->oper1)->type) {
6230       case OPT_JUMPTABLE_BEGIN:
6231         /* leading begin of jump table -- in one */
6232         pcinf = pic16_findPrevInstruction (pcinf);
6233         return pcinf;
6234         break;
6235         
6236       case OPT_JUMPTABLE_END:
6237         /* leading end of jumptable -- not in one */
6238         return NULL;
6239         break;
6240         
6241       default:
6242         /* ignore all other PCInfos */
6243         break;
6244       }
6245     }
6246     pcinf = pcinf->prev;
6247   }
6248
6249   /* no PCInfo found -- not in a jumptable */
6250   return NULL;
6251 }
6252
6253 /*-----------------------------------------------------------------*
6254  * void LinkFlow(pBlock *pb)
6255  *
6256  * In pic16_BuildFlow, the PIC code has been partitioned into contiguous
6257  * non-branching segments. In LinkFlow, we determine the execution
6258  * order of these segments. For example, if one of the segments ends
6259  * with a skip, then we know that there are two possible flow segments
6260  * to which control may be passed.
6261  *-----------------------------------------------------------------*/
6262 static void LinkFlow(pBlock *pb)
6263 {
6264   pCode *pc=NULL;
6265   pCode *pcflow;
6266   pCode *pct;
6267   pCode *jumptab_pre = NULL;
6268
6269   //fprintf(stderr,"linkflow \n");
6270
6271   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
6272        pcflow != NULL;
6273        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6274
6275     if(!isPCFL(pcflow))
6276       fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
6277
6278     //fprintf(stderr," link: ");
6279     //pcflow->print(stderr,pcflow);
6280
6281     //FillFlow(PCFL(pcflow));
6282
6283     pc = PCFL(pcflow)->end;
6284
6285     //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
6286     if(isPCI_SKIP(pc)) {
6287 //      fprintf(stderr, "ends with skip\n");
6288 //      pc->print(stderr,pc);
6289
6290       pct=pic16_findNextInstruction(pc->next);
6291       LinkFlow_pCode(PCI(pc),PCI(pct));
6292       pct=pic16_findNextInstruction(pct->next);
6293       LinkFlow_pCode(PCI(pc),PCI(pct));
6294       continue;
6295     }
6296
6297     if(isPCI_BRANCH(pc)) {
6298       pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6299
6300       /* handle GOTOs in jumptables */
6301       if ((jumptab_pre = pic16_getJumptabpCode (pc)) != NULL) {
6302         /* link to previous flow */
6303         //fprintf (stderr, "linked jumptable GOTO to predecessor %p\n", PCI(jumptab_pre)->pcflow);
6304         LinkFlow_pCode (PCI(jumptab_pre), PCI(pc));
6305       }
6306
6307       switch (PCI(pc)->op) {
6308       case POC_GOTO:
6309       case POC_BRA:
6310       case POC_RETURN:
6311       case POC_RETLW:
6312       case POC_RETFIE:
6313               /* unconditional branches -- do not link to next instruction */
6314               //fprintf (stderr, "%s: flow ended by unconditional branch\n", __FUNCTION__);
6315               break;
6316               
6317       case POC_CALL:
6318       case POC_RCALL:
6319               /* unconditional calls -- link to next instruction */
6320               //fprintf (stderr, "%s: flow ended by CALL\n", __FUNCTION__);
6321               LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6322               break;
6323               
6324       case POC_BC:
6325       case POC_BN:
6326       case POC_BNC:
6327       case POC_BNN:
6328       case POC_BNOV:
6329       case POC_BNZ:
6330       case POC_BOV:
6331       case POC_BZ:
6332               /* conditional branches -- also link to next instruction */
6333               //fprintf (stderr, "%s: flow ended by conditional branch\n", __FUNCTION__);
6334               LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6335               break;
6336               
6337       default:
6338               fprintf (stderr, "%s: unhandled op %u (%s)\n", __FUNCTION__, PCI(pc)->op , PCI(pc)->mnemonic);
6339               assert (0 && "unhandled branching instruction");
6340               break;
6341       }
6342
6343       //fprintf(stderr, "ends with branch\n  ");
6344       //pc->print(stderr,pc);
6345
6346       if(!(pcol && isPCOLAB(pcol))) {
6347         if((PCI(pc)->op != POC_RETLW)
6348                 && (PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL) && (PCI(pc)->op != POC_RCALL) && (PCI(pc)->op != POC_RETFIE) ) {
6349         
6350                 /* continue if label is '$' which assembler knows how to parse */
6351                 if(((PCI(pc)->pcop->type == PO_STR) && !strcmp(PCI(pc)->pcop->name, "$")))continue;
6352
6353                 if(pic16_pcode_verbose) {
6354                         pc->print(stderr,pc);
6355                         fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
6356                 }
6357         }
6358         continue;
6359       }
6360
6361       if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
6362         LinkFlow_pCode(PCI(pc),PCI(pct));
6363       else
6364         fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
6365                 __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
6366
6367 //      fprintf(stderr,"pic16_newpCodeOpLabel: key=%d, name=%s\n",pcol->key,(PCOP(pcol)->name)?(PCOP(pcol)->name):"<unknown>");
6368
6369       continue;
6370     }
6371
6372     if(isPCI(pc)) {
6373       //fprintf(stderr, "ends with non-branching instruction:\n");
6374       //pc->print(stderr,pc);
6375
6376       LinkFlow_pCode(PCI(pc),PCI(pic16_findNextInstruction(pc->next)));
6377
6378       continue;
6379     }
6380
6381     if(pc) {
6382       //fprintf(stderr, "ends with unknown\n");
6383       //pc->print(stderr,pc);
6384       continue;
6385     }
6386
6387     //fprintf(stderr, "ends with nothing: ERROR\n");
6388     
6389   }
6390 }
6391 /*-----------------------------------------------------------------*/
6392 /*-----------------------------------------------------------------*/
6393
6394 /*-----------------------------------------------------------------*/
6395 /*-----------------------------------------------------------------*/
6396 int pic16_isPCinFlow(pCode *pc, pCode *pcflow)
6397 {
6398
6399   if(!pc || !pcflow)
6400     return 0;
6401
6402   if((!isPCI(pc) && !isPCAD(pc)) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
6403     return 0;
6404
6405   if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
6406     return 1;
6407
6408   return 0;
6409 }
6410
6411
6412
6413
6414
6415 /*-----------------------------------------------------------------*/
6416 /* insertBankSwitch - inserts a bank switch statement in the       */
6417 /*                    assembly listing                             */
6418 /*                                                                 */
6419 /* position == 0: insert before                                    */
6420 /* position == 1: insert after pc                                  */
6421 /* position == 2: like 0 but previous was a skip instruction       */
6422 /*-----------------------------------------------------------------*/
6423 pCodeOp *pic16_popGetLabel(unsigned int key);
6424 extern int pic16_labelOffset;
6425
6426 static void insertBankSwitch(unsigned char position, pCode *pc)
6427 {
6428   pCode *new_pc;
6429
6430         if(!pc)
6431                 return;
6432
6433         /* emit BANKSEL [symbol] */
6434
6435
6436         new_pc = pic16_newpCodeAsmDir("BANKSEL", "%s", pic16_get_op_from_instruction(PCI(pc)));
6437         
6438 //      position = 0;           // position is always before (sanity check!)
6439
6440 #if 0
6441         fprintf(stderr, "%s:%d: inserting bank switch (pos: %d)\n", __FUNCTION__, __LINE__, position);
6442         pc->print(stderr, pc);
6443 #endif
6444
6445         switch(position) {
6446                 case 1: {
6447                         /* insert the bank switch after this pc instruction */
6448                         pCode *pcnext = pic16_findNextInstruction(pc);
6449
6450                                 pic16_pCodeInsertAfter(pc, new_pc);
6451                                 if(pcnext)pc = pcnext;
6452                 }; break;
6453                 
6454                 case 0:
6455                         /* insert the bank switch BEFORE this pc instruction */
6456                         pic16_pCodeInsertAfter(pc->prev, new_pc);
6457                         break;
6458
6459                 case 2: {
6460                           symbol *tlbl;
6461                           pCode *pcnext, *pcprev, *npci, *ppc;
6462                           PIC_OPCODE ipci;
6463                           int ofs1=0, ofs2=0, len=0;
6464                           
6465                         /* just like 0, but previous was a skip instruction,
6466                          * so some care should be taken */
6467                           
6468                                 pic16_labelOffset += 10000;
6469                                 tlbl = newiTempLabel(NULL);
6470                                 
6471                                 /* invert skip instruction */
6472                                 pcprev = pic16_findPrevInstruction(pc->prev);
6473                                 ipci = PCI(pcprev)->inverted_op;
6474                                 npci = pic16_newpCode(ipci, PCI(pcprev)->pcop);
6475
6476 //                              fprintf(stderr, "%s:%d old OP: %d\tnew OP: %d\n", __FILE__, __LINE__, PCI(pcprev)->op, ipci);
6477
6478                                 /* copy info from old pCode */
6479                                 ofs1 = ofs2 = sizeof( pCode ) + sizeof(PIC_OPCODE);
6480                                 len = sizeof(pCodeInstruction) - ofs1 - sizeof( char const * const *);
6481                                 ofs1 += strlen( PCI(pcprev)->mnemonic) + 1;
6482                                 ofs2 += strlen( PCI(npci)->mnemonic) + 1;
6483                                 memcpy(&PCI(npci)->from, &PCI(pcprev)->from, (char *)(&(PCI(npci)->pci_magic)) - (char *)(&(PCI(npci)->from)));
6484                                 PCI(npci)->op = PCI(pcprev)->inverted_op;
6485                                 
6486                                 /* unlink old pCode */
6487                                 ppc = pcprev->prev;
6488                                 ppc->next = pcprev->next;
6489                                 pcprev->next->prev = ppc;
6490                                 pic16_pCodeInsertAfter(ppc, npci);
6491                                 
6492                                 /* extra instructions to handle invertion */
6493                                 pcnext = pic16_newpCode(POC_BRA, pic16_popGetLabel(tlbl->key));
6494                                 pic16_pCodeInsertAfter(npci, pcnext);
6495                                 pic16_pCodeInsertAfter(pc->prev, new_pc);
6496                                 
6497                                 pcnext = pic16_newpCodeLabel(NULL,tlbl->key+100+pic16_labelOffset);
6498                                 pic16_pCodeInsertAfter(pc, pcnext);
6499                         }; break;
6500         }
6501         
6502
6503         /* Move the label, if there is one */
6504         if(PCI(pc)->label) {
6505 //              fprintf(stderr, "%s:%d: moving label due to bank switch directive src= 0x%p dst= 0x%p\n",
6506 //                      __FILE__, __LINE__, pc, new_pc);
6507                 PCAD(new_pc)->pci.label = PCI(pc)->label;
6508                 PCI(pc)->label = NULL;
6509         }
6510 }
6511
6512
6513 /*-----------------------------------------------------------------*/
6514 /*int compareBankFlow - compare the banking requirements between   */
6515 /*  flow objects. */
6516 /*-----------------------------------------------------------------*/
6517 static int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom)
6518 {
6519
6520   if(!pcflow || !pcflowLink || !pcflowLink->pcflow)
6521     return 0;
6522
6523   if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow))
6524     return 0;
6525
6526   if(pcflow->firstBank == -1)
6527     return 0;
6528
6529
6530   if(pcflowLink->pcflow->firstBank == -1) {
6531     pCodeFlowLink *pctl = setFirstItem( toORfrom ? 
6532                                         pcflowLink->pcflow->to : 
6533                                         pcflowLink->pcflow->from);
6534     return compareBankFlow(pcflow, pctl, toORfrom);
6535   }
6536
6537   if(toORfrom) {
6538     if(pcflow->lastBank == pcflowLink->pcflow->firstBank)
6539       return 0;
6540
6541     pcflowLink->bank_conflict++;
6542     pcflowLink->pcflow->FromConflicts++;
6543     pcflow->ToConflicts++;
6544   } else {
6545     
6546     if(pcflow->firstBank == pcflowLink->pcflow->lastBank)
6547       return 0;
6548
6549     pcflowLink->bank_conflict++;
6550     pcflowLink->pcflow->ToConflicts++;
6551     pcflow->FromConflicts++;
6552
6553   }
6554   /*
6555   fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n",
6556           pcflowLink->pcflow->pc.seq,
6557           pcflowLink->pcflow->FromConflicts,
6558           pcflowLink->pcflow->ToConflicts);
6559   */
6560   return 1;
6561
6562 }
6563
6564 #if 0
6565 /*-----------------------------------------------------------------*/
6566 /*-----------------------------------------------------------------*/
6567 static void DumpFlow(pBlock *pb)
6568 {
6569   pCode *pc=NULL;
6570   pCode *pcflow;
6571   pCodeFlowLink *pcfl;
6572
6573
6574   fprintf(stderr,"Dump flow \n");
6575   pb->pcHead->print(stderr, pb->pcHead);
6576
6577   pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW);
6578   pcflow->print(stderr,pcflow);
6579
6580   for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
6581        pcflow != NULL;
6582        pcflow = pic16_findNextpCode(pcflow->next, PC_FLOW) ) {
6583
6584     if(!isPCFL(pcflow)) {
6585       fprintf(stderr, "DumpFlow - pcflow is not a flow object ");
6586       continue;
6587     }
6588     fprintf(stderr,"dumping: ");
6589     pcflow->print(stderr,pcflow);
6590     FlowStats(PCFL(pcflow));
6591
6592     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6593
6594       pc = PCODE(pcfl->pcflow);
6595
6596       fprintf(stderr, "    from seq %d:\n",pc->seq);
6597       if(!isPCFL(pc)) {
6598         fprintf(stderr,"oops dumpflow - from is not a pcflow\n");
6599         pc->print(stderr,pc);
6600       }
6601
6602     }
6603
6604     for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) {
6605
6606       pc = PCODE(pcfl->pcflow);
6607
6608       fprintf(stderr, "    to seq %d:\n",pc->seq);
6609       if(!isPCFL(pc)) {
6610         fprintf(stderr,"oops dumpflow - to is not a pcflow\n");
6611         pc->print(stderr,pc);
6612       }
6613
6614     }
6615
6616   }
6617
6618 }
6619 #endif
6620 /*-----------------------------------------------------------------*/
6621 /*-----------------------------------------------------------------*/
6622 static int OptimizepBlock(pBlock *pb)
6623 {
6624   pCode *pc, *pcprev;
6625   int matches =0;
6626
6627   if(!pb || !peepOptimizing)
6628     return 0;
6629
6630   DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
6631 /*
6632   for(pc = pb->pcHead; pc; pc = pc->next)
6633     matches += pic16_pCodePeepMatchRule(pc);
6634 */
6635
6636   pc = pic16_findNextInstruction(pb->pcHead);
6637   if(!pc)
6638     return 0;
6639
6640   pcprev = pc->prev;
6641   do {
6642
6643
6644     if(pic16_pCodePeepMatchRule(pc)) {
6645
6646       matches++;
6647
6648       if(pcprev)
6649         pc = pic16_findNextInstruction(pcprev->next);
6650       else 
6651         pc = pic16_findNextInstruction(pb->pcHead);
6652     } else
6653       pc = pic16_findNextInstruction(pc->next);
6654   } while(pc);
6655
6656   if(matches)
6657     DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
6658   return matches;
6659
6660 }
6661
6662 /*-----------------------------------------------------------------*/
6663 /*-----------------------------------------------------------------*/
6664 static pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
6665 {
6666   pCode *pc;
6667
6668   for(pc = pcs; pc; pc = pc->next) {
6669
6670     if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) && 
6671        (PCI(pc)->pcop) && 
6672        (PCI(pc)->pcop->type == PO_LABEL) &&
6673        (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
6674       return pc;
6675   }
6676  
6677
6678   return NULL;
6679 }
6680
6681 /*-----------------------------------------------------------------*/
6682 /*-----------------------------------------------------------------*/
6683 static void exchangeLabels(pCodeLabel *pcl, pCode *pc)
6684 {
6685
6686   char *s=NULL;
6687
6688   if(isPCI(pc) && 
6689      (PCI(pc)->pcop) && 
6690      (PCI(pc)->pcop->type == PO_LABEL)) {
6691
6692     pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
6693
6694 //      fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
6695 //    if(pcol->pcop.name)
6696 //      Safe_free(pcol->pcop.name);
6697
6698     /* If the key is negative, then we (probably) have a label to
6699      * a function and the name is already defined */
6700        
6701     if(pcl->key>0)
6702       sprintf(s=buffer,"_%05d_DS_",pcl->key);
6703     else 
6704       s = pcl->label;
6705
6706     //sprintf(buffer,"_%05d_DS_",pcl->key);
6707     if(!s) {
6708       fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
6709     }
6710     pcol->pcop.name = Safe_strdup(s);
6711     pcol->key = pcl->key;
6712     //pc->print(stderr,pc);
6713
6714   }
6715
6716
6717 }
6718
6719 /*-----------------------------------------------------------------*/
6720 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
6721 /*                            pCode chain if they're not used.     */
6722 /*-----------------------------------------------------------------*/
6723 static void pBlockRemoveUnusedLabels(pBlock *pb)
6724 {
6725   pCode *pc; pCodeLabel *pcl;
6726
6727   if(!pb)
6728     return;
6729
6730   for(pc = pb->pcHead; (pc=pic16_findNextInstruction(pc->next)) != NULL; ) {
6731
6732     pBranch *pbr = PCI(pc)->label;
6733     if(pbr && pbr->next) {
6734       pCode *pcd = pb->pcHead;
6735
6736 //      fprintf(stderr, "multiple labels\n");
6737 //      pc->print(stderr,pc);
6738
6739       pbr = pbr->next;
6740       while(pbr) {
6741
6742         while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
6743           //fprintf(stderr,"Used by:\n");
6744           //pcd->print(stderr,pcd);
6745
6746           exchangeLabels(PCL(pbr->pc),pcd);
6747
6748           pcd = pcd->next;
6749         }
6750         pbr = pbr->next;
6751       }
6752     }
6753   }
6754
6755   for(pc = pb->pcHead; pc; pc = pc->next) {
6756
6757     if(isPCL(pc)) // pc->type == PC_LABEL)
6758       pcl = PCL(pc);
6759     else if (isPCI(pc) && PCI(pc)->label) //((pc->type == PC_OPCODE) && PCI(pc)->label)
6760       pcl = PCL(PCI(pc)->label->pc);
6761     else continue;
6762
6763 //      fprintf(stderr," found  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6764
6765     /* This pCode is a label, so search the pBlock to see if anyone
6766      * refers to it */
6767
6768     if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))
6769         && (!pcl->force)) {
6770     //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
6771       /* Couldn't find an instruction that refers to this label
6772        * So, unlink the pCode label from it's pCode chain
6773        * and destroy the label */
6774 //      fprintf(stderr," removed  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
6775
6776       DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
6777       if(pc->type == PC_LABEL) {
6778         pic16_unlinkpCode(pc);
6779         pCodeLabelDestruct(pc);
6780       } else {
6781         unlinkpCodeFromBranch(pc, PCODE(pcl));
6782         /*if(pc->label->next == NULL && pc->label->pc == NULL) {
6783           Safe_free(pc->label);
6784         }*/
6785       }
6786
6787     }
6788   }
6789
6790 }
6791
6792
6793 /*-----------------------------------------------------------------*/
6794 /* pic16_pBlockMergeLabels - remove the pCode labels from the pCode      */
6795 /*                     chain and put them into pBranches that are  */
6796 /*                     associated with the appropriate pCode       */
6797 /*                     instructions.                               */
6798 /*-----------------------------------------------------------------*/
6799 void pic16_pBlockMergeLabels(pBlock *pb)
6800 {
6801   pBranch *pbr;
6802   pCode *pc, *pcnext=NULL;
6803
6804   if(!pb)
6805     return;
6806
6807   /* First, Try to remove any unused labels */
6808   //pBlockRemoveUnusedLabels(pb);
6809
6810   /* Now loop through the pBlock and merge the labels with the opcodes */
6811
6812   pc = pb->pcHead;
6813   //  for(pc = pb->pcHead; pc; pc = pc->next) {
6814
6815   while(pc) {
6816     pCode *pcn = pc->next;
6817
6818     if(pc->type == PC_LABEL) {
6819
6820 //      fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
6821 //      fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
6822
6823       if((pcnext = pic16_findNextInstruction(pc) )) {
6824
6825 //              pcnext->print(stderr, pcnext);
6826
6827         // Unlink the pCode label from it's pCode chain
6828         pic16_unlinkpCode(pc);
6829         
6830 //      fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
6831         // And link it into the instruction's pBranch labels. (Note, since
6832         // it's possible to have multiple labels associated with one instruction
6833         // we must provide a means to accomodate the additional labels. Thus
6834         // the labels are placed into the singly-linked list "label" as 
6835         // opposed to being a single member of the pCodeInstruction.)
6836
6837         //_ALLOC(pbr,sizeof(pBranch));
6838 #if 1
6839         pbr = Safe_calloc(1,sizeof(pBranch));
6840         pbr->pc = pc;
6841         pbr->next = NULL;
6842
6843         PCI(pcnext)->label = pic16_pBranchAppend(PCI(pcnext)->label,pbr);
6844 #endif
6845       } else {
6846         if(pic16_pcode_verbose)
6847         fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
6848       }
6849     } else if(pc->type == PC_CSOURCE) {
6850
6851       /* merge the source line symbolic info into the next instruction */
6852       if((pcnext = pic16_findNextInstruction(pc) )) {
6853
6854         // Unlink the pCode label from it's pCode chain
6855         pic16_unlinkpCode(pc);
6856         PCI(pcnext)->cline = PCCS(pc);
6857         //fprintf(stderr, "merging CSRC\n");
6858         //genericPrint(stderr,pcnext);
6859       }
6860
6861     }
6862     pc = pcn;
6863   }
6864   pBlockRemoveUnusedLabels(pb);
6865
6866 }
6867
6868 /*-----------------------------------------------------------------*/
6869 /*-----------------------------------------------------------------*/
6870 static int OptimizepCode(char dbName)
6871 {
6872 #define MAX_PASSES 4
6873
6874   int matches = 0;
6875   int passes = 0;
6876   pBlock *pb;
6877
6878   if(!the_pFile)
6879     return 0;
6880
6881   DFPRINTF((stderr," Optimizing pCode\n"));
6882
6883   do {
6884     matches = 0;
6885     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
6886       if('*' == dbName || getpBlock_dbName(pb) == dbName)
6887         matches += OptimizepBlock(pb);
6888     }
6889   }
6890   while(matches && ++passes < MAX_PASSES);
6891
6892   return matches;
6893 }
6894
6895
6896
6897 const char *pic16_pCodeOpType(pCodeOp *pcop);
6898 const char *pic16_pCodeOpSubType(pCodeOp *pcop);
6899
6900
6901 /*-----------------------------------------------------------------*/
6902 /* pic16_popCopyGPR2Bit - copy a pcode operator                          */
6903 /*-----------------------------------------------------------------*/
6904
6905 pCodeOp *pic16_popCopyGPR2Bit(pCodeOp *pc, int bitval)
6906 {
6907   pCodeOp *pcop=NULL;
6908
6909 //  fprintf(stderr, "%s:%d pc type: %s\tname: %s\n", __FILE__, __LINE__, pic16_pCodeOpType(pc), pc->name);
6910
6911   if(pc->name) {
6912         pcop = pic16_newpCodeOpBit(pc->name, bitval, 0, pc->type);
6913   } else {
6914     if(PCOR(pc)->r)pcop = pic16_newpCodeOpBit(PCOR(pc)->r->name, bitval, 0, pc->type);
6915   }
6916
6917   assert(pcop != NULL);
6918
6919   if( !( (pcop->type == PO_LABEL) ||
6920          (pcop->type == PO_LITERAL) ||
6921          (pcop->type == PO_STR) ))
6922     PCOR(pcop)->r = PCOR(pc)->r;  /* This is dangerous... */
6923     PCOR(pcop)->r->wasUsed = 1;
6924     PCOR(pcop)->instance = PCOR(pc)->instance;
6925
6926   return pcop;
6927 }
6928
6929
6930 /*----------------------------------------------------------------------*
6931  * pic16_areRegsSame - check to see if the names of two registers match *
6932  *----------------------------------------------------------------------*/
6933 int pic16_areRegsSame(regs *r1, regs *r2)
6934 {
6935         if(!strcmp(r1->name, r2->name))return 1;
6936
6937   return 0;
6938 }
6939
6940
6941 /*-----------------------------------------------------------------*/
6942 /*-----------------------------------------------------------------*/
6943 static void pic16_FixRegisterBanking(pBlock *pb)
6944 {
6945   pCode *pc=NULL;
6946   pCode *pcprev=NULL;
6947   regs *reg, *prevreg;
6948   unsigned char flag=0;
6949   
6950         if(!pb)
6951                 return;
6952
6953         pc = pic16_findNextpCode(pb->pcHead, PC_OPCODE);
6954         if(!pc)return;
6955
6956         /* loop through all of the flow blocks with in one pblock */
6957
6958 //      fprintf(stderr,"%s:%d: Register banking\n", __FUNCTION__, __LINE__);
6959
6960         prevreg = NULL;
6961         do {
6962                 /* at this point, pc should point to a PC_FLOW object */
6963                 /* for each flow block, determine the register banking 
6964                  * requirements */
6965
6966                 
6967                 /* if label, then might come from other point, force banksel */
6968                 if(isPCL(pc))prevreg = NULL;
6969                 
6970                 if(!isPCI(pc))goto loop;
6971
6972                 if(PCI(pc)->label)prevreg = NULL;
6973
6974                 if(PCI(pc)->is2MemOp)goto loop;
6975
6976                 /* if goto, then force banksel */
6977 //              if(PCI(pc)->op == POC_GOTO)prevreg = NULL;
6978        
6979                 reg = pic16_getRegFromInstruction(pc);
6980
6981 #if 0
6982                 pc->print(stderr, pc);
6983                 fprintf(stderr, "reg = %p\n", reg);
6984
6985                 if(reg) {
6986                         fprintf(stderr, "%s:%d:  %s  %d\n",__FUNCTION__, __LINE__, reg->name, reg->rIdx);
6987                         fprintf(stderr, "addr = 0x%03x, bit=%d\tfix=%d\n",
6988                                 reg->address,reg->isBitField, reg->isFixed);
6989                 }
6990 #endif
6991
6992                 /* now make some tests to make sure that instruction needs bank switch */
6993
6994                 /* if no register exists, and if not a bit opcode goto loop */
6995                 if(!reg) {
6996                         if(!(PCI(pc)->pcop && PCI(pc)->pcop->type == PO_GPR_BIT))goto loop;
6997                 }
6998                  
6999                 if(isPCI_SKIP(pc)) {
7000 //                      fprintf(stderr, "instruction is SKIP instruction\n");
7001 //                prevreg = NULL;
7002                 }
7003                 if(reg && isACCESS_BANK(reg))goto loop;
7004
7005                 if(!isBankInstruction(pc))goto loop;
7006
7007                 if(isPCI_LIT(pc))goto loop;
7008          
7009                 if(PCI(pc)->op == POC_CALL)goto loop;
7010
7011                 /* Examine the instruction before this one to make sure it is
7012                  * not a skip type instruction */
7013                 pcprev = findPrevpCode(pc->prev, PC_OPCODE);
7014
7015                 flag = 0;               /* add before this instruction */
7016                 
7017                 /* if previous instruction is a skip one, then set flag
7018                  * to 2 and call insertBankSwitch */
7019                 if(pcprev && isPCI_SKIP(pcprev)) {
7020                   flag=2;       //goto loop
7021 //                prevreg = NULL;
7022                 }
7023                  
7024                 if(pic16_options.opt_banksel>0) {
7025                   char op1[128], op2[128];
7026                   
7027                     if(prevreg) {
7028                       strcpy(op1, pic16_get_op_from_instruction(PCI(pc)));
7029                       strcpy(op2, pic16_get_op_from_instruction(PCI(pcprev)));
7030                       if(!strcmp(op1, op2))goto loop;
7031                     }
7032                 }
7033                 prevreg = reg;
7034                 insertBankSwitch(flag, pc);
7035
7036 //              fprintf(stderr, "BANK SWITCH inserted\n");
7037                 
7038 loop:
7039                 pcprev = pc;
7040                 pc = pc->next;
7041         } while (pc);
7042 }
7043
7044 /** ADDITIONS BY RAPHAEL NEIDER, 2004-11-16: GOTO OPTIMIZATIONS **/
7045
7046 /* Returns the (maximum of the) number of bytes used by the specified pCode. */
7047 int instrSize (pCode *pc)
7048 {
7049   if (!pc) return 0;
7050
7051   if (isPCAD(pc)) {
7052     if (!PCAD(pc)->directive || strlen (PCAD(pc)->directive) < 3) return 0;
7053     return 4; // assumes only regular instructions using <= 4 bytes
7054   }
7055
7056   if (isPCI(pc)) return PCI(pc)->isize;
7057
7058   return 0;
7059 }
7060
7061 /* Returns 1 if pc is referenced by the given label (either
7062  * pc is the label itself or is an instruction with an attached
7063  * label).
7064  * Returns 0 if pc is not preceeded by the specified label.
7065  */
7066 int isLabel (pCode *pc, char *label)
7067 {
7068   if (!pc) return 0;
7069
7070   // label attached to the pCode?  
7071   if (isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO) {
7072     pBranch *lab = NULL;
7073     lab = PCI(pc)->label;
7074
7075     while (lab) {
7076       if (isPCL(lab->pc) && strcmp(PCL(lab->pc)->label, label) == 0) {
7077         return 1;
7078       }
7079       lab = lab->next;
7080     } // while
7081   } // if
7082
7083   // is inline assembly label?
7084   if (isPCAD(pc) && PCAD(pc)->directive == NULL && PCAD(pc)->arg) {
7085     // do not compare trailing ':'
7086     if (strncmp (PCAD(pc)->arg, label, strlen (label)) == 0) {
7087       return 1;
7088     }
7089   } // if
7090   
7091   // is pCodeLabel?
7092   if (isPCL(pc)) {
7093       if (strcmp(PCL(pc)->label,label) == 0) {
7094       return 1;
7095     }
7096   } // if
7097   
7098   // no label/no label attached/wrong label(s)
7099   return 0;
7100 }
7101
7102 /* Returns the distance to the given label in terms of words.
7103  * Labels are searched only within -max .. max words from pc.
7104  * Returns max if the label could not be found or
7105  * its distance from pc in (-max..+max).
7106  */
7107 int findpCodeLabel (pCode *pc, char *label, int max, pCode **target) {
7108   int dist = instrSize(pc);
7109   pCode *curr = pc;
7110
7111   // search backwards
7112   while (dist < max && curr && !isLabel (curr, label)) {
7113     curr = curr->prev;
7114     dist += instrSize(curr); // sizeof (instruction)
7115   } // while
7116   if (curr && dist < max) {
7117     if (target != NULL) *target = curr;
7118     return -dist;
7119   }
7120
7121   dist = 0;
7122   curr = pic16_findNextInstruction (pc->next);
7123   //search forwards
7124   while (dist < max && curr && !isLabel (curr, label)) {
7125     dist += instrSize(curr); // sizeof (instruction)
7126     curr = curr->next;
7127   } // while
7128   if (curr && dist < max) {
7129     if (target != NULL) *target = curr;
7130     return dist;
7131   }
7132
7133   if (target != NULL) *target = NULL;
7134   return max;
7135 }
7136
7137 /* Returns -1 if pc does NOT denote an instruction like
7138  * BTFS[SC] STATUS,i
7139  * Otherwise we return 
7140  *   (a) 0x10 + i for BTFSS
7141  *   (b) 0x00 + i for BTFSC
7142  */
7143 int isSkipOnStatus (pCode *pc)
7144 {
7145   int res = -1;
7146   pCodeOp *pcop;
7147   if (!pc || !isPCI(pc)) return -1;
7148   if (PCI(pc)->op == POC_BTFSS) res = 0x10;
7149   else if (PCI(pc)->op == POC_BTFSC) res = 0x00;
7150   else return -1;
7151
7152   pcop = PCI(pc)->pcop;
7153
7154   if (pcop->type == PO_STATUS || (pcop->type == PO_GPR_BIT && strcmp(pcop->name, "STATUS") == 0)) {
7155     return res + ((pCodeOpRegBit *)pcop)->bit;
7156   }
7157
7158   return -1;
7159 }
7160
7161 /* Returns 1 if pc is one of BC, BZ, BOV, BN, BNC, BNZ, BNOV or BNN,
7162  * returns 0 otherwise. */
7163 int isConditionalBranch (pCode *pc)
7164 {
7165   if (!pc || !isPCI_BRANCH(pc)) return 0;
7166
7167   switch (PCI(pc)->op) {
7168   case POC_BC:
7169   case POC_BZ:
7170   case POC_BOV:
7171   case POC_BN:
7172   case POC_BNC:
7173   case POC_BNZ:
7174   case POC_BNOV:
7175   case POC_BNN:
7176     return 1;
7177
7178   default:
7179     break;
7180   } // switch
7181
7182   return 0;
7183 }
7184
7185 /* Returns 1 if pc has a label attached to it.
7186  * This can be either a label stored in the pCode itself (.label)
7187  * or a label making up its own pCode preceding this pc.
7188  * Returns 0 if pc cannot be reached directly via a label.
7189  */
7190 int hasNoLabel (pCode *pc)
7191 {
7192   pCode *prev;
7193   if (!pc) return 1;
7194
7195   // are there any label pCodes between pc and the previous instruction?
7196   prev = pic16_findPrevInstruction (pc->prev);
7197   while (pc && pc != prev) {
7198     // pCode with attached label?
7199     if ((isPCI(pc) || isPCAD(pc) || isPCW(pc) || pc->type == PC_INFO)
7200         && PCI(pc)->label) {
7201       return 0;
7202     }
7203     // is inline assembly label?
7204     if (isPCAD(pc) && PCAD(pc)->directive == NULL) return 0;
7205     if (isPCW(pc) && PCW(pc)->label) return 0;
7206
7207     // pCodeLabel?
7208     if (isPCL(pc)) return 0;
7209
7210     pc = pc->prev;
7211   } // if
7212
7213   // no label found
7214   return 1;
7215 }
7216
7217 static void pic16_InsertCommentAfter (pCode *pc, const char *fmt, ...) {
7218   char buf[512];
7219   va_list va;
7220
7221   va_start (va, fmt);
7222   vsprintf (buf, fmt, va);
7223   va_end (va);
7224
7225   pic16_pCodeInsertAfter (pc, pic16_newpCodeCharP(buf));
7226 }
7227
7228 /* Replaces the old pCode with the new one, moving the labels,
7229  * C source line and probably flow information to the new pCode.
7230  */
7231 void pic16_pCodeReplace (pCode *oldPC, pCode *newPC) {
7232   if (!oldPC || !newPC || !isPCI(oldPC) || !isPCI(newPC))
7233     return;
7234
7235   /* first move all labels from old to new */
7236   PCI(newPC)->label = pic16_pBranchAppend (PCI(oldPC)->label, PCI(newPC)->label);
7237   PCI(oldPC)->label = NULL;
7238   
7239 #if 0
7240   /* move C source line (if possible) */
7241   if (PCI(oldPC)->cline && !PCI(newPC)->cline)
7242     PCI(newPC)->cline = PCI(oldPC)->cline;
7243 #endif
7244
7245   /* keep flow information intact */
7246   newPC->seq = oldPC->seq;
7247   PCI(newPC)->pcflow = PCI(oldPC)->pcflow;
7248   if (PCI(newPC)->pcflow && PCI(newPC)->pcflow->end == oldPC) {
7249     PCI(newPC)->pcflow->end = newPC;
7250   }
7251
7252   /* insert a comment stating which pCode has been replaced */
7253 #if 1
7254   if (pic16_pcode_verbose || pic16_debug_verbose) {
7255     char pc_str[256];
7256     pic16_pCode2str (pc_str, 256, oldPC);
7257     pic16_InsertCommentAfter (oldPC->prev, "%s: replaced %s", __FUNCTION__, pc_str);
7258   }
7259 #endif
7260   
7261   /* insert new pCode into pBlock */
7262   pic16_pCodeInsertAfter (oldPC, newPC);
7263   pic16_unlinkpCode (oldPC);
7264   
7265   /* destruct replaced pCode */
7266   oldPC->destruct (oldPC);
7267 }
7268
7269 /* Returns the inverted conditional branch (if any) or NULL.
7270  * pcop must be set to the new jump target.
7271  */
7272 pCode *getNegatedBcc (pCode *bcc, pCodeOp *pcop)
7273 {
7274   pCode *newBcc;
7275
7276   if (!bcc || !isPCI(bcc)) return NULL;
7277
7278   switch (PCI(bcc)->op) {
7279   case POC_BC:   newBcc = pic16_newpCode (POC_BNC , pcop); break;
7280   case POC_BZ:   newBcc = pic16_newpCode (POC_BNZ , pcop); break;
7281   case POC_BOV:  newBcc = pic16_newpCode (POC_BNOV, pcop); break;
7282   case POC_BN:   newBcc = pic16_newpCode (POC_BNN , pcop); break;
7283   case POC_BNC:  newBcc = pic16_newpCode (POC_BC  , pcop); break;
7284   case POC_BNZ:  newBcc = pic16_newpCode (POC_BZ  , pcop); break;
7285   case POC_BNOV: newBcc = pic16_newpCode (POC_BOV , pcop); break;
7286   case POC_BNN:  newBcc = pic16_newpCode (POC_BN  , pcop); break;
7287   default:
7288     newBcc = NULL;
7289   }
7290   return newBcc;
7291 }
7292
7293 #define MAX_DIST_GOTO         0x7FFFFFFF
7294 #define MAX_DIST_BRA                1020        // maximum offset (in bytes) possible with BRA
7295 #define MAX_DIST_BCC                 120        // maximum offset (in bytes) possible with Bcc
7296 #define MAX_JUMPCHAIN_DEPTH           16        // number of GOTOs to follow in resolveJumpChain() (to prevent endless loops)
7297 #define IS_GOTO(arg) ((arg) && isPCI(arg) && (PCI(arg)->op == POC_GOTO || PCI(arg)->op == POC_BRA))
7298
7299 /* Follows GOTO/BRA instructions to their target instructions, stores the
7300  * final destination (not a GOTO or BRA instruction) in target and returns
7301  * the distance from the original pc to *target.
7302  */
7303 int resolveJumpChain (pCode *pc, pCode **target, pCodeOp **pcop) {
7304         pCode *curr = pc;
7305         pCode *last = NULL;
7306         pCodeOp *lastPCOP = NULL;
7307         int dist = 0;
7308         int depth = 0;
7309
7310         //fprintf (stderr, "%s:%d: -=-", __FUNCTION__, __LINE__);
7311
7312         /* only follow unconditional branches, except for the initial pCode (which may be a conditional branch) */
7313         while (curr && (last != curr) && (depth++ < MAX_JUMPCHAIN_DEPTH) && isPCI(curr)
7314                         && (PCI(curr)->op == POC_GOTO || PCI(curr)->op == POC_BRA || (curr == pc && isConditionalBranch(curr)))) {
7315                 last = curr;
7316                 lastPCOP = PCI(curr)->pcop;
7317                 dist = findpCodeLabel (pc, PCI(curr)->pcop->name, MAX_DIST_GOTO, &curr);
7318                 //fprintf (stderr, "last:%p, curr:%p, label:%s\n", last, curr, PCI(last)->pcop->name);
7319         } // while
7320
7321         if (target) *target = last;
7322         if (pcop) *pcop = lastPCOP;
7323         return dist;
7324 }
7325
7326 /* Returns pc if it is not a OPT_JUMPTABLE_BEGIN INFO pCode.
7327  * Otherwise the first pCode after the jumptable (after
7328  * the OPT_JUMPTABLE_END tag) is returned.
7329  */
7330 pCode *skipJumptables (pCode *pc, int *isJumptable)
7331 {
7332   *isJumptable = 0;
7333   if (!pc) return NULL;
7334   
7335   while (pc->type == PC_INFO && PCINF(pc)->type == INF_OPTIMIZATION && PCOO(PCINF(pc)->oper1)->type == OPT_JUMPTABLE_BEGIN) {
7336     *isJumptable = 1;
7337     //fprintf (stderr, "SKIPPING jumptable\n");
7338     do {
7339       //pc->print(stderr, pc);
7340       pc = pc->next;
7341     } while (pc && (pc->type != PC_INFO || PCINF(pc)->type != INF_OPTIMIZATION
7342                     || PCOO(PCINF(pc)->oper1)->type != OPT_JUMPTABLE_END));
7343     //fprintf (stderr, "<<JUMPTAB:\n");
7344     // skip OPT_END as well
7345     if (pc) pc = pc->next;
7346   } // while
7347
7348   return pc;
7349 }
7350
7351 pCode *pic16_findNextInstructionSkipJumptables (pCode *pc, int *isJumptable)
7352 {
7353   int isJumptab;
7354   *isJumptable = 0;
7355   while (pc && !isPCI(pc) && !isPCAD(pc) && !isPCW(pc)) {
7356     // set pc to the first pCode after a jumptable, leave pc untouched otherwise
7357     pc = skipJumptables (pc, &isJumptab);
7358     if (isJumptab) {
7359         // pc is the first pCode after the jumptable
7360         *isJumptable = 1;
7361     } else {
7362         // pc has not been changed by skipJumptables()
7363         pc = pc->next;
7364     }
7365   } // while
7366   
7367   return pc;
7368 }
7369
7370 /* Turn GOTOs into BRAs if distance between GOTO and label
7371  * is less than 1024 bytes.
7372  *
7373  * This method is especially useful if GOTOs after BTFS[SC]
7374  * can be turned into BRAs as GOTO would cost another NOP
7375  * if skipped.
7376  */
7377 void pic16_OptimizeJumps ()
7378 {
7379   pCode *pc;
7380   pCode *pc_prev = NULL;
7381   pCode *pc_next = NULL;
7382   pBlock *pb;
7383   pCode *target;
7384   int change, iteration, isJumptab;
7385   int isHandled = 0;
7386   char *label;
7387   int opt=0, toofar=0, opt_cond = 0, cond_toofar=0, opt_reorder = 0, opt_gotonext = 0, opt_gotochain = 0;
7388   
7389   if (!the_pFile) return;
7390   
7391   //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__);
7392   
7393   for (pb = the_pFile->pbHead; pb != NULL; pb = pb->next) {
7394     int matchedInvertRule = 1;
7395     iteration = 1;
7396     do {
7397       //fprintf (stderr, "%s:%d: iterating over pBlock %p\n", __FUNCTION__, __LINE__, pb);
7398       change = 0;
7399       pc = pic16_findNextInstruction (pb->pcHead);
7400     
7401       while (pc) {
7402         pc_next = pic16_findNextInstructionSkipJumptables (pc->next, &isJumptab);
7403         if (isJumptab) {
7404                 // skip jumptable, i.e. start over with no pc_prev!     
7405                 pc_prev = NULL;
7406                 pc = pc_next;
7407                 continue;
7408         } // if
7409
7410         /* (1) resolve chained jumps
7411          * Do not perform this until pattern (4) is no longer present! Otherwise we will
7412          * (a) leave dead code in and
7413          * (b) skip over the dead code with an (unneccessary) jump.
7414          */
7415         if (!matchedInvertRule && (IS_GOTO(pc) || isConditionalBranch(pc))) {
7416           pCodeOp *lastTargetOp = NULL;
7417           int newDist = resolveJumpChain (pc, &target, &lastTargetOp);
7418           int maxDist = MAX_DIST_BCC;
7419           if (PCI(pc)->op == POC_BRA) maxDist = MAX_DIST_BRA;
7420           if (PCI(pc)->op == POC_GOTO) maxDist = MAX_DIST_GOTO;
7421           
7422           /* be careful NOT to make the jump instruction longer (might break previously shortened jumps!) */
7423           if (lastTargetOp && newDist <= maxDist && lastTargetOp != PCI(pc)->pcop
7424               && strcmp (lastTargetOp->name, PCI(pc)->pcop->name) != 0) {
7425             //fprintf (stderr, "(1) ");pc->print(stderr, pc); fprintf (stderr, " --> %s\n", lastTargetOp->name);
7426             if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(1) jump chain resolved")); }
7427             PCI(pc)->pcop->name = lastTargetOp->name;
7428             change++;
7429             opt_gotochain++;
7430           } // if
7431         } // if
7432
7433
7434         if (IS_GOTO(pc)) {
7435           int dist;
7436           int condBraType = isSkipOnStatus(pc_prev);
7437           label = PCI(pc)->pcop->name;
7438           dist = findpCodeLabel(pc, label, MAX_DIST_BRA, &target);
7439           if (dist < 0) dist = -dist;
7440           //fprintf (stderr, "distance: %d (", dist); pc->print(stderr, pc);fprintf (stderr, ")\n");
7441           isHandled = 0;
7442           
7443           
7444           /* (2) remove "GOTO label; label:" */
7445           if (isLabel (pc_next, label)) {
7446             //fprintf (stderr, "(2) GOTO next instruction: ");pc->print(stderr, pc);fprintf (stderr, " --> ");pc_next->print(stderr, pc_next); fprintf(stderr, "\n");
7447             // first remove all preceeding SKIP instructions
7448             while (pc_prev && isPCI_SKIP(pc_prev)) {
7449               // attach labels on this instruction to pc_next
7450               //fprintf (stderr, "(2) preceeding SKIP removed: ");pc_prev->print(stderr, pc_prev);fprintf(stderr, "\n");
7451               PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc_prev)->label, PCI(pc_next)->label);
7452               PCI(pc_prev)->label = NULL;
7453               if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("(2) SKIP removed")); }
7454               pic16_unlinkpCode (pc_prev);
7455               pc_prev = pic16_findPrevInstruction (pc);
7456             } // while
7457             // now remove the redundant goto itself
7458             PCI(pc_next)->label = pic16_pBranchAppend (PCI(pc)->label, PCI(pc_next)->label);
7459             if (pic16_pcode_verbose) { pic16_pCodeInsertAfter (pc, pic16_newpCodeCharP("(2) GOTO next instruction removed")); }
7460             pic16_unlinkpCode (pc);
7461             pc = pic16_findPrevInstruction(pc_next->prev);
7462             isHandled = 1; // do not perform further optimizations
7463             opt_gotonext++;
7464             change++;
7465           } // if
7466           
7467           
7468           /* (3) turn BTFSx STATUS,i; GOTO label into Bcc label if possible */
7469           if (!isHandled && condBraType != -1 && hasNoLabel(pc)) {
7470             if (dist < MAX_DIST_BCC) {
7471               pCode *bcc = NULL;
7472               switch (condBraType) {
7473               case 0x00: bcc = pic16_newpCode (POC_BC, PCI(pc)->pcop);break;
7474                 // no BDC on DIGIT CARRY available
7475               case 0x02: bcc = pic16_newpCode (POC_BZ, PCI(pc)->pcop);break;
7476               case 0x03: bcc = pic16_newpCode (POC_BOV, PCI(pc)->pcop);break;
7477               case 0x04: bcc = pic16_newpCode (POC_BN, PCI(pc)->pcop);break;
7478               case 0x10: bcc = pic16_newpCode (POC_BNC, PCI(pc)->pcop);break;
7479                 // no BNDC on DIGIT CARRY available
7480               case 0x12: bcc = pic16_newpCode (POC_BNZ, PCI(pc)->pcop);break;
7481               case 0x13: bcc = pic16_newpCode (POC_BNOV, PCI(pc)->pcop);break;
7482               case 0x14: bcc = pic16_newpCode (POC_BNN, PCI(pc)->pcop);break;
7483               default:
7484                 // no replacement possible
7485                 bcc = NULL;
7486                 break;
7487               } // switch
7488               if (bcc) {
7489                 // ATTENTION: keep labels attached to BTFSx!
7490                 // HINT: GOTO is label free (checked above)
7491                 //fprintf (stderr, "%s:%d: (3) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(bcc)->mnemonic, label);
7492                 isHandled = 1; // do not perform further optimizations
7493                 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(3) conditional branch introduced")); }
7494                 pic16_pCodeReplace (pc_prev, bcc);
7495                 pc->destruct(pc);
7496                 pc = bcc;
7497                 opt_cond++;
7498                 change++;
7499               } // if
7500             } else {
7501               //fprintf (stderr, "(%d, too far for Bcc)\n", dist);
7502               cond_toofar++;
7503             } // if
7504           } // if
7505
7506           if (!isHandled) {
7507             // (4) eliminate the following (common) tripel:
7508             //           <pred.>;
7509             //  labels1: Bcc label2;
7510             //           GOTO somewhere;    ; <-- instruction referenced by pc
7511             //  label2:  <cont.>
7512             // and replace it by
7513             //  labels1: B#(cc) somewhere;  ; #(cc) is the negated condition cc
7514             //  label2:  <cont.>
7515             // ATTENTION: all labels pointing to "Bcc label2" must be attached
7516             //            to <cont.> instead
7517             // ATTENTION: This optimization is only valid if <pred.> is
7518             //            not a skip operation!
7519             // ATTENTION: somewhere must be within MAX_DIST_BCC bytes!
7520             // ATTENTION: no label may be attached to the GOTO instruction!
7521             if (isConditionalBranch(pc_prev)
7522                 && (!isPCI_SKIP(pic16_findPrevInstruction(pc_prev->prev)))
7523                 && (dist < MAX_DIST_BCC)
7524                 && isLabel(pc_next,PCI(pc_prev)->pcop->name)
7525                 && hasNoLabel(pc)) {
7526               pCode *newBcc = getNegatedBcc (pc_prev, PCI(pc)->pcop);
7527             
7528               if (newBcc) {
7529                 //fprintf (stderr, "%s:%d: (4) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBcc)->mnemonic, label);
7530                 isHandled = 1; // do not perform further optimizations
7531                 if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc_prev->prev, pic16_newpCodeCharP("(4) conditional skipping branch inverted")); }
7532                 pic16_pCodeReplace (pc_prev, newBcc);
7533                 pc->destruct(pc);
7534                 pc = newBcc;
7535                 opt_reorder++;
7536                 change++;
7537                 matchedInvertRule++;
7538               }
7539             }
7540           }
7541           
7542           /* (5) now just turn GOTO into BRA */ 
7543           if (!isHandled && (PCI(pc)->op == POC_GOTO)) {
7544             if (dist < MAX_DIST_BRA) {
7545               pCode *newBra = pic16_newpCode (POC_BRA, PCI(pc)->pcop);
7546               //fprintf (stderr, "%s:%d: (5) turning %s %s into %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, label, PCI(newBra)->mnemonic, label);
7547               if (pic16_pcode_verbose) { pic16_pCodeInsertAfter(pc->prev, pic16_newpCodeCharP("(5) GOTO replaced by BRA")); }
7548               pic16_pCodeReplace (pc, newBra);
7549               pc = newBra;
7550               opt++;
7551               change++;
7552             } else {
7553               //fprintf (stderr, "(%d, too far for BRA)\n", dist);
7554               toofar++;
7555             }
7556           } // if (!isHandled)
7557         } // if
7558
7559         pc_prev = pc;
7560         pc = pc_next;
7561       } // while (pc)
7562       
7563       pBlockRemoveUnusedLabels (pb);
7564       
7565       // This line enables goto chain resolution!
7566       if (matchedInvertRule > 1) matchedInvertRule = 1; else matchedInvertRule = 0;
7567
7568       iteration++;
7569     } while (change); /* fixpoint iteration per pBlock */
7570   } // for (pb)
7571   
7572   // emit some statistics concerning goto-optimization
7573 #if 0
7574   if (pic16_debug_verbose || pic16_pcode_verbose) {
7575     fprintf (stderr, "optimize-goto:\n"
7576              "\t%5d GOTO->BRA; (%d GOTOs too far)\n"
7577              "\t%5d BTFSx, GOTO->Bcc (%d too far)\n"
7578              "\t%5d conditional \"skipping\" jumps inverted\n"
7579              "\t%5d GOTOs to next instruction removed\n"
7580              "\t%5d chained GOTOs resolved\n",
7581              opt, toofar, opt_cond, cond_toofar, opt_reorder, opt_gotonext, opt_gotochain);
7582   } // if
7583 #endif
7584   //fprintf (stderr, "%s:%d: %s\n", __FILE__, __LINE__, __FUNCTION__);
7585 }
7586
7587 #undef IS_GOTO
7588 #undef MAX_JUMPCHAIN_DEPTH
7589 #undef MAX_DIST_GOTO
7590 #undef MAX_DIST_BRA
7591 #undef MAX_DIST_BCC
7592
7593 /** END OF RAPHAEL NEIDER'S ADDITIONS **/
7594
7595 static void pBlockDestruct(pBlock *pb)
7596 {
7597
7598   if(!pb)
7599     return;
7600
7601
7602 //  Safe_free(pb);
7603
7604 }
7605
7606 /*-----------------------------------------------------------------*/
7607 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
7608 /*                                  name dbName and combine them   */
7609 /*                                  into one block                 */
7610 /*-----------------------------------------------------------------*/
7611 static void mergepBlocks(char dbName)
7612 {
7613
7614   pBlock *pb, *pbmerged = NULL,*pbn;
7615
7616   pb = the_pFile->pbHead;
7617
7618   //fprintf(stderr," merging blocks named %c\n",dbName);
7619   while(pb) {
7620
7621     pbn = pb->next;
7622     //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
7623     if( getpBlock_dbName(pb) == dbName) {
7624
7625       //fprintf(stderr," merged block %c\n",dbName);
7626
7627       if(!pbmerged) {
7628         pbmerged = pb;
7629       } else {
7630         pic16_addpCode2pBlock(pbmerged, pb->pcHead);
7631         /* pic16_addpCode2pBlock doesn't handle the tail: */
7632         pbmerged->pcTail = pb->pcTail;
7633
7634         pb->prev->next = pbn;
7635         if(pbn) 
7636           pbn->prev = pb->prev;
7637
7638
7639         pBlockDestruct(pb);
7640       }
7641       //pic16_printpBlock(stderr, pbmerged);
7642     } 
7643     pb = pbn;
7644   }
7645
7646 }
7647
7648 /*-----------------------------------------------------------------*/
7649 /* AnalyzeFlow - Examine the flow of the code and optimize         */
7650 /*                                                                 */
7651 /* level 0 == minimal optimization                                 */
7652 /*   optimize registers that are used only by two instructions     */
7653 /* level 1 == maximal optimization                                 */
7654 /*   optimize by looking at pairs of instructions that use the     */
7655 /*   register.                                                     */
7656 /*-----------------------------------------------------------------*/
7657
7658 static void AnalyzeFlow(int level)
7659 {
7660   static int times_called=0;
7661   pBlock *pb;
7662
7663     if(!the_pFile) {
7664       /* remove unused allocated registers before exiting */
7665       pic16_RemoveUnusedRegisters();
7666       return;
7667     }
7668
7669
7670     /* if this is not the first time this function has been called,
7671      * then clean up old flow information */
7672     if(times_called++) {
7673       for(pb = the_pFile->pbHead; pb; pb = pb->next)
7674         unBuildFlow(pb);
7675         pic16_RegsUnMapLiveRanges();
7676     }
7677     GpcFlowSeq = 1;
7678
7679     /* Phase 2 - Flow Analysis - Register Banking
7680      *
7681      * In this phase, the individual flow blocks are examined
7682      * and register banking is fixed.
7683      */
7684
7685 #if 0
7686     for(pb = the_pFile->pbHead; pb; pb = pb->next)
7687       pic16_FixRegisterBanking(pb);
7688 #endif
7689
7690     /* Phase 2 - Flow Analysis
7691      *
7692      * In this phase, the pCode is partition into pCodeFlow 
7693      * blocks. The flow blocks mark the points where a continuous
7694      * stream of instructions changes flow (e.g. because of
7695      * a call or goto or whatever).
7696      */
7697
7698     for(pb = the_pFile->pbHead; pb; pb = pb->next)
7699       pic16_BuildFlow(pb);
7700
7701
7702     /* Phase 2 - Flow Analysis - linking flow blocks
7703      *
7704      * In this phase, the individual flow blocks are examined
7705      * to determine their order of excution.
7706      */
7707
7708     for(pb = the_pFile->pbHead; pb; pb = pb->next)
7709       LinkFlow(pb);
7710
7711 #if 1
7712         if (pic16_options.opt_flags & OF_OPTIMIZE_DF) {
7713                 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7714                         pic16_createDF (pb);
7715 #if defined (DUMP_DF_GRAPHS) && DUMP_DF_GRAPHS > 0
7716                         pic16_vcg_dump_default (pb);
7717 #endif
7718                         //pic16_destructDF (pb);
7719                 }
7720
7721                 pic16_df_stats ();
7722                 if (0) releaseStack (); // releasing is costly...
7723         }
7724 #endif
7725
7726     /* Phase 3 - Flow Analysis - Flow Tree
7727      *
7728      * In this phase, the individual flow blocks are examined
7729      * to determine their order of execution.
7730      */
7731
7732     for(pb = the_pFile->pbHead; pb; pb = pb->next)
7733       pic16_BuildFlowTree(pb);
7734
7735
7736     /* Phase x - Flow Analysis - Used Banks
7737      *
7738      * In this phase, the individual flow blocks are examined
7739      * to determine the Register Banks they use
7740      */
7741
7742 #if 0
7743     for(pb = the_pFile->pbHead; pb; pb = pb->next)
7744       FixBankFlow(pb);
7745 #endif
7746
7747
7748     for(pb = the_pFile->pbHead; pb; pb = pb->next)
7749       pic16_pCodeRegMapLiveRanges(pb);
7750
7751     pic16_RemoveUnusedRegisters();
7752     pic16_removeUnusedRegistersDF ();
7753
7754   //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
7755     pic16_pCodeRegOptimizeRegUsage(level);
7756
7757
7758 #if 0
7759     if(!options.nopeep)
7760       OptimizepCode('*');
7761 #endif
7762
7763 #if 0
7764     for(pb = the_pFile->pbHead; pb; pb = pb->next)
7765       DumpFlow(pb);
7766 #endif
7767
7768     /* debug stuff */ 
7769     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7770       pCode *pcflow;
7771       
7772         for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
7773           (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7774           pcflow = pcflow->next) {
7775             FillFlow(PCFL(pcflow));
7776         }
7777     }
7778
7779 #if 0
7780     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7781       pCode *pcflow;
7782
7783         for( pcflow = pic16_findNextpCode(pb->pcHead, PC_FLOW); 
7784           (pcflow = pic16_findNextpCode(pcflow, PC_FLOW)) != NULL;
7785           pcflow = pcflow->next) {
7786             FlowStats(PCFL(pcflow));
7787         }
7788     }
7789 #endif
7790 }
7791
7792 /* VR -- no need to analyze banking in flow, but left here :
7793  *      1. because it may be used in the future for other purposes
7794  *      2. because if omitted we'll miss some optimization done here
7795  *
7796  * Perhaps I should rename it to something else
7797  */
7798
7799 /*-----------------------------------------------------------------*/
7800 /* pic16_AnalyzeBanking - Called after the memory addresses have been    */
7801 /*                  assigned to the registers.                     */
7802 /*                                                                 */
7803 /*-----------------------------------------------------------------*/
7804
7805 void pic16_AnalyzeBanking(void)
7806 {
7807   pBlock  *pb;
7808
7809     /* Phase x - Flow Analysis - Used Banks
7810      *
7811      * In this phase, the individual flow blocks are examined
7812      * to determine the Register Banks they use
7813      */
7814
7815     AnalyzeFlow(0);
7816     AnalyzeFlow(1);
7817
7818     if(!options.nopeep)
7819       OptimizepCode('*');
7820
7821
7822     if(!the_pFile)return;
7823
7824     if(!pic16_options.no_banksel) {
7825       for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7826 //        fprintf(stderr, "%s:%d: Fix register banking in pb= 0x%p\n", __FILE__, __LINE__, pb);
7827         pic16_FixRegisterBanking(pb);
7828       }
7829     }
7830 }
7831
7832 /*-----------------------------------------------------------------*/
7833 /* buildCallTree - Look at the flow and extract all of the calls.  */
7834 /*-----------------------------------------------------------------*/
7835 static set *register_usage(pBlock *pb);
7836
7837 static void buildCallTree(void    )
7838 {
7839   pBranch *pbr;
7840   pBlock  *pb;
7841   pCode   *pc;
7842   regs *r;
7843   
7844   if(!the_pFile)
7845     return;
7846
7847
7848
7849   /* Now build the call tree.
7850      First we examine all of the pCodes for functions.
7851      Keep in mind that the function boundaries coincide
7852      with pBlock boundaries. 
7853
7854      The algorithm goes something like this:
7855      We have two nested loops. The outer loop iterates
7856      through all of the pBlocks/functions. The inner
7857      loop iterates through all of the pCodes for
7858      a given pBlock. When we begin iterating through
7859      a pBlock, the variable pc_fstart, pCode of the start
7860      of a function, is cleared. We then search for pCodes
7861      of type PC_FUNCTION. When one is encountered, we
7862      initialize pc_fstart to this and at the same time
7863      associate a new pBranch object that signifies a 
7864      branch entry. If a return is found, then this signifies
7865      a function exit point. We'll link the pCodes of these
7866      returns to the matching pc_fstart.
7867
7868      When we're done, a doubly linked list of pBranches
7869      will exist. The head of this list is stored in
7870      `the_pFile', which is the meta structure for all
7871      of the pCode. Look at the pic16_printCallTree function
7872      on how the pBranches are linked together.
7873
7874    */
7875   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7876     pCode *pc_fstart=NULL;
7877     for(pc = pb->pcHead; pc; pc = pc->next) {
7878
7879         if(isPCI(pc) && pc_fstart) {
7880                 if(PCI(pc)->is2MemOp) {
7881                         r = pic16_getRegFromInstruction2(pc);
7882                         if(r && !strcmp(r->name, "POSTDEC1"))
7883                                 PCF(pc_fstart)->stackusage++;
7884                 } else {
7885                         r = pic16_getRegFromInstruction(pc);
7886                         if(r && !strcmp(r->name, "PREINC1"))
7887                                 PCF(pc_fstart)->stackusage--;
7888                 }
7889         }
7890
7891       if(isPCF(pc)) {
7892         if (PCF(pc)->fname) {
7893         char buf[16];
7894
7895           sprintf(buf, "%smain", port->fun_prefix);
7896           if(STRCASECMP(PCF(pc)->fname, buf) == 0) {
7897             //fprintf(stderr," found main \n");
7898             pb->cmemmap = NULL;  /* FIXME do we need to free ? */
7899             pb->dbName = 'M';
7900           }
7901
7902           pbr = Safe_calloc(1,sizeof(pBranch));
7903           pbr->pc = pc_fstart = pc;
7904           pbr->next = NULL;
7905
7906           the_pFile->functions = pic16_pBranchAppend(the_pFile->functions,pbr);
7907
7908           // Here's a better way of doing the same:
7909           addSet(&pb->function_entries, pc);
7910
7911         } else {
7912           // Found an exit point in a function, e.g. return
7913           // (Note, there may be more than one return per function)
7914           if(pc_fstart)
7915             pBranchLink(PCF(pc_fstart), PCF(pc));
7916
7917           addSet(&pb->function_exits, pc);
7918         }
7919       } else if(isCALL(pc)) {
7920         addSet(&pb->function_calls,pc);
7921       }
7922     }
7923   }
7924
7925
7926 #if 0
7927   /* This is not needed because currently all register used
7928    * by a function are stored in stack -- VR */
7929    
7930   /* Re-allocate the registers so that there are no collisions
7931    * between local variables when one function call another */
7932
7933   // this is weird...
7934   //  pic16_deallocateAllRegs();
7935
7936   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7937     if(!pb->visited)
7938       register_usage(pb);
7939   }
7940 #endif
7941
7942 }
7943
7944 /*-----------------------------------------------------------------*/
7945 /* pic16_AnalyzepCode - parse the pCode that has been generated and form */
7946 /*                all of the logical connections.                  */
7947 /*                                                                 */
7948 /* Essentially what's done here is that the pCode flow is          */
7949 /* determined.                                                     */
7950 /*-----------------------------------------------------------------*/
7951
7952 void pic16_AnalyzepCode(char dbName)
7953 {
7954   pBlock *pb;
7955   int i,changes;
7956
7957   if(!the_pFile)
7958     return;
7959
7960   mergepBlocks('D');
7961
7962
7963   /* Phase 1 - Register allocation and peep hole optimization
7964    *
7965    * The first part of the analysis is to determine the registers
7966    * that are used in the pCode. Once that is done, the peep rules
7967    * are applied to the code. We continue to loop until no more
7968    * peep rule optimizations are found (or until we exceed the
7969    * MAX_PASSES threshold). 
7970    *
7971    * When done, the required registers will be determined.
7972    *
7973    */
7974   i = 0;
7975   do {
7976
7977     DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
7978     //fprintf(stderr," Analyzing pCode: PASS #%d\n",i+1);
7979
7980     /* First, merge the labels with the instructions */
7981     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
7982       if('*' == dbName || getpBlock_dbName(pb) == dbName) {
7983
7984         DFPRINTF((stderr," analyze and merging block %c\n",dbName));
7985         //fprintf(stderr," analyze and merging block %c\n",dbName);
7986         pic16_pBlockMergeLabels(pb);
7987         AnalyzepBlock(pb);
7988       } else {
7989         DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
7990       }
7991     }
7992
7993         if(!options.nopeep)
7994                 changes = OptimizepCode(dbName);
7995         else changes = 0;
7996
7997   } while(changes && (i++ < MAX_PASSES));
7998
7999   
8000   buildCallTree();
8001 }
8002
8003
8004 /* convert a series of movff's of local regs to stack, with a single call to
8005  * a support functions which does the same thing via loop */
8006 static void pic16_convertLocalRegs2Support(pCode *pcstart, pCode *pcend, int count, regs *r, int entry)
8007 {
8008   pBranch *pbr;
8009   pCode *pc, *pct;
8010   char *fname[]={"__lr_store", "__lr_restore"};
8011
8012 //    pc = pic16_newpCode(POC_CALL, pic16_popGetFromString( (entry?fname[0]:fname[1]) ));
8013
8014     pct = pic16_findNextInstruction(pcstart->next);
8015     do {
8016       pc = pct;
8017       pct = pc->next;   //pic16_findNextInstruction(pc->next);
8018 //      pc->print(stderr, pc);
8019       if(isPCI(pc) && PCI(pc)->label) {
8020         pbr = PCI(pc)->label;
8021         while(pbr && pbr->pc) {
8022           PCI(pcstart)->label = pic16_pBranchAppend(PCI(pcstart)->label, pbr);
8023           pbr = pbr->next;
8024         }
8025
8026 //        pc->print(stderr, pc);
8027         /* unlink pCode */
8028         pc->prev->next = pct;
8029         pct->prev = pc->prev;
8030 //        pc->next = NULL;
8031 //        pc->prev = NULL;
8032       }
8033     } while ((pc) && (pc != pcend));
8034
8035     /* unlink movff instructions */
8036     pcstart->next = pcend;
8037     pcend->prev = pcstart;
8038
8039     pc = pcstart;
8040 //    if(!entry) {
8041 //      pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
8042 //              pic16_popCopyReg(&pic16_pc_fsr0l), pic16_popCopyReg(pic16_framepnt_lo)))); pc = pct;
8043 //    }
8044                 
8045     pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_LFSR, pic16_popGetLit2(0, pic16_popGetWithString(r->name)))); pc = pct;
8046     pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_MOVLW, pic16_popGetLit( count ))); pc = pct;
8047     pic16_pCodeInsertAfter(pc, pct=pic16_newpCode(POC_CALL, pic16_popGetWithString( fname[ (entry==1?0:1) ] ))); pc = pct;
8048
8049 //    if(!entry) {
8050 //      pic16_pCodeInsertAfter(pc, pct = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
8051 //              pic16_popCopyReg(pic16_framepnt_lo), pic16_popCopyReg(&pic16_pc_fsr0l)))); pc = pct;
8052 //    }
8053
8054     
8055     {
8056       symbol *sym;
8057
8058         sym = newSymbol( fname[ entry?0:1 ], 0 );
8059         strcpy(sym->rname, fname[ entry?0:1 ]);
8060         checkAddSym(&externs, sym);
8061         
8062 //        fprintf(stderr, "%s:%d adding extern symbol %s in externs\n", __FILE__, __LINE__, fname[ entry?0:1 ]);
8063     }
8064
8065 }
8066
8067 /*-----------------------------------------------------------------*/
8068 /* OptimizeLocalRegs - turn sequence of MOVFF instructions for     */
8069 /*    local registers to a support function call                   */
8070 /*-----------------------------------------------------------------*/
8071 void pic16_OptimizeLocalRegs(void)
8072 {
8073   pBlock  *pb;
8074   pCode   *pc;
8075   pCodeInfo *pci;
8076   pCodeOpLocalReg *pclr;
8077   int regCount=0;
8078   int inRegCount=0;
8079   regs *r, *lastr=NULL, *firstr=NULL;
8080   pCode *pcstart=NULL, *pcend=NULL;
8081   int inEntry=0;
8082   char *curFunc=NULL;
8083
8084         /* Overview:
8085          *   local_regs begin mark
8086          *      MOVFF r0x01, POSTDEC1
8087          *      MOVFF r0x02, POSTDEC1
8088          *      ...
8089          *      ...
8090          *      MOVFF r0x0n, POSTDEC1
8091          *   local_regs end mark
8092          *
8093          * convert the above to the below:
8094          *      MOVLW   starting_register_index
8095          *      MOVWF   PRODL
8096          *      MOVLW   register_count
8097          *      call    __save_registers_in_stack
8098          */
8099
8100     if(!the_pFile)
8101       return;
8102
8103     for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8104       inRegCount = regCount = 0;
8105       firstr = lastr = NULL;
8106       for(pc = pb->pcHead; pc; pc = pc->next) {
8107
8108         /* hold current function name */
8109         if(pc && isPCF(pc))curFunc = PCF(pc)->fname;
8110         
8111         if(pc && (pc->type == PC_INFO)) {
8112           pci = PCINF(pc);
8113
8114           if(pci->type == INF_LOCALREGS) {
8115             pclr = PCOLR(pci->oper1);
8116             
8117             if((pclr->type == LR_ENTRY_BEGIN)
8118               || (pclr->type == LR_ENTRY_END))inEntry = 1;
8119             else inEntry = 0;
8120             
8121             switch(pclr->type) {
8122               case LR_ENTRY_BEGIN:
8123               case LR_EXIT_BEGIN:
8124                         inRegCount = 1; regCount = 0;
8125                         pcstart = pc;   //pic16_findNextInstruction(pc->next);
8126                         firstr = lastr = NULL;
8127                         break;
8128               
8129               case LR_ENTRY_END:
8130               case LR_EXIT_END:
8131                         inRegCount = -1;
8132                         pcend = pc;     //pic16_findPrevInstruction(pc->prev);
8133
8134 #if 1
8135                         if(curFunc && inWparamList(curFunc+1)) {
8136                           fprintf(stderr, "sdcc: %s: warning: disabling lr-support for functionn %s\n",
8137                                         filename, curFunc);
8138                         } else {
8139                           if(regCount>2) {
8140                             pic16_convertLocalRegs2Support(pcstart, pcend, regCount,
8141                               firstr, inEntry);
8142                           }
8143                         }
8144 #endif
8145                         firstr = lastr = NULL;
8146                         break;
8147             }
8148             
8149             if(inRegCount == -1) {
8150 //              fprintf(stderr, "%s:%d registers used [%s] %d\n", __FILE__, __LINE__, inEntry?"entry":"exit", regCount);
8151               regCount = 0;
8152               inRegCount = 0;
8153             }
8154           }
8155         } else {
8156           if(isPCI(pc) && (PCI(pc)->op == POC_MOVFF) && (inRegCount == 1)) {
8157             if(inEntry)
8158               r = pic16_getRegFromInstruction(pc);
8159             else
8160               r = pic16_getRegFromInstruction2(pc);
8161             if(r && (r->type == REG_GPR) && (r->pc_type == PO_GPR_TEMP)) {
8162               if(!firstr)firstr = r;
8163               regCount++;
8164 //              fprintf(stderr, "%s:%d\t%s\t%i\t%d/%d\n", __FILE__, __LINE__, r->name, r->rIdx);
8165             }
8166           }
8167         }
8168       }
8169     }
8170 }
8171               
8172             
8173
8174
8175
8176 /*-----------------------------------------------------------------*/
8177 /* ispCodeFunction - returns true if *pc is the pCode of a         */
8178 /*                   function                                      */
8179 /*-----------------------------------------------------------------*/
8180 static bool ispCodeFunction(pCode *pc)
8181 {
8182
8183   if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
8184     return 1;
8185
8186   return 0;
8187 }
8188
8189 /*-----------------------------------------------------------------*/
8190 /* findFunction - Search for a function by name (given the name)   */
8191 /*                in the set of all functions that are in a pBlock */
8192 /* (note - I expect this to change because I'm planning to limit   */
8193 /*  pBlock's to just one function declaration                      */
8194 /*-----------------------------------------------------------------*/
8195 static pCode *findFunction(char *fname)
8196 {
8197   pBlock *pb;
8198   pCode *pc;
8199   if(!fname)
8200     return NULL;
8201
8202   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8203
8204     pc = setFirstItem(pb->function_entries);
8205     while(pc) {
8206     
8207       if((pc->type == PC_FUNCTION) &&
8208          (PCF(pc)->fname) && 
8209          (strcmp(fname, PCF(pc)->fname)==0))
8210         return pc;
8211
8212       pc = setNextItem(pb->function_entries);
8213
8214     }
8215
8216   }
8217   return NULL;
8218 }
8219
8220 static void MarkUsedRegisters(set *regset)
8221 {
8222
8223   regs *r1,*r2;
8224
8225   for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
8226 //      fprintf(stderr, "marking register = %s\t", r1->name);
8227     r2 = pic16_regWithIdx(r1->rIdx);
8228 //      fprintf(stderr, "to register = %s\n", r2->name);
8229     r2->isFree = 0;
8230     r2->wasUsed = 1;
8231   }
8232 }
8233
8234 static void pBlockStats(FILE *of, pBlock *pb)
8235 {
8236
8237   pCode *pc;
8238   regs  *r;
8239
8240         if(!pic16_pcode_verbose)return;
8241         
8242   fprintf(of,";***\n;  pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
8243
8244   // for now just print the first element of each set
8245   pc = setFirstItem(pb->function_entries);
8246   if(pc) {
8247     fprintf(of,";entry:  ");
8248     pc->print(of,pc);
8249   }
8250   pc = setFirstItem(pb->function_exits);
8251   if(pc) {
8252     fprintf(of,";has an exit\n");
8253     //pc->print(of,pc);
8254   }
8255
8256   pc = setFirstItem(pb->function_calls);
8257   if(pc) {
8258     fprintf(of,";functions called:\n");
8259
8260     while(pc) {
8261       if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8262         fprintf(of,";   %s\n",pic16_get_op_from_instruction(PCI(pc)));
8263       }
8264       pc = setNextItem(pb->function_calls);
8265     }
8266   }
8267
8268   r = setFirstItem(pb->tregisters);
8269   if(r) {
8270     int n = elementsInSet(pb->tregisters);
8271
8272     fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
8273
8274     while (r) {
8275       fprintf(of,   ";   %s\n",r->name);
8276       r = setNextItem(pb->tregisters);
8277     }
8278   }
8279   
8280   fprintf(of, "; uses %d bytes of stack\n", 1+ elementsInSet(pb->tregisters));
8281 }
8282
8283 /*-----------------------------------------------------------------*/
8284 /*-----------------------------------------------------------------*/
8285 #if 0
8286 static void sequencepCode(void)
8287 {
8288   pBlock *pb;
8289   pCode *pc;
8290
8291
8292   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8293
8294     pb->seq = GpCodeSequenceNumber+1;
8295
8296     for( pc = pb->pcHead; pc; pc = pc->next)
8297       pc->seq = ++GpCodeSequenceNumber;
8298   }
8299
8300 }
8301 #endif
8302
8303 /*-----------------------------------------------------------------*/
8304 /*-----------------------------------------------------------------*/
8305 static set *register_usage(pBlock *pb)
8306 {
8307   pCode *pc,*pcn;
8308   set *registers=NULL;
8309   set *registersInCallPath = NULL;
8310
8311   /* check recursion */
8312
8313   pc = setFirstItem(pb->function_entries);
8314
8315   if(!pc)
8316     return registers;
8317
8318   pb->visited = 1;
8319
8320   if(pc->type != PC_FUNCTION)
8321     fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
8322
8323   pc = setFirstItem(pb->function_calls);
8324   for( ; pc; pc = setNextItem(pb->function_calls)) {
8325
8326     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8327       char *dest = pic16_get_op_from_instruction(PCI(pc));
8328
8329       pcn = findFunction(dest);
8330       if(pcn) 
8331         registersInCallPath = register_usage(pcn->pb);
8332     } else
8333       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8334
8335   }
8336
8337 #ifdef PCODE_DEBUG
8338   pBlockStats(stderr,pb);  // debug
8339 #endif
8340
8341   // Mark the registers in this block as used.
8342
8343   MarkUsedRegisters(pb->tregisters);
8344   if(registersInCallPath) {
8345     /* registers were used in the functions this pBlock has called */
8346     /* so now, we need to see if these collide with the ones we are */
8347     /* using here */
8348
8349     regs *r1,*r2, *newreg;
8350
8351     DFPRINTF((stderr,"comparing registers\n"));
8352
8353     r1 = setFirstItem(registersInCallPath);
8354     while(r1) {
8355
8356       r2 = setFirstItem(pb->tregisters);
8357
8358       while(r2 && (r1->type != REG_STK)) {
8359
8360         if(r2->rIdx == r1->rIdx) {
8361           newreg = pic16_findFreeReg(REG_GPR);
8362
8363
8364           if(!newreg) {
8365             DFPRINTF((stderr,"Bummer, no more registers.\n"));
8366             exit(1);
8367           }
8368
8369           DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
8370                   r1->rIdx, newreg->rIdx));
8371           r2->rIdx = newreg->rIdx;
8372           //if(r2->name) Safe_free(r2->name);
8373           if(newreg->name)
8374             r2->name = Safe_strdup(newreg->name);
8375           else
8376             r2->name = NULL;
8377           newreg->isFree = 0;
8378           newreg->wasUsed = 1;
8379         }
8380         r2 = setNextItem(pb->tregisters);
8381       }
8382
8383       r1 = setNextItem(registersInCallPath);
8384     }
8385
8386     /* Collisions have been resolved. Now free the registers in the call path */
8387     r1 = setFirstItem(registersInCallPath);
8388     while(r1) {
8389       if(r1->type != REG_STK) {
8390         newreg = pic16_regWithIdx(r1->rIdx);
8391         newreg->isFree = 1;
8392       }
8393       r1 = setNextItem(registersInCallPath);
8394     }
8395
8396   }// else
8397   //    MarkUsedRegisters(pb->registers);
8398
8399   registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
8400 #ifdef PCODE_DEBUG
8401   if(registers) 
8402     DFPRINTF((stderr,"returning regs\n"));
8403   else
8404     DFPRINTF((stderr,"not returning regs\n"));
8405
8406   DFPRINTF((stderr,"pBlock after register optim.\n"));
8407   pBlockStats(stderr,pb);  // debug
8408 #endif
8409
8410   return registers;
8411 }
8412
8413 /*-----------------------------------------------------------------*/
8414 /* pct2 - writes the call tree to a file                           */
8415 /*                                                                 */
8416 /*-----------------------------------------------------------------*/
8417 static void pct2(FILE *of,pBlock *pb,int indent,int usedstack)
8418 {
8419   pCode *pc,*pcn;
8420   int i;
8421   //  set *registersInCallPath = NULL;
8422
8423   if(!of)
8424     return;
8425
8426   if(indent > 10) {
8427         fprintf(of, "recursive function\n");
8428     return; //recursion ?
8429   }
8430
8431   pc = setFirstItem(pb->function_entries);
8432
8433   if(!pc)
8434     return;
8435
8436   pb->visited = 0;
8437
8438   for(i=0;i<indent;i++)   // Indentation
8439         fputs("+   ", of);
8440   fputs("+- ", of);
8441
8442   if(pc->type == PC_FUNCTION) {
8443     usedstack += PCF(pc)->stackusage;
8444     fprintf(of,"%s (stack: %i)\n",PCF(pc)->fname, usedstack);
8445   } else return;  // ???
8446
8447
8448   pc = setFirstItem(pb->function_calls);
8449   for( ; pc; pc = setNextItem(pb->function_calls)) {
8450
8451     if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
8452       char *dest = pic16_get_op_from_instruction(PCI(pc));
8453
8454       pcn = findFunction(dest);
8455       if(pcn) 
8456         pct2(of,pcn->pb,indent+1, usedstack);   // + PCF(pcn)->stackusage);
8457     } else
8458       fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8459
8460   }
8461
8462
8463 }
8464
8465
8466 /*-----------------------------------------------------------------*/
8467 /* pic16_printCallTree - writes the call tree to a file                  */
8468 /*                                                                 */
8469 /*-----------------------------------------------------------------*/
8470
8471 void pic16_printCallTree(FILE *of)
8472 {
8473   pBranch *pbr;
8474   pBlock  *pb;
8475   pCode   *pc;
8476
8477   if(!the_pFile)
8478     return;
8479
8480   if(!of)
8481     of = stderr;
8482
8483   fprintf(of, "\npBlock statistics\n");
8484   for(pb = the_pFile->pbHead; pb;  pb = pb->next )
8485     pBlockStats(of,pb);
8486
8487
8488   fprintf(of,"Call Tree\n");
8489   pbr = the_pFile->functions;
8490   while(pbr) {
8491     if(pbr->pc) {
8492       pc = pbr->pc;
8493       if(!ispCodeFunction(pc))
8494         fprintf(of,"bug in call tree");
8495
8496
8497       fprintf(of,"Function: %s\n", PCF(pc)->fname);
8498
8499       while(pc->next && !ispCodeFunction(pc->next)) {
8500         pc = pc->next;
8501         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
8502           fprintf(of,"\t%s\n",pic16_get_op_from_instruction(PCI(pc)));
8503       }
8504     }
8505
8506     pbr = pbr->next;
8507   }
8508
8509
8510   fprintf(of,"\n**************\n\na better call tree\n");
8511   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8512 //    if(pb->visited)
8513       pct2(of,pb,0,0);
8514   }
8515
8516   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8517     fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
8518   }
8519 }
8520
8521
8522
8523 /*-----------------------------------------------------------------*/
8524 /*                                                                 */
8525 /*-----------------------------------------------------------------*/
8526
8527 static void InlineFunction(pBlock *pb)
8528 {
8529   pCode *pc;
8530   pCode *pc_call;
8531
8532   if(!pb)
8533     return;
8534
8535   pc = setFirstItem(pb->function_calls);
8536
8537   for( ; pc; pc = setNextItem(pb->function_calls)) {
8538
8539     if(isCALL(pc)) {
8540       pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
8541       pCode *pct;
8542       pCode *pce;
8543
8544       pBranch *pbr;
8545
8546       if(pcn && isPCF(pcn) && (PCF(pcn)->ncalled == 0)) {               /* change 0 to 1 to enable inlining */
8547         
8548         //fprintf(stderr,"Cool can inline:\n");
8549         //pcn->print(stderr,pcn);
8550
8551         //fprintf(stderr,"recursive call Inline\n");
8552         InlineFunction(pcn->pb);
8553         //fprintf(stderr,"return from recursive call Inline\n");
8554
8555         /*
8556           At this point, *pc points to a CALL mnemonic, and
8557           *pcn points to the function that is being called.
8558
8559           To in-line this call, we need to remove the CALL
8560           and RETURN(s), and link the function pCode in with
8561           the CALLee pCode.
8562
8563         */
8564
8565
8566         /* Remove the CALL */
8567         pc_call = pc;
8568         pc = pc->prev;
8569
8570         /* remove callee pBlock from the pBlock linked list */
8571         removepBlock(pcn->pb);
8572
8573         pce = pcn;
8574         while(pce) {
8575           pce->pb = pb;
8576           pce = pce->next;
8577         }
8578
8579         /* Remove the Function pCode */
8580         pct = pic16_findNextInstruction(pcn->next);
8581
8582         /* Link the function with the callee */
8583         pc->next = pcn->next;
8584         pcn->next->prev = pc;
8585         
8586         /* Convert the function name into a label */
8587
8588         pbr = Safe_calloc(1,sizeof(pBranch));
8589         pbr->pc = pic16_newpCodeLabel(PCF(pcn)->fname, -1);
8590         pbr->next = NULL;
8591         PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,pbr);
8592         PCI(pct)->label = pic16_pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
8593
8594         /* turn all of the return's except the last into goto's */
8595         /* check case for 2 instruction pBlocks */
8596         pce = pic16_findNextInstruction(pcn->next);
8597         while(pce) {
8598           pCode *pce_next = pic16_findNextInstruction(pce->next);
8599
8600           if(pce_next == NULL) {
8601             /* found the last return */
8602             pCode *pc_call_next =  pic16_findNextInstruction(pc_call->next);
8603
8604             //fprintf(stderr,"found last return\n");
8605             //pce->print(stderr,pce);
8606             pce->prev->next = pc_call->next;
8607             pc_call->next->prev = pce->prev;
8608             PCI(pc_call_next)->label = pic16_pBranchAppend(PCI(pc_call_next)->label,
8609                                                       PCI(pce)->label);
8610           }
8611
8612           pce = pce_next;
8613         }
8614
8615
8616       }
8617     } else
8618       fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8619
8620   }
8621
8622 }
8623
8624 /*-----------------------------------------------------------------*/
8625 /*                                                                 */
8626 /*-----------------------------------------------------------------*/
8627
8628 void pic16_InlinepCode(void)
8629 {
8630
8631   pBlock  *pb;
8632   pCode   *pc;
8633
8634   if(!the_pFile)
8635     return;
8636
8637   if(!functionInlining)
8638     return;
8639
8640   /* Loop through all of the function definitions and count the
8641    * number of times each one is called */
8642   //fprintf(stderr,"inlining %d\n",__LINE__);
8643
8644   for(pb = the_pFile->pbHead; pb; pb = pb->next) {
8645
8646     pc = setFirstItem(pb->function_calls);
8647
8648     for( ; pc; pc = setNextItem(pb->function_calls)) {
8649
8650       if(isCALL(pc)) {
8651         pCode *pcn = findFunction(pic16_get_op_from_instruction(PCI(pc)));
8652         if(pcn && isPCF(pcn)) {
8653           PCF(pcn)->ncalled++;
8654         }
8655       } else
8656         fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
8657
8658     }
8659   }
8660
8661   //fprintf(stderr,"inlining %d\n",__LINE__);
8662
8663   /* Now, Loop through the function definitions again, but this
8664    * time inline those functions that have only been called once. */
8665   
8666   InlineFunction(the_pFile->pbHead);
8667   //fprintf(stderr,"inlining %d\n",__LINE__);
8668
8669   for(pb = the_pFile->pbHead; pb; pb = pb->next)
8670     unBuildFlow(pb);
8671
8672 }
8673
8674 char *pic_optype_names[]={
8675         "PO_NONE",         // No operand e.g. NOP
8676         "PO_W",              // The working register (as a destination)
8677         "PO_WREG",           // The working register (as a file register)
8678         "PO_STATUS",         // The 'STATUS' register
8679         "PO_BSR",            // The 'BSR' register
8680         "PO_FSR0",           // The "file select register" (in PIC18 family it's one 
8681                              // of three)
8682         "PO_INDF0",          // The Indirect register
8683         "PO_INTCON",         // Interrupt Control register
8684         "PO_GPR_REGISTER",   // A general purpose register
8685         "PO_GPR_BIT",        // A bit of a general purpose register
8686         "PO_GPR_TEMP",       // A general purpose temporary register
8687         "PO_SFR_REGISTER",   // A special function register (e.g. PORTA)
8688         "PO_PCL",            // Program counter Low register
8689         "PO_PCLATH",         // Program counter Latch high register
8690         "PO_PCLATU",         // Program counter Latch upper register
8691         "PO_PRODL",          // Product Register Low
8692         "PO_PRODH",          // Product Register High
8693         "PO_LITERAL",        // A constant
8694         "PO_REL_ADDR",       // A relative address
8695         "PO_IMMEDIATE",      //  (8051 legacy)
8696         "PO_DIR",            // Direct memory (8051 legacy)
8697         "PO_CRY",            // bit memory (8051 legacy)
8698         "PO_BIT",            // bit operand.
8699         "PO_STR",            //  (8051 legacy)
8700         "PO_LABEL",
8701         "PO_WILD",           // Wild card operand in peep optimizer
8702         "PO_TWO_OPS"         // combine two operands
8703 };
8704
8705
8706 char *dumpPicOptype(PIC_OPTYPE type)
8707 {
8708         assert( type >= 0 && type < sizeof(pic_optype_names)/sizeof( char *) );
8709         return (pic_optype_names[ type ]);
8710 }
8711
8712
8713 /*** BEGIN of stuff belonging to the BANKSEL optimization ***/
8714 #include "graph.h"
8715
8716 #define MAX_COMMON_BANK_SIZE    32
8717 #define FIRST_PSEUDO_BANK_NR  1000
8718
8719 hTab *sym2bank = NULL; // <OPERAND NAME> --> <PSEUDO BANK NR>
8720 hTab *bank2sym = NULL; // <PSEUDO BANK NR> --> <OPERAND NAME>
8721 hTab *coerce = NULL;   // <PSEUDO BANK NR> --> <&PSEUDOBANK>
8722 Graph *adj = NULL;
8723
8724 typedef enum { INVALID_BANK = -1, UNKNOWN_BANK = -2, FIXED_BANK = -3 } pseudoBankNr;
8725
8726 typedef struct {
8727   pseudoBankNr bank;  // number assigned to this pseudoBank
8728   unsigned int size;  // number of operands assigned to this bank
8729   unsigned int ref;   // number of symbols referring to this pseudoBank (for garbage collection)
8730 } pseudoBank;
8731
8732 /*----------------------------------------------------------------------*/
8733 /* hashSymbol - hash function used to map SYMBOLs (or operands) to ints */
8734 /*----------------------------------------------------------------------*/
8735 unsigned int hashSymbol (const char *str)
8736 {
8737   unsigned int res = 0;
8738   if (!str) return 0;
8739
8740   while (*str) {
8741     res ^= (*str);
8742     res = (res << 4) | (res >> (8 * sizeof(unsigned int) - 4));
8743     str++;
8744   } // while
8745
8746   return res;
8747 }
8748
8749 /*-----------------------------------------------------------------------*/
8750 /* compareSymbol - return 1 iff sym1 equals sym2                         */
8751 /*-----------------------------------------------------------------------*/
8752 int compareSymbol (const void *sym1, const void *sym2)
8753 {
8754   char *s1 = (char*) sym1;
8755   char *s2 = (char*) sym2;
8756   
8757   return (strcmp (s1,s2) == 0);
8758 }
8759
8760 /*-----------------------------------------------------------------------*/
8761 /* comparePre - return 1 iff p1 == p2                                    */
8762 /*-----------------------------------------------------------------------*/
8763 int comparePtr (const void *p1, const void *p2)
8764 {
8765   return (p1 == p2);
8766 }
8767
8768 /*----------------------------------------------------------*/
8769 /* getSymbolFromOperand - return a pointer to the symbol in */
8770 /*                        the given operand and its length  */
8771 /*----------------------------------------------------------*/
8772 char *getSymbolFromOperand (char *op, int *len)
8773 {
8774   char *sym, *curr;
8775   *len = 0;
8776
8777   if (!op) return NULL;
8778
8779   // we recognize two forms of operands: SYMBOL and (SYMBOL + offset)
8780   sym = op;
8781   if (*sym == '(') sym++;
8782
8783   curr = sym;
8784   while (((*curr >= 'A') && (*curr <= 'Z'))
8785          || ((*curr >= 'a') && (*curr <= 'z'))
8786          || ((curr != sym) && (*curr >= '0') && (*curr <= '9'))
8787          || (*curr == '_')) {
8788     // find end of symbol [A-Za-z_]?[A-Za-z0-9]*
8789     curr++;
8790     (*len)++;
8791   } // while
8792
8793   return sym;
8794 }
8795
8796 /*--------------------------------------------------------------------------*/
8797 /* getSymFromBank - get (one) name of a symbol assigned to the given bank   */
8798 /*--------------------------------------------------------------------------*/
8799 char *getSymFromBank (pseudoBankNr bank)
8800 {
8801   assert (bank2sym);
8802
8803   if (bank < 0) return "<INVALID BANK NR>";
8804   return hTabFindByKey (bank2sym, bank % bank2sym->size, (void *) bank, &comparePtr);
8805 }
8806
8807 /*-----------------------------------------------------------------------*/
8808 /* getPseudoBsrFromOperand - maps a string to its corresponding pseudo   */
8809 /*                           bank number (uses hTab sym2bank), if the    */
8810 /*                           symbol is not yet assigned a pseudo bank it */
8811 /*                           is assigned one here                        */
8812 /*-----------------------------------------------------------------------*/
8813 pseudoBankNr getPseudoBankNrFromOperand (const char *op)
8814 {
8815   static pseudoBankNr next_bank = FIRST_PSEUDO_BANK_NR;
8816   pseudoBankNr bank;
8817   unsigned int hash;
8818
8819   assert (sym2bank);
8820
8821   hash = hashSymbol (op) % sym2bank->size;
8822   bank = (pseudoBankNr) hTabFindByKey (sym2bank, hash, op, &compareSymbol);
8823   if (bank == (pseudoBankNr)NULL) bank = UNKNOWN_BANK;
8824
8825   if (bank == UNKNOWN_BANK) {
8826     // create a pseudo bank for the operand
8827     bank = next_bank++;
8828     hTabAddItemLong (&sym2bank, hash, (char *)op, (void *)bank);
8829     hTabAddItemLong (&bank2sym, bank, (void *) bank, (void *)op);
8830     getOrAddGNode (adj, NULL, bank); // adds the node if it does not exist yet
8831     //fprintf (stderr, "%s:%d: adding %s with hash %u in bank %u\n", __FUNCTION__, __LINE__, op, hash, bank);
8832   } else {
8833     //fprintf (stderr, "%s:%d: found %s with hash %u in bank %u\n", __FUNCTION__, __LINE__, op, hash, bank);
8834   } // if
8835
8836   assert (bank >= 0);
8837
8838   return bank;
8839 }
8840
8841 /*--------------------------------------------------------------------*/
8842 /* isBanksel - check whether the given pCode is a BANKSEL instruction */
8843 /*--------------------------------------------------------------------*/
8844 int isBanksel (pCode *pc)
8845 {
8846   if (!pc) return 0;
8847
8848   if (isPCI(pc) && (PCI(pc)->op == POC_BANKSEL || PCI(pc)->op == POC_MOVLB)) {
8849     // BANKSEL <variablename>  or  MOVLB <banknr>
8850     //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8851     return 1;
8852   }
8853
8854   // check for inline assembler BANKSELs
8855   if (isPCAD(pc) && PCAD(pc)->directive && (STRCASECMP(PCAD(pc)->directive,"BANKSEL") == 0 ||
8856                                             STRCASECMP(PCAD(pc)->directive,"MOVLB") == 0)) {
8857     //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8858     return 1;
8859   }
8860
8861   // assume pc is no BANKSEL instruction
8862   return 0;
8863 }
8864
8865 /*---------------------------------------------------------------------------------*/
8866 /* invalidatesBSR - check whether the pCodeInstruction passed in modifies the BSR  */
8867 /*                  This method can not guarantee to find all modifications of the */
8868 /*                  BSR (e.g. via INDirection registers) but covers all compiler   */
8869 /*                  generated plus some cases.                                     */
8870 /*---------------------------------------------------------------------------------*/
8871 int invalidatesBSR(pCode *pc)
8872 {
8873   // assembler directives invalidate BSR (well, they might, we don't know)
8874   if (isPCAD(pc)) return 1;
8875
8876   // only ASMDIRs and pCodeInstructions can invalidate BSR
8877   if (!isPCI(pc)) return 0;
8878
8879   // we have a pCodeInstruction
8880
8881   // check for BSR modifying instructions
8882   switch (PCI(pc)->op) {
8883   case POC_CALL:
8884   case POC_RCALL:
8885   case POC_MOVLB:
8886   case POC_RETFIE:  // might be used as CALL replacement
8887   case POC_RETLW:   // might be used as CALL replacement
8888   case POC_RETURN:  // might be used as CALL replacement
8889   case POC_BANKSEL:
8890     return 1;
8891     break;
8892
8893   default:          // other instruction do not change BSR unless BSR is an explicit operand!
8894     // TODO: check for BSR as an explicit operand (e.g. INCF BSR,F), which should be rather unlikely...!
8895     break;
8896   } // switch
8897
8898   // no change of BSR possible/probable
8899   return 0;
8900 }
8901
8902 /*------------------------------------------------------------*/
8903 /* getBankFromBanksel - return the pseudo bank nr assigned to */
8904 /*                      the symbol referenced in this BANKSEL */
8905 /*------------------------------------------------------------*/
8906 pseudoBankNr getBankFromBanksel (pCode *pc)
8907 {
8908   char *sym;
8909   int data = (int)NULL;
8910
8911   if (!pc) return INVALID_BANK;
8912   
8913   if (isPCAD(pc) && PCAD(pc)->directive) {
8914     if (STRCASECMP(PCAD(pc)->directive,"BANKSEL") == 0) {
8915       // get symbolname from PCAD(pc)->arg
8916       //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8917       sym = PCAD(pc)->arg;
8918       data = getPseudoBankNrFromOperand (sym);
8919       //fprintf (stderr, "symbol: %s, data=%i\n", sym, data);
8920     } else if (STRCASECMP(PCAD(pc)->directive,"MOVLB")) {
8921       // get (literal) bank number from PCAD(pc)->arg
8922       fprintf (stderr, "%s:%d: MOVLB found: %s %s\n", __FUNCTION__, __LINE__, PCAD(pc)->directive, PCAD(pc)->arg);
8923       assert (0 && "not yet implemented - turn off banksel optimization for now");
8924     }
8925   } else if (isPCI(pc)) {
8926     if (PCI(pc)->op == POC_BANKSEL) {
8927       // get symbolname from PCI(pc)->pcop->name (?)
8928       //fprintf (stderr, "%s:%d: BANKSEL found: %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pcop->name);
8929       sym = PCI(pc)->pcop->name;
8930       data = getPseudoBankNrFromOperand (sym);
8931       //fprintf (stderr, "symbol: %s, data=%i\n", sym, data);
8932     } else if (PCI(pc)->op == POC_MOVLB) {
8933       // get (literal) bank number from PCI(pc)->pcop->name
8934       fprintf (stderr, "%s:%d: MOVLB found: %s %s\n", __FUNCTION__, __LINE__, PCI(pc)->mnemonic, PCI(pc)->pcop->name);
8935       assert (0 && "not yet implemented - turn off banksel optimization for now");
8936     }
8937   }
8938   
8939   if (data == 0)
8940     // no assigned bank could be found
8941     return UNKNOWN_BANK;
8942   else
8943     return data;
8944 }
8945
8946 /*------------------------------------------------------------------------------*/
8947 /* getEffectiveBank - resolves the currently assigned effective pseudo bank nr  */
8948 /*------------------------------------------------------------------------------*/
8949 pseudoBankNr getEffectiveBank (pseudoBankNr bank)
8950 {
8951   pseudoBank *data;
8952
8953   if (bank < FIRST_PSEUDO_BANK_NR) return bank;
8954
8955   do {
8956     //fprintf (stderr, "%s:%d: bank=%d\n", __FUNCTION__, __LINE__, bank);
8957     data = (pseudoBank *) hTabFindByKey (coerce, bank % coerce->size, (void *) bank, &comparePtr);
8958     if (data) {
8959       if (data->bank != bank)
8960         bank = data->bank;
8961       else
8962         data = NULL;
8963     }
8964   } while (data);
8965   
8966   //fprintf (stderr, "%s:%d: effective bank=%d\n", __FUNCTION__, __LINE__, bank);
8967   return bank;
8968 }
8969
8970 /*------------------------------------------------------------------*/
8971 /* attachBsrInfo2pBlock - create a look-up table as to which pseudo */
8972 /*                        bank is selected at a given pCode         */
8973 /*------------------------------------------------------------------*/
8974
8975 /* Create a graph with pseudo banks as its nodes and switches between
8976  * these as edges (with the edge weight representing the absolute
8977  * number of BANKSELs from one to the other).
8978  * Removes redundand BANKSELs instead iff mod == 1.
8979  * BANKSELs update the pseudo BSR, labels invalidate the current BSR
8980  * value (setting it to 0=UNNKOWN), (R)CALLs also invalidate the
8981  * pseudo BSR.
8982  * TODO: check ALL instructions operands if they modify BSR directly...
8983  *
8984  * pb - the pBlock to annotate
8985  * mod  - select either graph creation (0) or BANKSEL removal (1)
8986  */
8987 unsigned int attachBsrInfo2pBlock (pBlock *pb, int mod)
8988 {
8989   pCode *pc, *pc_next;
8990   unsigned int prevBSR = UNKNOWN_BANK, pseudoBSR = UNKNOWN_BANK;
8991   int isBankselect = 0;
8992   unsigned int banksels=0;
8993   
8994   if (!pb) return 0;
8995
8996   pc = pic16_findNextInstruction(pb->pcHead);
8997   while (pc) {
8998     isBankselect = isBanksel (pc);
8999     pc_next = pic16_findNextInstruction (pc->next);
9000
9001     if (!hasNoLabel (pc)) {
9002       // we don't know our predecessors -- assume different BSRs
9003       prevBSR = UNKNOWN_BANK;
9004       pseudoBSR = UNKNOWN_BANK;
9005       //fprintf (stderr, "invalidated by label at "); pc->print (stderr, pc);
9006     } // if
9007
9008     // check if this is a BANKSEL instruction
9009     if (isBankselect) {
9010       pseudoBSR = getEffectiveBank (getBankFromBanksel(pc));
9011       //fprintf (stderr, "BANKSEL via "); pc->print (stderr, pc);
9012       if (mod) {
9013         if (prevBSR == pseudoBSR && pseudoBSR >= 0) {
9014           //fprintf (stderr, "removing redundant "); pc->print (stderr, pc);
9015           if (1 || pic16_pcode_verbose) pic16_pCodeInsertAfter (pc->prev, pic16_newpCodeCharP("removed redundant BANKSEL"));
9016           pic16_unlinkpCode (pc);
9017           banksels++;
9018         }
9019       } else {
9020         addGEdge2 (getOrAddGNode (adj, NULL, prevBSR), getOrAddGNode (adj, NULL, pseudoBSR), 1, 0);
9021         banksels++;
9022       }
9023     } // if
9024
9025     if (!isBankselect && invalidatesBSR(pc)) {
9026       // check if this instruction invalidates the pseudoBSR
9027       pseudoBSR = UNKNOWN_BANK;
9028       //fprintf (stderr, "invalidated via "); pc->print (stderr, pc);
9029     } // if
9030
9031     prevBSR = pseudoBSR;
9032     pc = pc_next;
9033   } // while
9034
9035   return banksels;
9036 }
9037
9038 /*------------------------------------------------------------------------------------*/
9039 /* assignToSameBank - returns 0 on success or an error code                           */
9040 /*  1 - common bank would be too large                                                */
9041 /*  2 - assignment to fixed (absolute) bank not performed                             */
9042 /*                                                                                    */
9043 /* This functions assumes that unsplittable operands are already assigned to the same */
9044 /* bank (e.g. all objects being referenced as (SYMBOL + offset) must be in the same   */
9045 /* bank so that we can make sure the bytes are laid out sequentially in memory)       */
9046 /* TODO: Symbols with an abslute address must be handled specially!                   */
9047 /*------------------------------------------------------------------------------------*/
9048 int assignToSameBank (int bank0, int bank1, int doAbs)
9049 {
9050   int eff0, eff1, dummy;
9051   pseudoBank *pbank0, *pbank1;
9052   hashtItem *hitem;
9053
9054   eff0 = getEffectiveBank (bank0);
9055   eff1 = getEffectiveBank (bank1);
9056
9057   //fprintf (stderr, "%s:%d: bank0=%d/%d, bank1=%d/%d, doAbs=%d\n", __FUNCTION__, __LINE__, bank0, eff0, bank1, eff1, doAbs);
9058
9059   // nothing to do if already same bank
9060   if (eff0 == eff1) return 0;
9061
9062   if (!doAbs && (eff0 < FIRST_PSEUDO_BANK_NR || eff1 < FIRST_PSEUDO_BANK_NR))
9063     return 2;
9064
9065   // ensure eff0 < eff1
9066   if (eff0 > eff1) {
9067     // swap eff0 and eff1
9068     dummy = eff0;
9069     eff0 = eff1;
9070     eff1 = dummy;
9071     dummy = bank0;
9072     bank0 = bank1;
9073     bank1 = dummy;
9074   } // if
9075
9076   // now assign bank eff1 to bank eff0
9077   pbank0 = (pseudoBank *) hTabFindByKey (coerce, eff0 % coerce->size, (void *)((char*)0+eff0), &comparePtr);
9078   if (!pbank0) {
9079     pbank0 = Safe_calloc (1, sizeof (pseudoBank));
9080     pbank0->bank = eff0;
9081     pbank0->size = 1;
9082     pbank0->ref = 1;
9083     hTabAddItemLong (&coerce, eff0 % coerce->size, (void *)((char*)0+eff0), (void *) pbank0);
9084   } // if
9085
9086   pbank1 = NULL;
9087   hitem = hTabSearch (coerce, eff1 % coerce->size);
9088   while (hitem && hitem->pkey != (void *)((char*)0+eff1))
9089     hitem = hitem->next;
9090
9091   if (hitem) pbank1 = (pseudoBank *) hitem->item;
9092
9093 #if 0
9094   fprintf (stderr, "bank #%d/%d & bank #%d/%d --> bank #%d: %u (%s & %s)\n", bank0, eff0, bank1, eff1,
9095            pbank0->bank, pbank0->size,
9096            getSymFromBank (eff0), getSymFromBank (eff1));
9097 #endif
9098
9099   if (pbank1) {
9100     if (pbank0->size + pbank1->size > MAX_COMMON_BANK_SIZE) {
9101 #if 0
9102       fprintf (stderr, "bank #%d: %u, bank #%d: %u --> bank #%d': %u > %u (%s,%s)\n",
9103                pbank0->bank, pbank0->size, pbank1->bank, pbank1->size,
9104                pbank0->bank, pbank0->size + pbank1->size, MAX_COMMON_BANK_SIZE,
9105                getSymFromBank (pbank0->bank), getSymFromBank (pbank1->bank));
9106 #endif
9107       return 1;
9108     } // if
9109     pbank0->size += pbank1->size;
9110     pbank1->ref--;
9111     if (pbank1->ref == 0) Safe_free (pbank1);
9112   } else {
9113     pbank0->size++;
9114   } // if
9115
9116   if (hitem)
9117     hitem->item = pbank0;
9118   else  
9119     hTabAddItemLong (&coerce, eff1 % coerce->size, (void *)((char*)0+eff1), (void *) pbank0);
9120   pbank0->ref++;
9121
9122   //fprintf (stderr, "%s:%d: leaving.\n", __FUNCTION__, __LINE__);
9123
9124   return 0;
9125 }
9126
9127 /*----------------------------------------------------------------*/
9128 /* mergeGraphNodes - combines two nodes into one and modifies all */
9129 /*                   edges to and from the nodes accordingly      */
9130 /* This method needs complete backedges, i.e. if (A,B) is an edge */
9131 /* then also (B,A) must be an edge (possibly with weight 0).      */
9132 /*----------------------------------------------------------------*/
9133 void mergeGraphNodes (GraphNode *node1, GraphNode *node2)
9134 {
9135   GraphEdge *edge, *backedge, *nextedge;
9136   GraphNode *node;
9137   int backweight;
9138
9139   assert (node1 && node2);
9140   assert (node1 != node2);
9141   
9142   // add all edges starting at node2 to node1
9143   edge = node2->edge;
9144   while (edge) {
9145     nextedge = edge->next;
9146     node = edge->node;
9147     backedge = getGEdge (node, node2);
9148     if (backedge)
9149       backweight = backedge->weight;
9150     else
9151       backweight = 0;
9152     // insert edges (node1,node) and (node,node1)
9153     addGEdge2 (node1, node, edge->weight, backweight);
9154     // remove edges (node, node2) and (node2, node)
9155     remGEdge (node2, node);
9156     remGEdge (node, node2);
9157     edge = nextedge;
9158   } // while
9159   
9160   // now node2 should not be referenced by any other GraphNode...
9161   //remGNode (adj, node2->data, node2->hash);
9162 }
9163
9164 /*----------------------------------------------------------------*/
9165 /* showGraph - dump the current BANKSEL graph as a node/edge list */
9166 /*----------------------------------------------------------------*/
9167 void showGraph (Graph *g)
9168 {
9169   GraphNode *node;
9170   GraphEdge *edge;
9171   pseudoBankNr bankNr;
9172   pseudoBank *pbank;
9173   unsigned int size;
9174
9175   node = g->node;
9176   while (node) {
9177     edge = node->edge;
9178     bankNr = getEffectiveBank (node->hash);
9179     assert (bankNr >= 0);
9180     pbank = (pseudoBank *) hTabFindByKey (coerce, bankNr % coerce->size, (void *) bankNr, &comparePtr);
9181     if (pbank) {
9182       bankNr = pbank->bank;
9183       size = pbank->size;
9184     } else {
9185       size = 1;
9186     }
9187     
9188     fprintf (stderr, "edges from %s (bank %u, size %u) to:\n", getSymFromBank (node->hash), bankNr, size);
9189
9190     while (edge) {
9191       if (edge->weight > 0)
9192         fprintf (stderr, "  %4u x %s\n", edge->weight, getSymFromBank (edge->node->hash));
9193       edge = edge->next;
9194     } // while (edge)
9195     node = node->next;
9196   } // while (node)
9197 }
9198
9199 /*---------------------------------------------------------------*/
9200 /* pic16_OptimizeBanksel - remove redundant BANKSEL instructions */
9201 /*---------------------------------------------------------------*/
9202 void pic16_OptimizeBanksel ()
9203 {
9204   GraphNode *node, *node1, *node1next;
9205
9206 #if 0
9207   // needed for more effective bank assignment (needs adjusted pic16_emit_usection())
9208   GraphEdge *edge, *backedge;
9209   GraphEdge *max;
9210   int maxWeight, weight, mergeMore, absMaxWeight;
9211   pseudoBankNr curr0, curr1;
9212 #endif
9213   pseudoBank *pbank;
9214   pseudoBankNr bankNr;
9215   char *base_symbol0, *base_symbol1;
9216   int len0, len1;
9217   pBlock *pb;
9218   set *set;
9219   regs *reg;
9220   unsigned int bankselsTotal = 0, bankselsRemoved = 0; 
9221
9222   //fprintf (stderr, "%s:%s:%d: entered.\n", __FILE__, __FUNCTION__, __LINE__);
9223
9224   if (!the_pFile || !the_pFile->pbHead) return;
9225
9226   adj = newGraph (NULL);
9227   sym2bank = newHashTable ( 255 );
9228   bank2sym = newHashTable ( 255 );
9229   coerce = newHashTable ( 255 );
9230
9231   // create graph of BANKSEL relationships (node = operands, edge (A,B) iff BANKSEL B follows BANKSEL A)
9232   for (pb = the_pFile->pbHead; pb; pb = pb->next) {
9233     bankselsTotal += attachBsrInfo2pBlock (pb, 0);
9234   } // for pb
9235
9236 #if 1
9237   // assign symbols with absolute addresses to their respective bank nrs
9238   set = pic16_fix_udata;
9239   for (reg = setFirstItem (set); reg; reg = setNextItem (set)) {
9240     bankNr = reg->address >> 8;
9241     node = getOrAddGNode (adj, NULL, bankNr);
9242     bankNr = (pseudoBankNr) getEffectiveBank (getPseudoBankNrFromOperand(reg->name));
9243     assignToSameBank (node->hash, bankNr, 1);
9244     
9245     assert (bankNr >= 0);
9246     pbank = (pseudoBank *) hTabFindByKey (coerce, bankNr % coerce->size, (void *) bankNr, &comparePtr);
9247     if (!pbank) {
9248       pbank = Safe_calloc (1, sizeof (pseudoBank));
9249       pbank->bank = reg->address >> 8; //FIXED_BANK;
9250       pbank->size = 1;
9251       pbank->ref = 1;
9252       hTabAddItemLong (&coerce, bankNr % coerce->size, (void *) bankNr, pbank);
9253     } else {
9254       assert (pbank->bank == (reg->address >> 8));
9255       pbank->bank = reg->address >> 8; //FIXED_BANK;
9256     }
9257     //fprintf (stderr, "ABS: %s (%d bytes) at %x in bank %u\n", reg->name, reg->size, reg->address, bankNr);
9258   } // for reg
9259 #endif
9260
9261 #if 1
9262   // assign operands referring to the same symbol (which is not given an absolute address) to the same bank
9263   //fprintf (stderr, "assign operands with the same symbol to the same bank\n");
9264   node = adj->node;
9265   while (node) {
9266     if (node->hash < 0) { node = node->next; continue; }
9267     base_symbol0 = getSymbolFromOperand (getSymFromBank (getEffectiveBank(node->hash)), &len0);
9268     node1 = node->next;
9269     while (node1) {
9270       if (node1->hash < 0) { node1 = node1->next; continue; }
9271       node1next = node1->next;
9272       base_symbol1 = getSymbolFromOperand (getSymFromBank (getEffectiveBank (node1->hash)), &len1);
9273       if (len0 == len1 && len0 > 0 && strncmp (base_symbol0, base_symbol1, len0) == 0) {
9274         // TODO: check for symbols with absolute addresses -- these might be placed across bank boundaries!
9275         //fprintf (stderr, "merging %s and %s\n", getSymFromBank (getEffectiveBank(node->hash)), getSymFromBank (getEffectiveBank(node1->hash)));
9276         if (assignToSameBank (node->hash, node1->hash, 0)) {
9277           fprintf (stderr, "%s(%d) == %s(%d)\n", base_symbol0, len0, base_symbol1, len1);
9278           assert (0 && "Could not assign a symbol to a bank!");
9279         }
9280         mergeGraphNodes (node, node1);
9281         /*
9282         if (node->hash < node1->hash)
9283           mergeGraphNodes (node, node1);
9284         else
9285           mergeGraphNodes (node1, node); // this removes node so node->next will fail...
9286         */
9287       } // if
9288       node1 = node1next;
9289     } // while (node1)
9290     node = node->next;
9291   } // while (node)
9292 #endif
9293
9294 #if 0
9295   // >>> THIS ALSO NEEDS AN UPDATED pic16_emit_usection() TO REFLECT THE BANK ASSIGNMENTS <<<
9296   // assign tightly coupled operands to the same (pseudo) bank
9297   //fprintf (stderr, "assign tightly coupled operands to the same bank\n");
9298   mergeMore = 1;
9299   absMaxWeight = 0;
9300   while (mergeMore) {
9301     node = adj->node;
9302     max = NULL;
9303     maxWeight = 0;
9304     while (node) {
9305       curr0 = getEffectiveBank (node->hash);
9306       if (curr0 < 0) { node = node->next; continue; }
9307       edge = node->edge;
9308       while (edge) {
9309         assert (edge->src == node);
9310         backedge = getGEdge (edge->node, edge->src);
9311         weight = edge->weight + (backedge ? backedge->weight : 0);
9312         curr1 = getEffectiveBank (edge->node->hash);
9313         if (curr1 < 0) { edge = edge->next; continue; }
9314
9315         // merging is only useful if the items are not assigned to the same bank already...
9316         if (curr0 != curr1 && weight > maxWeight) {
9317           if (maxWeight > absMaxWeight) absMaxWeight = maxWeight;
9318           maxWeight = weight;
9319           max = edge;
9320         } // if
9321         edge = edge->next;
9322       } // while
9323       node = node->next;
9324     } // while
9325     
9326     if (maxWeight > 0) {
9327 #if 0
9328       fprintf (stderr, "%s:%d: merging (%4u) %d(%s) and %d(%s)\n", __FUNCTION__, __LINE__, maxWeight,
9329                max->src->hash, getSymFromBank (max->src->hash),
9330                max->node->hash, getSymFromBank (max->node->hash));
9331 #endif
9332
9333       node = getGNode (adj, max->src->data, max->src->hash);
9334       node1 = getGNode (adj, max->node->data, max->node->hash);
9335
9336       if (0 == assignToSameBank (max->src->hash, max->node->hash, 0)) {
9337         if (max->src->hash < max->node->hash)
9338           mergeGraphNodes (node, node1);
9339         else
9340           mergeGraphNodes (node1, node);
9341       } else {
9342         remGEdge (node, node1);
9343         remGEdge (node1, node);
9344         //mergeMore = 0;
9345       }
9346
9347     } else {
9348       mergeMore = 0;
9349     }
9350   } // while
9351 #endif
9352
9353 #if 1  
9354   // remove redundant BANKSELs
9355   //fprintf (stderr, "removing redundant BANKSELs\n");
9356   for (pb = the_pFile->pbHead; pb; pb = pb->next) {
9357     bankselsRemoved += attachBsrInfo2pBlock (pb, 1);
9358   } // for pb
9359 #endif
9360
9361 #if 0
9362   fprintf (stderr, "display graph\n");
9363   showGraph ();
9364 #endif
9365
9366   deleteGraph (adj);
9367   //fprintf (stderr, "%s:%s:%d: leaving, %u/%u BANKSELs removed...\n", __FILE__, __FUNCTION__, __LINE__, bankselsRemoved, bankselsTotal);
9368 }
9369
9370 /*** END of stuff belonging to the BANKSEL optimization ***/
9371
9372
9373
9374 /*** BEGIN of helpers for pCode dataflow optimizations ***/
9375
9376 typedef unsigned int symbol_t;
9377 typedef unsigned int valnum_t;
9378 //typedef unsigned int hash_t;
9379
9380 #ifndef INT_TO_PTR
9381 #define INT_TO_PTR(x) (((char *) 0) + (x))
9382 #endif
9383
9384 #ifndef PTR_TO_INT
9385 #define PTR_TO_INT(x) (((char *)(x)) - ((char *) 0))
9386 #endif
9387
9388 static int pic16_regIsLocal (regs *r);
9389 static int pic16_safepCodeRemove (pCode *pc, char *comment);
9390
9391 /* statistics */
9392 static unsigned int pic16_df_removed_pcodes = 0;
9393 static unsigned int pic16_df_saved_bytes = 0;
9394 static unsigned int df_findall_sameflow = 0;
9395 static unsigned int df_findall_otherflow = 0;
9396 static unsigned int df_findall_in_vals = 0;
9397
9398 static void pic16_df_stats () {
9399   return;
9400   if (pic16_debug_verbose || pic16_pcode_verbose) {
9401     fprintf (stderr, "PIC16: dataflow analysis removed %u instructions (%u bytes)\n", pic16_df_removed_pcodes, pic16_df_saved_bytes);
9402     fprintf (stderr, "findAll: same flow %u (%u in_vals), other flow %u\n", df_findall_sameflow, df_findall_in_vals, df_findall_otherflow);
9403     //pic16_df_removed_pcodes = pic16_df_saved_bytes = 0;
9404   }
9405 }
9406
9407 /* Remove a pCode iff possible:
9408  * - previous pCode is no SKIP
9409  * - pc has no label
9410  * Returns 1 iff the pCode has been removed, 0 otherwise. */
9411 static int pic16_safepCodeUnlink (pCode *pc, char *comment) {
9412   pCode *pcprev, *pcnext;
9413   char buf[256], *total=NULL;
9414   int len;
9415   
9416   if (!comment) comment = "=DF= pCode removed by pic16_safepCodeUnlink";
9417
9418   pcprev = pic16_findPrevInstruction (pc->prev);
9419   pcnext = pic16_findNextInstruction (pc->next);
9420   
9421   /* move labels to next instruction (if possible) */
9422   if (PCI(pc)->label && !pcnext) return 0;
9423
9424   /* if this is a SKIP with side-effects -- do not remove */
9425   /* XXX: might try to replace this one with the side-effect only version */
9426   if (isPCI_SKIP(pc)
9427         && ((PCI(pc)->outCond & (PCC_REGISTER | PCC_W)) != 0))
9428   {
9429     pCode *newpc;
9430     switch (PCI(pc)->op)
9431     {
9432     case POC_INCFSZ:
9433     case POC_INFSNZ:
9434       newpc = pic16_newpCode(POC_INCF, pic16_pCodeOpCopy( PCI(pc)->pcop ) );
9435       pic16_pCodeReplace( pc, newpc );
9436       return 1;
9437       break;
9438     case POC_INCFSZW:
9439       newpc = pic16_newpCode(POC_INCFW, pic16_pCodeOpCopy( PCI(pc)->pcop ) );
9440       pic16_pCodeReplace( pc, newpc );
9441       return 1;
9442       break;
9443     case POC_DECFSZ:
9444     case POC_DCFSNZ:
9445       newpc = pic16_newpCode(POC_INCF, pic16_pCodeOpCopy( PCI(pc)->pcop ) );
9446       pic16_pCodeReplace( pc, newpc );
9447       return 1;
9448       break;
9449     case POC_DECFSZW:
9450       newpc = pic16_newpCode(POC_INCF, pic16_pCodeOpCopy( PCI(pc)->pcop ) );
9451       pic16_pCodeReplace( pc, newpc );
9452       return 1;
9453       break;
9454     default:
9455       return 0;
9456     }
9457     return 0;
9458   }
9459
9460   /* if previous instruction is a skip -- do not remove */
9461   if (pcprev && isPCI_SKIP(pcprev)) {
9462     if (!pic16_safepCodeUnlink (pcprev, "=DF= removed now unused SKIP")) {
9463       /* preceeding SKIP could not be removed -- keep this instruction! */
9464       return 0;
9465     }
9466   }
9467
9468   if (PCI(pc)->label) {
9469     //fprintf (stderr, "%s: moving label(s)\n", __FUNCTION__);
9470     //pc->print (stderr, pc);
9471     PCI(pcnext)->label = pic16_pBranchAppend (PCI(pc)->label, PCI(pcnext)->label);
9472     PCI(pc)->label = NULL;
9473   }
9474   
9475   /* update statistics */
9476   pic16_df_removed_pcodes++;
9477   if (isPCI(pc)) pic16_df_saved_bytes += PCI(pc)->isize;
9478   
9479   /* remove the pCode */
9480   pic16_pCode2str (buf, 256, pc);
9481   //fprintf (stderr, "%s: removing pCode: %s\n", __FUNCTION__, buf);
9482   if (0 || pic16_debug_verbose || pic16_pcode_verbose) {
9483     len = strlen (buf) + strlen (comment) + 10;
9484     total = (char *) Safe_malloc (len);
9485     SNPRINTF (total, len, "%s: %s", comment, buf);
9486     pic16_pCodeInsertAfter (pc, pic16_newpCodeCharP(total));
9487     Safe_free (total);
9488   }
9489
9490   /* actually unlink it from the pBlock -- also remove from to/from lists */
9491   pic16_pCodeUnlink (pc);
9492
9493   /* remove the pCode -- release registers */
9494   pc->destruct (pc);
9495
9496   /* report success */
9497   return 1;
9498 }
9499
9500
9501 /* ======================================================================== */
9502 /* === SYMBOL HANDLING ==================================================== */
9503 /* ======================================================================== */
9504
9505 static hTab *map_strToSym = NULL;               /** (char *) --> symbol_t */
9506 static hTab *map_symToStr = NULL;               /** symbol_t -> (char *) */
9507 static symbol_t nextSymbol = 0x2000;            /** next symbol_t assigned to the next generated symbol */
9508
9509 /** Calculate a hash for a given string.
9510  * If len == 0 the string is assumed to be NUL terminated. */
9511 static hash_t symbolHash (const char *str, unsigned int len) {
9512   hash_t hash = 0;
9513   if (!len) {
9514     while (*str) {
9515       hash = (hash << 2) ^ *str;
9516       str++;
9517     } // while
9518   } else {
9519     while (len--) {
9520       hash = (hash << 2) ^ *str;
9521       str++;
9522     }
9523   }
9524   return hash;
9525 }
9526
9527 /** Return 1 iff strings v1 and v2 are identical. */
9528 static int symcmp (const void *v1, const void *v2) {
9529   return !strcmp ((const char *) v1, (const char *) v2);
9530 }
9531
9532 /** Return 1 iff pointers v1 and v2 are identical. */
9533 static int ptrcmp (const void *v1, const void *v2) {
9534   return (v1 == v2);
9535 }
9536
9537 enum {  SPO_WREG=0x1000,
9538         SPO_STATUS,
9539         SPO_PRODL,
9540         SPO_PRODH,
9541         SPO_INDF0,
9542         SPO_POSTDEC0,
9543         SPO_POSTINC0,
9544         SPO_PREINC0,
9545         SPO_PLUSW0,
9546         SPO_INDF1,
9547         SPO_POSTDEC1,
9548         SPO_POSTINC1,
9549         SPO_PREINC1,
9550         SPO_PLUSW1,
9551         SPO_INDF2,
9552         SPO_POSTDEC2,
9553         SPO_POSTINC2,
9554         SPO_PREINC2,
9555         SPO_PLUSW2,
9556         SPO_STKPTR,
9557         SPO_TOSL,
9558         SPO_TOSH,
9559         SPO_TOSU,
9560         SPO_BSR,
9561         SPO_FSR0L,
9562         SPO_FSR0H,
9563         SPO_FSR1L,
9564         SPO_FSR1H,
9565         SPO_FSR2L,
9566         SPO_FSR2H,
9567         SPO_PCL,
9568         SPO_PCLATH,
9569         SPO_PCLATU,
9570         SPO_TABLAT,
9571         SPO_TBLPTRL,
9572         SPO_TBLPTRH,
9573         SPO_TBLPTRU,
9574         SPO_LAST
9575 };
9576
9577 /* Return the unique symbol_t for the given string. */
9578 static symbol_t symFromStr (const char *str) {
9579   hash_t hash;
9580   char *res;
9581   symbol_t sym;
9582
9583   if (!map_symToStr) {
9584     int i;
9585     struct { char *name; symbol_t sym; } predefsyms[] = {
9586         {"WREG", SPO_WREG},
9587         {"STATUS", SPO_STATUS},
9588         {"PRODL", SPO_PRODL},
9589         {"PRODH", SPO_PRODH},
9590         {"INDF0", SPO_INDF0},
9591         {"POSTDEC0", SPO_POSTDEC0},
9592         {"POSTINC0", SPO_POSTINC0},
9593         {"PREINC0", SPO_PREINC0},
9594         {"PLUSW0", SPO_PLUSW0},
9595         {"INDF1", SPO_INDF1},
9596         {"POSTDEC1", SPO_POSTDEC1},
9597         {"POSTINC1", SPO_POSTINC1},
9598         {"PREINC1", SPO_PREINC1},
9599         {"PLUSW1", SPO_PLUSW1},
9600         {"INDF2", SPO_INDF2},
9601         {"POSTDEC2", SPO_POSTDEC2},
9602         {"POSTINC2", SPO_POSTINC2},
9603         {"PREINC2", SPO_PREINC2},
9604         {"PLUSW2", SPO_PLUSW2},
9605         {"STKPTR", SPO_STKPTR},
9606         {"TOSL", SPO_TOSL},
9607         {"TOSH", SPO_TOSH},
9608         {"TOSU", SPO_TOSU},
9609         {"BSR", SPO_BSR},
9610         {"FSR0L", SPO_FSR0L},
9611         {"FSR0H", SPO_FSR0H},
9612         {"FSR1L", SPO_FSR1L},
9613         {"FSR1H", SPO_FSR1H},
9614         {"FSR2L", SPO_FSR2L},
9615         {"FSR2H", SPO_FSR2H},
9616         {"PCL", SPO_PCL},
9617         {"PCLATH", SPO_PCLATH},
9618         {"PCLATU", SPO_PCLATU},
9619         {"TABLAT", SPO_TABLAT},
9620         {"TBLPTRL", SPO_TBLPTRL},
9621         {"TBLPTRH", SPO_TBLPTRH},
9622         {"TBLPTRU", SPO_TBLPTRU},
9623         {NULL, 0}
9624     };
9625
9626     map_strToSym = newHashTable (128);
9627     map_symToStr = newHashTable (128);
9628
9629     for (i=0; predefsyms[i].name; i++) {
9630       char *name;
9631
9632       /* enter new symbol */
9633       sym = predefsyms[i].sym;
9634       name = predefsyms[i].name;
9635       res = Safe_strdup (name);
9636       hash = symbolHash (name, 0);
9637
9638       hTabAddItemLong (&map_strToSym, hash, res, INT_TO_PTR(sym));
9639       hTabAddItemLong (&map_symToStr, sym % map_symToStr->size, INT_TO_PTR(sym), res);
9640     } // for i
9641   }
9642
9643   hash = symbolHash (str, 0) % map_strToSym->size;
9644   
9645   /* find symbol in table */
9646   sym = PTR_TO_INT(hTabFindByKey (map_strToSym, hash, str, &symcmp));
9647   if (sym) {
9648     //fprintf (stderr, "found symbol %x for %s\n", sym, str);
9649     return sym;
9650   }
9651
9652   /* enter new symbol */
9653   sym = nextSymbol++;
9654   res = Safe_strdup (str);
9655
9656   hTabAddItemLong (&map_strToSym, hash, res, INT_TO_PTR(sym));
9657   hTabAddItemLong (&map_symToStr, sym % map_symToStr->size, INT_TO_PTR(sym), res);
9658
9659   //fprintf (stderr, "created symbol %x for %s\n", sym, res);
9660   
9661   return sym;
9662 }
9663
9664 #if 1
9665 static const char *strFromSym (symbol_t sym) {
9666   return (const char *) hTabFindByKey (map_symToStr, sym % map_symToStr->size, INT_TO_PTR(sym), &ptrcmp);
9667 }
9668 #endif
9669
9670 /* ======================================================================== */
9671 /* === DEFINITION MAP HANDLING ============================================ */
9672 /* ======================================================================== */
9673
9674 /* A defmap provides information about which symbol is defined by which pCode.
9675  * The most recent definitions are prepended to the list, so that the most
9676  * recent definition can be found by forward scanning the list.
9677  * pc2: MOVFF r0x00, r0x01
9678  * pc1: INCF r0x01
9679  * head --> ("r0x01",pc1,42) --> ("STATUS",pc1,44) --> ("r0x01",pc2,28) --> NULL
9680  *
9681  * We attach one defmap to each flow object, and each pCode will occur at
9682  * least once in its flow's defmap (maybe defining the 0 symbol). This can be
9683  * used to find definitions for a pCode in its own defmap that precede pCode.
9684  */
9685
9686 typedef struct defmap_s {
9687   symbol_t sym;                 /** symbol this item refers to */
9688   union {
9689     struct {
9690       unsigned int in_mask:8;   /** mask leaving in accessed bits */
9691       unsigned int mask:8;      /** mask leaving in modified bits (if isWrite) */
9692       int isRead:1;             /** sym/mask is read */
9693       int isWrite:1;            /** sym/mask is written */
9694     } access;
9695     int accessmethod;
9696   } acc;
9697   pCode *pc;                    /** pCode this symbol is refrenced at */
9698   valnum_t in_val;              /** valnum_t of symbol's previous value (the one read at pc) */
9699   valnum_t val;                 /** new unique number for this value (if isWrite) */
9700   struct defmap_s *prev, *next; /** link to previous an next definition */
9701 } defmap_t;
9702
9703 static defmap_t *defmap_free = NULL;            /** list of unused defmaps */
9704 static int defmap_free_count = 0;               /** number of released defmap items */
9705
9706 /* Returns a defmap_t with the specified data; this will be the new list head.
9707  * next - pointer to the current list head */
9708 static defmap_t *newDefmap (symbol_t sym, int in_mask, int mask, int isRead, int isWrite, pCode *pc, valnum_t val, defmap_t *next) {
9709   defmap_t *map;
9710   
9711   if (defmap_free) {
9712     map = defmap_free;
9713     defmap_free = map->next;
9714     --defmap_free_count;
9715   } else {
9716     map = (defmap_t *) Safe_calloc (1, sizeof (defmap_t));
9717   }
9718   map->sym = sym;
9719   map->acc.access.in_mask = (isRead ? (in_mask ? in_mask : 0xFF) : 0x00);
9720   map->acc.access.mask = (isWrite ? (mask ? mask : 0xFF) : 0x00);
9721   map->acc.access.isRead = (isRead != 0);
9722   map->acc.access.isWrite = (isWrite != 0);
9723   map->pc = pc;
9724   map->in_val = 0;
9725   map->val = (isWrite ? val : 0);
9726   map->prev = NULL;
9727   map->next = next;
9728   if (next) next->prev = map;
9729   
9730   return map;
9731 }
9732
9733 /* Returns a copy of the single defmap item. */
9734 static defmap_t *copyDefmap (defmap_t *map) {
9735   defmap_t *res = (defmap_t *) Safe_malloc (sizeof (defmap_t));
9736   memcpy (res, map, sizeof (defmap_t));
9737   res->next = NULL;
9738   res->prev = NULL;
9739   return res;
9740 }
9741
9742 /* Insert a defmap item after the specified one. */
9743 static int defmapInsertAfter (defmap_t *ref, defmap_t *newItem) {
9744   if (!ref || !newItem) return 1;
9745
9746   newItem->next = ref->next;
9747   newItem->prev = ref;
9748   ref->next = newItem;
9749   if (newItem->next) newItem->next->prev = newItem;
9750   
9751   return 0;
9752 }
9753
9754 /* Check whether item (or an identical one) is already in the chain and add it if neccessary.
9755  * item is copied before insertion into chain and therefore left untouched.
9756  * Returns 1 iff the item has been inserted into the list, 0 otherwise. */
9757 static int defmapAddCopyIfNew (defmap_t **head, defmap_t *item) {
9758   defmap_t *dummy;
9759   dummy = *head;
9760   while (dummy && (dummy->sym != item->sym
9761                           || dummy->pc != item->pc
9762                           || dummy->acc.accessmethod != item->acc.accessmethod
9763                           || dummy->val != item->val
9764                           || dummy->in_val != item->in_val)) {
9765     dummy = dummy->next;
9766   } // while
9767
9768   /* item already present? */
9769   if (dummy) return 0;
9770   
9771   /* otherwise: insert copy of item */
9772   dummy = copyDefmap (item);
9773   dummy->next = *head;
9774   if (*head) (*head)->prev = dummy;
9775   *head = dummy;
9776
9777   return 1;
9778 }
9779
9780 /* Releases a defmap. This also removes the map from its chain -- update the head manually! */
9781 static void deleteDefmap (defmap_t *map) {
9782   if (!map) return;
9783   
9784   /* unlink from chain -- fails for the first item (head is not updated!) */
9785   if (map->next) map->next->prev = map->prev;
9786   if (map->prev) map->prev->next = map->next;
9787
9788   /* clear map */
9789   memset (map, 0, sizeof (defmap_t));
9790
9791   /* save for future use */
9792   map->next = defmap_free;
9793   defmap_free = map;
9794   ++defmap_free_count;
9795 }
9796
9797 /* Release all defmaps referenced from map. */
9798 static void deleteDefmapChain (defmap_t **_map) {
9799   defmap_t *map, *next;
9800
9801   if (!_map) return;
9802
9803   map = *_map;
9804   
9805   /* find list head */
9806   while (map && map->prev) map = map->prev;
9807
9808   /* delete all items */
9809   while (map) {
9810     next = map->next;
9811     deleteDefmap (map);
9812     map = next;
9813   } // while
9814
9815   *_map = NULL;
9816 }
9817
9818 /* Free all defmap items. */
9819 static void freeDefmap (defmap_t **_map) {
9820   defmap_t *next;
9821   defmap_t *map;
9822
9823   if (!_map) return;
9824
9825   map = (*_map);
9826   
9827   /* find list head */
9828   while (map->prev) map = map->prev;
9829
9830   /* release all items */
9831   while (map) {
9832     next = map->next;
9833     Safe_free (map);
9834     map = next;
9835   }
9836
9837   (*_map) = NULL;
9838 }
9839
9840 /* Returns the most recent definition for the given symbol preceeding pc.
9841  * If no definition is found, NULL is returned. 
9842  * If pc == NULL the whole list is scanned. */
9843 static defmap_t *defmapFindDef (defmap_t *map, symbol_t sym, pCode *pc) {
9844   defmap_t *curr = map;
9845
9846   if (pc) {
9847     /* skip all definitions up to pc */
9848     while (curr && (curr->pc != pc)) curr = curr->next;
9849
9850     /* pc not in the list -- scan the whole list for definitions */
9851     if (!curr) {
9852       fprintf (stderr, "pc %p not found in defmap -- scanning whole list for symbol '%s'\n", pc, strFromSym (sym));
9853       curr = map;
9854     } else {
9855       /* skip all definitions performed by pc */
9856       while (curr && (curr->pc == pc)) curr = curr->next;
9857     }
9858   } // if (pc)
9859
9860   /* find definition for sym */
9861   while (curr && (!curr->acc.access.isWrite || (curr->sym != sym))) {
9862     curr = curr->next;
9863   }
9864
9865   return curr;
9866 }
9867
9868 #if 0
9869 /* Returns the first use (read) of the given symbol AFTER pc.
9870  * If no such use is found, NULL is returned.
9871  * If pc == NULL the whole list is scanned. */
9872 static defmap_t *defmapFindUse (defmap_t *map, symbol_t sym, pCode *pc) {
9873   defmap_t *curr = map, *prev = NULL;
9874   
9875   if (pc) {
9876     /* skip all definitions up to pc */
9877     while (curr && (curr->pc != pc)) { prev = curr; curr = curr->next; }
9878
9879     /* pc not in the list -- scan the whole list for definitions */
9880     if (!curr) {
9881       //fprintf (stderr, "pc %p not found in defmap -- scanning whole list for symbol '%s'\n", pc, strFromSym (sym));
9882       curr = prev;
9883     }
9884   } else {
9885     /* find end of list */
9886     while (curr && curr->next) curr = curr->next;
9887   } // if (pc)
9888
9889   /* find use of sym (scan list backwards) */
9890   while (curr && (!curr->acc.access.isRead || (curr->sym != sym))) curr = curr->prev;
9891
9892   return curr;
9893 }
9894 #endif
9895
9896 /* Return the defmap entry for sym AT pc. 
9897  * If none is found, NULL is returned.
9898  * If more than one entry is found an assertion is triggered. */
9899 static defmap_t *defmapCurr (defmap_t *map, symbol_t sym, pCode *pc) {
9900   defmap_t *res = NULL;
9901
9902   /* find entries for pc */
9903   while (map && map->pc != pc) map = map->next;
9904
9905   /* find first entry for sym @ pc */
9906   while (map && map->pc == pc && map->sym != sym) map = map->next;
9907
9908   /* no entry found */
9909   if (!map) return NULL;
9910
9911   /* check for more entries */
9912   res = map;
9913   map = map->next;
9914   while (map && map->pc == pc) {
9915     /* more than one entry for sym @ pc found? */
9916     assert (map->sym != sym);
9917     map = map->next;
9918   }
9919
9920   /* return single entry for sym @ pc */
9921   return res;
9922 }
9923
9924 /* Modifies the definition of sym at pCode to newval.
9925  * Returns 0 on success, 1 if no definition of sym in pc has been found.
9926  */
9927 static int defmapUpdate (defmap_t *map, symbol_t sym, pCode *pc, valnum_t newval) {
9928   defmap_t *m  = map;
9929
9930   /* find definitions of pc */
9931   while (m && m->pc != pc) m = m->next;
9932
9933   /* find definition of sym at pc */
9934   while (m && m->pc == pc && (!m->acc.access.isWrite || (m->sym != sym))) m = m->next;
9935   
9936   /* no definition found */
9937   if (!m) return 1;
9938
9939   /* redefine */
9940   m->val = newval;
9941
9942   /* update following uses of sym */
9943   while (m && m->pc == pc) m = m->prev;
9944   while (m) {
9945     if (m->sym == sym) {
9946       m->in_val = newval;
9947       if (m->acc.access.isWrite) m = NULL;
9948     } // if
9949     if (m) m = m->prev;
9950   } // while
9951   
9952   return 0;
9953 }
9954
9955 /* ======================================================================== */
9956 /* === STACK ROUTINES ===================================================== */
9957 /* ======================================================================== */
9958
9959 typedef struct stack_s {
9960   void *data;
9961   struct stack_s *next;
9962 } stackitem_t;
9963
9964 typedef stackitem_t *dynstack_t;
9965 static stackitem_t *free_stackitems = NULL;
9966
9967 /* Create a stack with one item. */
9968 static dynstack_t *newStack () {
9969   dynstack_t *s = (dynstack_t *) Safe_malloc (sizeof (dynstack_t));
9970   *s = NULL;
9971   return s;
9972 }
9973
9974 /* Remove a stack -- its items are only marked free. */
9975 static void deleteStack (dynstack_t *s) {
9976   stackitem_t *i;
9977
9978   while (*s) {
9979     i = *s;
9980     *s = (*s)->next;
9981     i->next = free_stackitems;
9982     free_stackitems = i;
9983   } // while
9984   Safe_free (s);
9985 }
9986
9987 /* Release all stackitems. */
9988 static void releaseStack () {
9989   stackitem_t *i;
9990   
9991   while (free_stackitems) {
9992     i = free_stackitems->next;
9993     Safe_free(free_stackitems);
9994     free_stackitems = i;
9995   } // while
9996 }
9997
9998 static void stackPush (dynstack_t *stack, void *data) {
9999   stackitem_t *i;
10000   
10001   if (free_stackitems) {
10002     i = free_stackitems;
10003     free_stackitems = free_stackitems->next;
10004   } else {
10005     i = (stackitem_t *) Safe_calloc (1, sizeof (stackitem_t));
10006   }
10007   i->data = data;
10008   i->next = *stack;
10009   *stack = i;
10010 }
10011
10012 static void *stackPop (dynstack_t *stack) {
10013   void *data;
10014   stackitem_t *i;
10015   
10016   if (stack && *stack) {
10017     data = (*stack)->data;
10018     i = *stack;
10019     *stack = (*stack)->next;
10020     i->next = free_stackitems;
10021     free_stackitems = i;
10022     return data;
10023   } else {
10024     return NULL;
10025   }
10026 }
10027
10028 #if 0
10029 static int stackContains (dynstack_t *s, void *data) {
10030   stackitem_t *i;
10031   if (!s) return 0;
10032   i = *s;
10033   while (i) {
10034     if (i->data == data) return 1;
10035     i = i->next;
10036   } // while
10037
10038   /* not found */
10039   return 0;
10040 }
10041 #endif
10042
10043 static int stackIsEmpty (dynstack_t *s) {
10044   return (*s == NULL);
10045 }
10046
10047
10048 typedef struct {
10049   pCodeFlow *flow;
10050   defmap_t *lastdef;
10051 } state_t;
10052
10053 static state_t *newState (pCodeFlow *flow, defmap_t *lastdef) {
10054   state_t *s = (state_t *) Safe_calloc (1, sizeof (state_t));
10055   s->flow = flow;
10056   s->lastdef = lastdef;
10057   return s;
10058 }
10059
10060 static void deleteState (state_t *s) {
10061   Safe_free (s);
10062 }
10063
10064 static int stateIsNew (state_t *state, dynstack_t *todo, dynstack_t *done) {
10065   stackitem_t *i;
10066
10067   /* scan working list for state */
10068   if (todo) {
10069     i = *todo;
10070     while (i) {
10071       /* is i == state? -- state not new */
10072       if ((((state_t *) (i->data))->flow == state->flow) && (((state_t *) (i->data))->lastdef == state->lastdef)) return 0;
10073       i = i->next;
10074     } // while
10075   }
10076
10077   if (done) {
10078     i = *done;
10079     while (i) {
10080       /* is i == state? -- state not new */
10081       if ((((state_t *) (i->data))->flow == state->flow) && (((state_t *) (i->data))->lastdef == state->lastdef)) return 0;
10082       i = i->next;
10083     } // while
10084   }
10085
10086   /* not found -- state is new */
10087   return 1;
10088 }
10089
10090 static inline valnum_t newValnum ();
10091
10092 const char *pic16_pBlockGetFunctionName (pBlock *pb) {
10093   pCode *pc;
10094
10095   if (!pb) return "<unknown function>";
10096
10097   pc = pic16_findNextpCode (pb->pcHead, PC_FUNCTION);
10098   if (pc && isPCF(pc)) return PCF(pc)->fname;
10099   else return "<unknown function>";
10100 }
10101
10102 static defmap_t *pic16_pBlockAddInval (pBlock *pb, symbol_t sym) {
10103   defmap_t *map;
10104   pCodeFlow *pcfl;
10105
10106   pcfl = PCI(pic16_findNextInstruction (pb->pcHead))->pcflow;
10107
10108   /* find initial value (assigning pc == NULL) */
10109   map = PCFL(pcfl)->in_vals;
10110   while (map && map->sym != sym) map = map->next;
10111
10112   /* initial value already present? */
10113   if (map) {
10114     //fprintf (stderr, "found init value for sym %s (%x): %u\n", strFromSym(sym), sym, map->val);
10115     return map;
10116   }
10117
10118   /* create a new initial value */
10119   map = newDefmap (sym, 0x00, 0xff, 0, 1, NULL, newValnum(), PCFL(pcfl)->in_vals);
10120   PCFL(pcfl)->in_vals = map;
10121   //fprintf (stderr, "Created init value for sym %s (%x): %u\n", strFromSym(sym), sym, map->val);
10122   return map;
10123
10124 #if 0
10125   /* insert map as last item in pcfl's defmap */
10126   if (!prev) prev = PCFL(pcfl)->defmap;
10127   if (!prev) {
10128     PCFL(pcfl)->defmap = map;
10129   } else {
10130     while (prev->next) prev = prev->next;
10131     prev->next = map;
10132     map->prev = prev;
10133   }
10134
10135   return map;
10136 #endif
10137 }
10138
10139 /* Find all reaching definitions for sym at pc. 
10140  * A new (!) list of definitions is returned.
10141  * Returns the number of reaching definitions found.
10142  * The defining defmap entries are returned in *chain.
10143  */
10144 static int defmapFindAll (symbol_t sym, pCode *pc, defmap_t **chain) {
10145   defmap_t *map;
10146   defmap_t *res;
10147
10148   pCodeFlow *curr;
10149   pCodeFlowLink *succ;
10150   state_t *state;
10151   dynstack_t *todo;     /** stack of state_t */
10152   dynstack_t *done;     /** stack of state_t */
10153
10154   int firstState, n_defs;
10155   
10156   assert (pc && isPCI(pc) && PCI(pc)->pcflow);
10157   assert (chain);
10158
10159   /* initialize return list */
10160   *chain = NULL;
10161
10162   /* wildcard symbol? */
10163   if (!sym) return 0;
10164   
10165   //fprintf (stderr, "Searching definition of sym %s(%x) @ pc %p(%p)\n", strFromSym(sym), sym, pc, pc->pb);
10166   
10167   map = PCI(pc)->pcflow->defmap;
10168
10169   res = defmapFindDef (map, sym, pc);
10170   //if (res) fprintf (stderr, "found def in own flow @ pc %p\n", res->pc);
10171
10172 #define USE_PRECALCED_INVALS 1
10173 #if USE_PRECALCED_INVALS
10174   if (!res && PCI(pc)->pcflow->in_vals) {
10175     res = defmapFindDef (PCI(pc)->pcflow->in_vals, sym, NULL);
10176     if (res) {
10177       //fprintf  (stderr, "found def in init values\n");
10178       df_findall_in_vals++;
10179     }
10180   }
10181 #endif
10182
10183   if (res) {
10184     // found a single definition (in pc's flow)
10185     //fprintf (stderr, "unique definition for %s @ %p found @ %p (val: %x)\n", strFromSym(sym), pc, res->pc, res->val);
10186     defmapAddCopyIfNew (chain, res);
10187     df_findall_sameflow++;
10188     return 1;
10189   }
10190
10191 #if USE_PRECALCED_INVALS
10192   else {
10193     defmapAddCopyIfNew (chain, pic16_pBlockAddInval (pc->pb, sym));
10194     return 1;
10195   }
10196
10197 #endif
10198   
10199 #define FORWARD_FLOW_ANALYSIS 1
10200 #if defined FORWARD_FLOW_ANALYSIS && FORWARD_FLOW_ANALYSIS
10201   /* no definition found in pc's flow preceeding pc */
10202   todo = newStack ();
10203   done = newStack ();
10204   n_defs = 0; firstState = 1;
10205   stackPush (todo, newState (PCI(pic16_findNextInstruction(pc->pb->pcHead))->pcflow, res));
10206
10207   while (!stackIsEmpty (todo)) {
10208     state = (state_t *) stackPop (todo);
10209     stackPush (done, state);
10210     curr = state->flow;
10211     res = state->lastdef;
10212     //fprintf (stderr, "searching def of sym %s in pcFlow %p (lastdef %x @ %p)\n", strFromSym(sym), curr, res ? res->val : 0, res ? res->pc : NULL);
10213
10214     /* there are no definitions BEFORE pc in pc's flow (see above) */
10215     if (curr == PCI(pc)->pcflow) {
10216       if (!res) {
10217         //fprintf (stderr, "symbol %s(%x) might be used uninitialized at %p\n", strFromSym(sym), sym, pc);
10218         res = pic16_pBlockAddInval (pc->pb, sym);
10219         if (defmapAddCopyIfNew (chain, res)) n_defs++;
10220         res = NULL;
10221       } else {
10222         //fprintf (stderr, "reaching definition for %s @ %p found @ %p (val: %x)\n", strFromSym(sym), pc, res->pc, res->val);
10223         if (defmapAddCopyIfNew (chain, res)) n_defs++;
10224       }
10225     }
10226
10227     /* save last definition of sym in this flow as initial def in successors */
10228     res = defmapFindDef (curr->defmap, sym, NULL);
10229     if (!res) res = state->lastdef;
10230     
10231     /* add successors to working list */
10232     state = newState (NULL, NULL);
10233     succ = (pCodeFlowLink *) setFirstItem (curr->to);
10234     while (succ) {
10235       //fprintf (stderr, "  %p --> %p with %x\n", curr, succ->pcflow, res ? res->val : 0);
10236       state->flow = succ->pcflow;
10237       state->lastdef = res;
10238       if (stateIsNew (state, todo, done)) {
10239         stackPush (todo, state);
10240         state = newState (NULL, NULL);
10241       } // if
10242       succ = (pCodeFlowLink *) setNextItem (curr->to);
10243     } // while
10244     deleteState (state);
10245   } // while
10246
10247 #else // !FORWARD_FLOW_ANALYSIS 
10248
10249   /* no definition found in pc's flow preceeding pc */
10250   todo = newStack ();
10251   done = newStack ();
10252   n_defs = 0; firstState = 1;
10253   stackPush (todo, newState (PCI(pc)->pcflow, res));
10254
10255   while (!stackIsEmpty (todo)) {
10256     state = (state_t *) stackPop (todo);
10257     curr = state->flow;
10258
10259     if (firstState) {
10260       firstState = 0;
10261       /* only check predecessor flows */
10262     } else {
10263       /* get (last) definition of sym in this flow */
10264       res = defmapFindDef (curr->defmap, sym, NULL);
10265     }
10266
10267     if (res) {
10268       /* definition found */
10269       //fprintf (stderr, "reaching definition for %s @ %p found @ %p (val: %x)\n", strFromSym(sym), pc, res->pc, res->val);
10270       if (defmapAddCopyIfNew (chain, res)) n_defs++;
10271     } else {
10272       /* no definition found -- check predecessor flows */
10273       state = newState (NULL, NULL);
10274       succ = (pCodeFlowLink *) setFirstItem (curr->from);
10275
10276       /* if no flow predecessor available -- sym might be uninitialized */
10277       if (!succ) {
10278         //fprintf (stder, "sym %s might be used uninitialized at %p\n", strFromSym (sym), pc);
10279         res = newDefmap (sym, 0xff, 0, 1, NULL, 0, *chain);
10280         if (defmapAddCopyIfNew (chain, res)) n_defs++;
10281         deleteDefmap (res); res = NULL;
10282       }
10283       
10284       while (succ) {
10285         //fprintf (stderr, "  %p --> %p with %x\n", curr, succ->pcflow, res ? res->val : 0);
10286         state->flow = succ->pcflow;
10287         state->lastdef = res;
10288         if (stateIsNew (state, todo, done)) {
10289           stackPush (todo, state);
10290           state = newState (NULL, NULL);
10291         } // if
10292         succ = (pCodeFlowLink *) setNextItem (curr->from);
10293       } // while
10294       deleteState (state);
10295     }
10296   } // while
10297
10298 #endif
10299
10300   /* clean up done stack */
10301   while (!stackIsEmpty(done)) {
10302     deleteState ((state_t *) stackPop (done));
10303   } // while
10304   deleteStack (done);
10305
10306   /* return number of items in result set */
10307   if (n_defs == 0) {
10308     //fprintf (stderr, "sym %s might be used uninitialized at %p\n", strFromSym (sym), pc);
10309   } else if (n_defs == 1) {
10310     assert (*chain);
10311     //fprintf (stderr, "sym %s at %p always defined as %x @ %p\n", strFromSym(sym), pc, (*chain)->val, (*chain)->pc);
10312   } else if (n_defs > 0) {
10313     //fprintf (stderr, "%u definitions for sym %s at %p found:\n", n_defs, strFromSym(sym), pc);
10314 #if 0
10315     res = *chain;
10316     while (res) {
10317       fprintf (stderr, "  as %4x @ %p\n", res->val, res->pc);
10318       res = res->next;
10319     } // while
10320 #endif
10321   }
10322   //fprintf (stderr, "%u definitions for sym %s at %p found\n", n_defs, strFromSym(sym), pc);
10323   df_findall_otherflow++;
10324   return n_defs;
10325 }
10326
10327 /* ======================================================================== */
10328 /* === VALUE NUMBER HANDLING ============================================== */
10329 /* ======================================================================== */
10330
10331 static valnum_t nextValnum = 0x1000;
10332 static hTab *map_symToValnum = NULL;
10333
10334 /** Return a new value number. */
10335 static inline valnum_t newValnum () {
10336   return (nextValnum += 4);
10337 }
10338
10339 static valnum_t valnumFromStr (const char *str) {
10340   symbol_t sym;
10341   valnum_t val;
10342   void *res;
10343   
10344   sym = symFromStr (str);
10345
10346   if (!map_symToValnum) {
10347     map_symToValnum = newHashTable (128);
10348   } // if
10349
10350   /* literal already known? */
10351   res = hTabFindByKey (map_symToValnum, sym % map_symToValnum->size, INT_TO_PTR(sym), &ptrcmp);
10352
10353   /* return existing valnum */
10354   if (res) return (valnum_t) PTR_TO_INT(res);
10355   
10356   /* create new valnum */
10357   val = newValnum();
10358   hTabAddItemLong (&map_symToValnum, sym % map_symToValnum->size, INT_TO_PTR(sym), INT_TO_PTR(val));
10359   //fprintf (stderr, "NEW VALNUM %x for symbol %s\n", val, str);
10360   return val;
10361 }
10362
10363 /* Create a valnum for a literal. */
10364 static valnum_t valnumFromLit (unsigned int lit) {
10365   return ((valnum_t) 0x100 + (lit & 0x0FF));
10366 }
10367
10368 /* Return the (positive) literal value represented by val
10369  * or -1 iff val is no known literal's valnum. */
10370 static int litFromValnum (valnum_t val) {
10371   if (val >= 0x100 && val < 0x200) {
10372     /* valnum is a (known) literal */
10373     return val & 0x00FF;
10374   } else {
10375     /* valnum is not a known literal */
10376     return -1;
10377   }
10378 }
10379
10380 #if 0
10381 /* Sanity check - all flows in a block must be reachable from initial flow. */
10382 static int verifyAllFlowsReachable (pBlock *pb) {
10383   set *reached;
10384   set *flowInBlock;
10385   set *checked;
10386   pCode *pc;
10387   pCodeFlow *pcfl;
10388   pCodeFlowLink *succ;
10389   int res;
10390
10391   //fprintf (stderr, "%s - started for %s.\n" ,__FUNCTION__, pic16_pBlockGetFunctionName (pb));
10392
10393   reached = NULL;
10394   flowInBlock = NULL;
10395   checked = NULL;
10396   /* mark initial flow as reached (and "not needs to be reached") */
10397   pc = pic16_findNextpCode (pb->pcHead, PC_FLOW);
10398   assert (pc);
10399   addSetHead (&reached, pc);
10400   addSetHead (&checked, pc);
10401   
10402   /* mark all further flows in block as "need to be reached" */
10403   pc = pb->pcHead;
10404   do {
10405     if (isPCI(pc)) addSetIfnotP (&flowInBlock, PCI(pc)->pcflow);
10406     pc = pic16_findNextInstruction (pc->next);
10407   } while (pc);
10408
10409   while (reached && (pcfl = (pCodeFlow *)indexSet (reached, 0)) != NULL) {
10410     /* mark as reached and "not need to be reached" */
10411     deleteSetItem (&reached, pcfl);
10412     //fprintf (stderr, "%s - checking %p\n" ,__FUNCTION__, pcfl);
10413     
10414     /* flow is no longer considered unreachable */
10415     deleteSetItem (&flowInBlock, pcfl);
10416
10417     for (succ = setFirstItem (pcfl->to); succ; succ = setNextItem (pcfl->to)) {
10418       if (!isinSet (checked, succ->pcflow)) {
10419         /* flow has never been reached before */
10420         addSetHead (&reached, succ->pcflow);
10421         addSetHead (&checked, succ->pcflow);
10422       } // if
10423     } // for succ
10424   } // while
10425
10426   //fprintf (stderr, "%s - finished\n", __FUNCTION__);
10427
10428   /* by now every flow should have been reached
10429    * --> flowInBlock should be empty */
10430   res = (flowInBlock == NULL);
10431
10432 #if 1
10433   if (flowInBlock) {
10434           fprintf (stderr, "not all flows reached in %s:\n", pic16_pBlockGetFunctionName (pb));
10435     while (flowInBlock) {
10436       pcfl = indexSet (flowInBlock, 0);
10437       fprintf (stderr, "not reached: flow %p\n", pcfl);
10438       deleteSetItem (&flowInBlock, pcfl);
10439     } // while
10440   }
10441 #endif
10442   
10443   /* clean up */
10444   deleteSet (&reached);
10445   deleteSet (&flowInBlock);
10446   deleteSet (&checked);
10447   
10448   /* if we reached every flow, succ is NULL by now... */
10449   //assert (res); // will fire on unreachable code...
10450   return (res);
10451 }
10452 #endif
10453
10454 /* Checks a flow for accesses to sym AFTER pc.
10455  * 
10456  * Returns -1 if the symbol is read in this flow (before redefinition),
10457  * returns 0 if the symbol is redefined in this flow or
10458  * returns a mask [0x01 -- 0xFF] indicating the bits still alive after this flow.
10459  */
10460 int pic16_isAliveInFlow (symbol_t sym, int mask, pCodeFlow *pcfl, pCode *pc) {
10461   defmap_t *map, *mappc;
10462
10463   /* find pc or start of definitions */
10464   map = pcfl->defmap;
10465   while (map && (map->pc != pc) && map->next) map = map->next;
10466   /* if we found pc -- ignore it */
10467   while (map && map->pc == pc) map = map->prev;
10468
10469   /* scan list backwards (first definition first) */
10470   while (map && mask) {
10471 //    if (map->sym == sym) {
10472       //fprintf (stderr, "%s: accessing sym %s in pc %p/map %p\n", __FUNCTION__, strFromSym(sym), map->pc, map);
10473       mappc = map;
10474       /* scan list for reads at this pc first */
10475       while (map && map->pc == mappc->pc) {
10476         /* is the symbol (partially) read? */
10477         if ((map->sym == sym) && (map->acc.access.isRead && ((map->acc.access.in_mask & mask) != 0))) {
10478           //if (sym != SPO_STATUS) fprintf (stderr, "%s: symbol %s read at pc %p\n", __FUNCTION__, strFromSym (sym), map->pc);
10479           return -1;
10480         }
10481         map = map->prev;
10482       } // while
10483       map = mappc;
10484
10485       while (map && map->pc == mappc->pc) {
10486         /* honor (partial) redefinitions of sym */
10487         if ((map->sym == sym) && (map->acc.access.isWrite)) {
10488           mask &= ~map->acc.access.mask;
10489           //if (sym != SPO_STATUS) fprintf (stderr, "%s: symbol %s redefined at pc %p, alive mask: %x\n", __FUNCTION__, strFromSym (sym), map->pc, mask);
10490         }
10491         map = map->prev;
10492       } // while
10493 //    } // if
10494     /* map already points to the first defmap for the next pCode */
10495     //map = mappc->prev;
10496   } // while
10497
10498   /* the symbol is not completely redefined in this flow and not accessed -- symbol
10499    * is still alive; return the appropriate mask of alive bits */
10500   return mask;
10501 }
10502
10503 /* Check whether a symbol is alive (AFTER pc). */
10504 static int pic16_isAlive (symbol_t sym, pCode *pc) {
10505   int mask, visit;
10506   defmap_t *map;
10507   dynstack_t *todo, *done;
10508   state_t *state;
10509   pCodeFlow *pcfl;
10510   pCodeFlowLink *succ;
10511
10512   mask = 0x00ff;
10513   
10514   assert (isPCI(pc));
10515   pcfl = PCI(pc)->pcflow;
10516   map = pcfl->defmap;
10517
10518   todo = newStack ();
10519   done = newStack ();
10520   
10521   state = newState (pcfl, (defmap_t *) INT_TO_PTR(mask));
10522   stackPush (todo, state);
10523   visit = 0;
10524   
10525   while (!stackIsEmpty (todo)) {
10526     state = (state_t *) stackPop (todo);
10527     pcfl = state->flow;
10528     mask = PTR_TO_INT(state->lastdef);
10529     if (visit) stackPush (done, state); else deleteState(state);
10530     //fprintf (stderr, "%s: checking flow %p for symbol %s (%x)/%x\n", __FUNCTION__, pcfl, strFromSym(sym), sym, mask);
10531     // make sure flows like A(i1,i2,pc,i3,...) --> A with pc reading and writing sym are handled correctly!
10532     mask = pic16_isAliveInFlow (sym, mask, pcfl, visit == 0 ? pc : NULL);
10533     visit++;
10534
10535     /* symbol is redefined in flow before use -- not alive in this flow (maybe in others?) */
10536     if (mask == 0) continue;
10537
10538     /* symbol is (partially) read before redefinition in flow */
10539     if (mask == -1) break;
10540
10541     /* symbol is neither read nor completely redefined -- check successor flows */
10542     for (succ = setFirstItem(pcfl->to); succ; succ = setNextItem (pcfl->to)) {
10543       state = newState (succ->pcflow, (defmap_t *) INT_TO_PTR(mask));
10544       if (stateIsNew (state, todo, done)) {
10545         stackPush (todo, state);
10546       } else {
10547         deleteState (state);
10548       }
10549     } // for
10550   } // while
10551
10552   while (!stackIsEmpty (todo)) deleteState ((state_t *) stackPop (todo));
10553   while (!stackIsEmpty (done)) deleteState ((state_t *) stackPop (done));
10554
10555   /* symbol is read in at least one flow -- is alive */
10556   if (mask == -1) return 1;
10557
10558   /* symbol is read in no flow */
10559   return 0;
10560 }
10561
10562 /* Returns whether access to the given symbol has side effects. */
10563 static int pic16_symIsSpecial (symbol_t sym) {
10564   //fprintf (stderr, "%s: sym=%x\n", __FUNCTION__, sym);
10565   switch (sym) {
10566   case SPO_INDF0:
10567   case SPO_PLUSW0:
10568   case SPO_POSTINC0:
10569   case SPO_POSTDEC0:
10570   case SPO_PREINC0:
10571   case SPO_INDF1:
10572   case SPO_PLUSW1:
10573   case SPO_POSTINC1:
10574   case SPO_POSTDEC1:
10575   case SPO_PREINC1:
10576   case SPO_INDF2:
10577   case SPO_PLUSW2:
10578   case SPO_POSTINC2:
10579   case SPO_POSTDEC2:
10580   case SPO_PREINC2:
10581   case SPO_PCL:
10582           return 1;
10583   default:
10584           /* no special effects known */
10585           return 0;
10586   } // switch
10587
10588   return 0;
10589 }
10590
10591 /* Check whether a register should be considered local (to the current function) or not. */
10592 static int pic16_regIsLocal (regs *r) {
10593   symbol_t sym;
10594   if (r) {
10595     if (r->type == REG_TMP) return 1;
10596
10597     sym = symFromStr (r->name);
10598     switch (sym) {
10599     case SPO_WREG:
10600     case SPO_FSR0L: // used in ptrget/ptrput
10601     case SPO_FSR0H: // ... as well
10602     case SPO_FSR1L: // used as stack pointer... (so not really local but shared among function calls)
10603     case SPO_FSR1H: // ... as well
10604     case SPO_FSR2L: // used as frame pointer
10605     case SPO_FSR2H: // ... as well
10606     case SPO_PRODL: // used to return values from functions
10607     case SPO_PRODH: // ... as well
10608       /* these registers (and some more...) are considered local */
10609       return 1;
10610       break;
10611     default:
10612       /* for unknown regs: check is marked local, leave if not */
10613       if (r->isLocal) {
10614         return 1;
10615       } else {
10616         //fprintf (stderr, "%s: non-local reg used: %s\n", __FUNCTION__, r->name);
10617         return 0;
10618       }
10619     } // switch
10620   } // if
10621
10622   /* if in doubt, assume non-local... */
10623   return 0;
10624 }
10625
10626 /* Check all symbols touched by pc whether their newly assigned values are read.
10627  * Returns 0 if no symbol is used later on, 1 otherwise. */
10628 static int pic16_pCodeIsAlive (pCode *pc) {
10629   pCodeInstruction *pci;
10630   defmap_t *map, *lastpc;
10631   regs *checkreg;
10632   
10633   /* we can only handle PCIs */
10634   if (!isPCI(pc)) return 1;
10635
10636   //pc->print (stderr, pc);
10637
10638   pci = PCI(pc);
10639   assert (pci && pci->pcflow && pci->pcflow->defmap);
10640
10641   /* NEVER remove instructions with implicit side effects */
10642   switch (pci->op) {
10643   case POC_TBLRD:
10644   case POC_TBLRD_POSTINC:       /* modify TBLPTRx */
10645   case POC_TBLRD_POSTDEC:
10646   case POC_TBLRD_PREINC:
10647   case POC_TBLWT:               /* modify program memory */
10648   case POC_TBLWT_POSTINC:       /* modify TBLPTRx */
10649   case POC_TBLWT_POSTDEC:
10650   case POC_TBLWT_PREINC:
10651   case POC_CLRWDT:              /* clear watchdog timer */
10652   case POC_PUSH:                /* should be safe to remove though... */
10653   case POC_POP:                 /* should be safe to remove though... */
10654   case POC_CALL:
10655   case POC_RCALL:
10656   case POC_RETFIE:
10657   case POC_RETURN:
10658     //fprintf (stderr, "%s: instruction with implicit side effects not removed: %s\n", __FUNCTION__, pci->mnemonic);
10659     return 1;
10660
10661   default:
10662     /* no special instruction */
10663     break;
10664   } // switch
10665
10666   /* prevent us from removing assignments to non-local variables */
10667   checkreg = NULL;
10668   if (PCI(pc)->outCond & PCC_REGISTER) checkreg = pic16_getRegFromInstruction (pc);
10669   else if (PCI(pc)->outCond & PCC_REGISTER2) checkreg =  pic16_getRegFromInstruction2(pc);
10670
10671   if ((PCI(pc)->outCond & (PCC_REGISTER | PCC_REGISTER2)) && !checkreg) {
10672     /* assignment to DIRECT operand like "BSF (_global + 1),6" */
10673     //fprintf (stderr, "%s: assignment to register detected, but register not available!\n", __FUNCTION__);
10674     //pc->print (stderr, pc);
10675     return 1;
10676   }
10677   if ((PCI(pc)->outCond & (PCC_REGISTER | PCC_REGISTER2)) && !pic16_regIsLocal (checkreg)) {
10678     //fprintf (stderr, "%s: dest-reg not local %s\n", __FUNCTION__, checkreg ? checkreg->name : "<unknown>");
10679     return 1;
10680   }
10681   
10682 #if 1
10683   /* OVERKILL: prevent us from removing reads from non-local variables 
10684    * THIS IS HERE TO AVOID PROBLEMS WITH VOLATILE OPERANDS ONLY! 
10685    * Once registers get a "isVolatile" field this might be handled more efficiently... */
10686   checkreg = NULL;
10687   if (PCI(pc)->inCond & PCC_REGISTER) checkreg = pic16_getRegFromInstruction (pc);
10688   else if (PCI(pc)->inCond & PCC_REGISTER2) checkreg =  pic16_getRegFromInstruction2(pc);
10689
10690   if ((PCI(pc)->inCond & (PCC_REGISTER | PCC_REGISTER2)) && !checkreg) {
10691     /* read from DIRECT operand like "BTFSS (_global + 1),6" -- might be volatile */
10692     //fprintf (stderr, "%s: read from register detected, but register not available!\n", __FUNCTION__);
10693     //pc->print (stderr, pc);
10694     return 1;
10695   }
10696   if ((PCI(pc)->inCond & (PCC_REGISTER | PCC_REGISTER2)) && !pic16_regIsLocal (checkreg)) {
10697     //fprintf (stderr, "%s: src-reg not local: %s\n", __FUNCTION__, checkreg ? checkreg->name : "<unknown>");
10698     return 1;
10699   }
10700 #endif
10701   
10702   /* now check that the defined symbols are not used */
10703   map = pci->pcflow->defmap;
10704   
10705   /* find items for pc */
10706   while (map && map->pc != pc) map = map->next;
10707
10708   /* no entries found? something is fishy with DF analysis... -- play safe */
10709   if (!map) {
10710     if (pic16_pcode_verbose) {
10711       fprintf (stderr, "%s: defmap not found\n", __FUNCTION__);
10712     }
10713     return 1;
10714   }
10715
10716   /* remember first item assigned to pc for later use */
10717   lastpc = map;
10718   
10719   /* check all symbols being modified by pc */
10720   while (map && map->pc == pc) {
10721     if (map->sym == 0) { map = map->next; continue; }
10722
10723     /* keep pc if it references special symbols (like POSTDEC0) */
10724 #if 0
10725     {
10726       char buf[256];
10727       pic16_pCode2str (buf, 256, pc);
10728       fprintf (stderr, "%s: checking for sym %x(%s) at pc %p (%s)\n", __FUNCTION__, map->sym, strFromSym (map->sym), pc, buf);
10729     }
10730 #endif
10731     if (pic16_symIsSpecial (map->sym)) {
10732       //fprintf (stderr, "%s: special sym\n", __FUNCTION__);
10733       return 1;
10734     }
10735     if (map->acc.access.isWrite) {
10736       if (pic16_isAlive (map->sym, pc)) {
10737         //fprintf (stderr, "%s(%s): pCode is alive (sym %s still used)\n", __FUNCTION__, pic16_pBlockGetFunctionName (pc->pb),strFromSym (map->sym));
10738         return 1;
10739       }
10740     }
10741     map = map->next;
10742   } // while
10743
10744   /* no use for any of the pc-assigned symbols found -- pCode is dead and can be removed */
10745 #if 0
10746   {
10747     char buf[256];
10748     pic16_pCode2str (buf, 256, pc);
10749     fprintf (stderr, "%s: pCode %p (%s) is dead.\n", __FUNCTION__, pc, buf);
10750   }
10751 #endif
10752   return 0;
10753 }
10754
10755 /* Adds implied operands to the list.
10756  * sym - operand being accessed in the pCode
10757  * list - list to append the operand
10758  * isRead - set to 1 iff sym is read in pCode
10759  * listRead - set to 1 iff all operands being read are to be listed
10760  *
10761  * Returns 0 for "normal" operands, 1 for special operands.
10762  */
10763 static int fixupSpecialOperands (symbol_t sym, int in_mask, int mask, pCode *pc, valnum_t val, defmap_t **list, int isRead, int isWrite) {
10764   /* check whether accessing REG accesses other REGs as well */
10765   switch (sym) {
10766   case SPO_INDF0:
10767     /* reads FSR0x */
10768     *list = newDefmap (sym, 0xff, 0xff, 0, 0, pc, 0, *list);
10769     *list = newDefmap (SPO_FSR0L, 0xff, 0xff, 1, 0, pc, 0, *list);
10770     *list = newDefmap (SPO_FSR0H, 0xff, 0xff, 1, 0, pc, 0, *list);
10771     break;
10772     
10773   case SPO_PLUSW0:
10774     /* reads FSR0x and WREG */
10775     *list = newDefmap (SPO_WREG, 0xff, 0x00, 1, 0, pc, 0, *list);
10776     *list = newDefmap (sym, 0xff, 0xff, 0, 0, pc, 0, *list);
10777     *list = newDefmap (SPO_FSR0L, 0xff, 0xff, 1, 0, pc, 0, *list);
10778     *list = newDefmap (SPO_FSR0H, 0xff, 0xff, 1, 0, pc, 0, *list);
10779     break;
10780     
10781   case SPO_POSTDEC0:
10782   case SPO_POSTINC0:
10783   case SPO_PREINC0:
10784     /* reads/modifies FSR0x */
10785     *list = newDefmap (sym, 0xff, 0xff, 0, 0, pc, 0, *list);
10786     *list = newDefmap (SPO_FSR0L, 0xff, 0xff, 1, 1, pc, newValnum (), *list);
10787     *list = newDefmap (SPO_FSR0H, 0xff, 0xff, 1, 1, pc, newValnum (), *list);
10788     break;
10789
10790   case SPO_INDF1:
10791     /* reads FSR1x */
10792     *list = newDefmap (sym, 0xff, 0xff, 0, 0, pc, 0, *list);
10793     *list = newDefmap (SPO_FSR1L, 0xff, 0xff, 1, 0, pc, 0, *list);
10794     *list = newDefmap (SPO_FSR1H, 0xff, 0xff, 1, 0, pc, 0, *list);
10795     break;
10796     
10797   case SPO_PLUSW1:
10798     /* reads FSR1x and WREG */
10799     *list = newDefmap (SPO_WREG, 0xff, 0x00, 1, 0, pc, 0, *list);
10800     *list = newDefmap (sym, 0xff, 0xff, 0, 0, pc, 0, *list);
10801     *list = newDefmap (SPO_FSR1L, 0xff, 0xff, 1, 0, pc, 0, *list);
10802     *list = newDefmap (SPO_FSR1H, 0xff, 0xff, 1, 0, pc, 0, *list);
10803     break;
10804     
10805   case SPO_POSTDEC1:
10806   case SPO_POSTINC1:
10807   case SPO_PREINC1:
10808     /* reads/modifies FSR1x */
10809     *list = newDefmap (sym, 0xff, 0xff, 0, 0, pc, 0, *list);
10810     *list = newDefmap (SPO_FSR1L, 0xff, 0xff, 1, 1, pc, newValnum (), *list);
10811     *list = newDefmap (SPO_FSR1H, 0xff, 0xff, 1, 1, pc, newValnum (), *list);
10812     break;
10813
10814   case SPO_INDF2:
10815     /* reads FSR2x */
10816     *list = newDefmap (sym, 0xff, 0xff, 0, 0, pc, 0, *list);
10817     *list = newDefmap (SPO_FSR2L, 0xff, 0xff, 1, 0, pc, 0, *list);
10818     *list = newDefmap (SPO_FSR2H, 0xff, 0xff, 1, 0, pc, 0, *list);
10819     break;
10820     
10821   case SPO_PLUSW2:
10822     /* reads FSR2x and WREG */
10823     *list = newDefmap (SPO_WREG, 0xff, 0x00, 1, 0, pc, 0, *list);
10824     *list = newDefmap (sym, 0xff, 0xff, 0, 0, pc, 0, *list);
10825     *list = newDefmap (SPO_FSR2L, 0xff, 0xff, 1, 0, pc, 0, *list);
10826     *list = newDefmap (SPO_FSR2H, 0xff, 0xff, 1, 0, pc, 0, *list);
10827     break;
10828     
10829   case SPO_POSTDEC2:
10830   case SPO_POSTINC2:
10831   case SPO_PREINC2:
10832     /* reads/modifies FSR2x */
10833     *list = newDefmap (sym, 0xff, 0xff, 0, 0, pc, 0, *list);
10834     *list = newDefmap (SPO_FSR2L, 0xff, 0xff, 1, 1, pc, newValnum (), *list);
10835     *list = newDefmap (SPO_FSR2H, 0xff, 0xff, 1, 1, pc, newValnum (), *list);
10836     break;
10837
10838   case SPO_PCL:
10839     /* modifies PCLATH and PCLATU */
10840     *list = newDefmap (SPO_PCL, 0xff, 0xff, isRead, isWrite, pc, newValnum (), *list);
10841     if (isRead) {
10842       /* reading PCL updates PCLATx */
10843       *list = newDefmap (SPO_PCLATH, 0xff, 0xff, 0, 1, pc, newValnum (), *list);
10844       *list = newDefmap (SPO_PCLATU, 0xff, 0xff, 0, 1, pc, newValnum (), *list);
10845     }
10846     if (isWrite) {
10847       /* writing PCL implicitly reads PCLATx (computed GOTO) */
10848       *list = newDefmap (SPO_PCLATH, 0xff, 0xff, 1, 0, pc, 0, *list);
10849       *list = newDefmap (SPO_PCLATU, 0xff, 0xff, 1, 0, pc, 0, *list);
10850     }
10851     break;
10852
10853   default:
10854     *list = newDefmap (sym, in_mask, mask, isRead, isWrite, pc, val, *list);
10855     /* nothing special */
10856     return 0;
10857     break;
10858   }
10859
10860   /* has been a special operand */
10861   return 1;
10862 }
10863
10864 static symbol_t pic16_fsrsym_idx[][2] = {
10865     {SPO_FSR0L, SPO_FSR0H},
10866     {SPO_FSR1L, SPO_FSR1H},
10867     {SPO_FSR2L, SPO_FSR2H}
10868 };
10869
10870 /* Merge multiple defmap entries for the same symbol for list's pCode. */
10871 static void mergeDefmapSymbols (defmap_t *list) { 
10872   defmap_t *ref, *curr, *temp;
10873
10874   /* now make sure that each symbol occurs at most once per pc */
10875   ref = list;
10876   while (ref && (ref->pc == list->pc)) {
10877     curr = ref->next;
10878     while (curr && (curr->pc == list->pc)) {
10879       if (curr->sym == ref->sym) {
10880         //fprintf (stderr, "Merging defmap entries for symbol %s\n", strFromSym (ref->sym));
10881         /* found a symbol occuring twice... merge the two */
10882         if (curr->acc.access.isRead) {
10883           //if (ref->acc.access.isRead) fprintf (stderr, "symbol %s was marked twice as read at pc %p\n", strFromSym (ref->sym), ref->pc);
10884           ref->acc.access.isRead = 1;
10885           ref->acc.access.in_mask |= curr->acc.access.in_mask;
10886         }
10887         if (curr->acc.access.isWrite) {
10888           //if (ref->acc.access.isWrite) fprintf (stderr, "symbol %s was marked twice as written at pc %p\n", strFromSym (ref->sym), ref->pc);
10889           ref->acc.access.isWrite = 1;
10890           ref->acc.access.mask |= curr->acc.access.mask;
10891         }
10892         temp = curr;
10893         curr = curr->next;
10894         deleteDefmap (temp);
10895         continue; // do not skip curr!
10896       } // if
10897       curr = curr->next;
10898     } // while
10899     ref = ref->next;
10900   } // while
10901 }
10902
10903 /** Prepend list with the reads and definitions performed by pc. */
10904 static defmap_t *createDefmap (pCode *pc, defmap_t *list) {
10905   pCodeInstruction *pci;
10906   int cond, inCond, outCond;
10907   int mask = 0xff, smask;
10908   int isSpecial, isSpecial2;
10909   symbol_t sym, sym2;
10910   char *name;
10911
10912   if (isPCAD(pc)) {
10913     /* make sure there is at least one entry for each pc (needed by list traversal routines) */
10914     /* TODO: mark this defmap node as an ASMDIR -- any values might be read/modified */
10915     fprintf (stderr, "ASMDIRs not supported by data flow analysis!\n");
10916     list = newDefmap (0, 0xff, 0xff, 0, 0, pc, 0, list);
10917     return list;
10918   }
10919   assert (isPCI(pc));
10920   pci = PCI(pc);
10921   
10922   /* handle bit instructions */
10923   if (pci->isBitInst) {
10924     assert (pci->pcop->type == PO_GPR_BIT);
10925     mask = 1U << (PCORB(PCI(pc)->pcop)->bit);
10926   }
10927
10928   /* handle (additional) implicit arguments */
10929   switch (pci->op) {
10930   case POC_LFSR:
10931     {
10932       int lit;
10933       valnum_t val;
10934       lit = PCOL(pci->pcop)->lit;
10935       assert (lit >= 0 && lit < 3);
10936       //fprintf (stderr, "LFSR: %s // %s\n", pci->pcop->name, pic16_get_op(((pCodeOpLit2 *)(pci->pcop))->arg2, NULL, 0));
10937       val = valnumFromStr (pic16_get_op(((pCodeOpLit2 *)(pci->pcop))->arg2, NULL, 0));
10938       //fprintf (stderr, "LFSR lit=%u, symval=%4x\n", lit, val);
10939       list = newDefmap (pic16_fsrsym_idx[lit][0], 0x00, 0xff, 0, 1, pc, val, list);
10940       list = newDefmap (pic16_fsrsym_idx[lit][1], 0x00, 0xff, 0, 1, pc, val+1, list); // val+1 is guaranteed not be used as a valnum...
10941     }
10942     break;
10943
10944   case POC_MOVLB: // BSR
10945   case POC_BANKSEL: // BSR
10946     list = newDefmap (SPO_BSR, 0x00, 0xff, 0, 1, pc, valnumFromStr (pic16_get_op (((pCodeOpLit2 *)(pci->pcop))->arg2, NULL, 0)), list);
10947     break;
10948
10949   case POC_MULWF: // PRODx
10950   case POC_MULLW: // PRODx
10951     list = newDefmap (SPO_PRODH, 0x00, 0xff, 0, 1, pc, newValnum (), list);
10952     list = newDefmap (SPO_PRODL, 0x00, 0xff, 0, 1, pc, newValnum (), list);
10953     break;
10954
10955   case POC_POP: // TOS, STKPTR
10956     list = newDefmap (SPO_STKPTR, 0xff, 0xff, 1, 1, pc, newValnum (), list);
10957     list = newDefmap (SPO_TOSL, 0x00, 0xff, 0, 1, pc, newValnum (), list);
10958     list = newDefmap (SPO_TOSH, 0x00, 0xff, 0, 1, pc, newValnum (), list);
10959     list = newDefmap (SPO_TOSU, 0x00, 0xff, 0, 1, pc, newValnum (), list);
10960     break;
10961     
10962   case POC_PUSH: // STKPTR
10963     list = newDefmap (SPO_STKPTR, 0xff, 0xff, 1, 1, pc, newValnum (), list);
10964     list = newDefmap (SPO_TOSL, 0xff, 0xff, 0, 1, pc, newValnum (), list);
10965     list = newDefmap (SPO_TOSH, 0xff, 0xff, 0, 1, pc, newValnum (), list);
10966     list = newDefmap (SPO_TOSU, 0xff, 0xff, 0, 1, pc, newValnum (), list);
10967     break;
10968     
10969   case POC_CALL: // return values (and arguments?): WREG, PRODx, FSR0L
10970   case POC_RCALL: // return values (and arguments?): WREG, PRODx, FSR0L
10971     list = newDefmap (SPO_WREG, 0xff, 0xff, 1, 1, pc, newValnum (), list);
10972     list = newDefmap (SPO_PRODL, 0xff, 0xff, 1, 1, pc, newValnum (), list);
10973     list = newDefmap (SPO_PRODH, 0xff, 0xff, 1, 1, pc, newValnum (), list);
10974     list = newDefmap (SPO_FSR0L, 0xff, 0xff, 1, 1, pc, newValnum (), list);
10975
10976     /* needs correctly set-up stack pointer */
10977     list = newDefmap (SPO_FSR1L, 0xff, 0x00, 1, 0, pc, 0, list);
10978     list = newDefmap (SPO_FSR1H, 0xff, 0x00, 1, 0, pc, 0, list);
10979     break;
10980
10981   case POC_RETLW: // return values: WREG, PRODx, FSR0L
10982     /* pseudo read on (possible) return values */
10983     // WREG is handled below via outCond
10984     list = newDefmap (SPO_PRODL, 0xff, 0x00, 1, 0, pc, 0, list);
10985     list = newDefmap (SPO_PRODH, 0xff, 0x00, 1, 0, pc, 0, list);
10986     list = newDefmap (SPO_FSR0L, 0xff, 0x00, 1, 0, pc, 0, list);
10987
10988     /* caller's stack pointers must be restored */
10989     list = newDefmap (SPO_FSR1L, 0xff, 0x00, 1, 0, pc, 0, list);
10990     list = newDefmap (SPO_FSR1H, 0xff, 0x00, 1, 0, pc, 0, list);
10991     list = newDefmap (SPO_FSR2L, 0xff, 0x00, 1, 0, pc, 0, list);
10992     list = newDefmap (SPO_FSR2H, 0xff, 0x00, 1, 0, pc, 0, list);
10993     break;
10994
10995   case POC_RETURN: // return values; WREG, PRODx, FSR0L
10996   case POC_RETFIE: // return value: WREG, PRODx, FSR0L
10997     /* pseudo read on (possible) return values */
10998     list = newDefmap (SPO_WREG, 0xff, 0x00, 1, 0, pc, 0, list);
10999     list = newDefmap (SPO_PRODL, 0xff, 0x00, 1, 0, pc, 0, list);
11000     list = newDefmap (SPO_PRODH, 0xff, 0x00, 1, 0, pc, 0, list);
11001     list = newDefmap (SPO_FSR0L, 0xff, 0x00, 1, 0, pc, 0, list);
11002
11003     /* caller's stack pointers must be restored */
11004     list = newDefmap (SPO_FSR1L, 0xff, 0x00, 1, 0, pc, 0, list);
11005     list = newDefmap (SPO_FSR1H, 0xff, 0x00, 1, 0, pc, 0, list);
11006     list = newDefmap (SPO_FSR2L, 0xff, 0x00, 1, 0, pc, 0, list);
11007     list = newDefmap (SPO_FSR2H, 0xff, 0x00, 1, 0, pc, 0, list);
11008     break;
11009     
11010   case POC_TBLRD:
11011     list = newDefmap (SPO_TBLPTRL, 0xff, 0x00, 1, 0, pc, 0, list);
11012     list = newDefmap (SPO_TBLPTRH, 0xff, 0x00, 1, 0, pc, 0, list);
11013     list = newDefmap (SPO_TBLPTRU, 0xff, 0x00, 1, 0, pc, 0, list);
11014     list = newDefmap (SPO_TABLAT, 0x00, 0xff, 0, 1, pc, newValnum(), list);
11015     break;
11016     
11017   case POC_TBLRD_POSTINC:
11018   case POC_TBLRD_POSTDEC:
11019   case POC_TBLRD_PREINC:
11020     list = newDefmap (SPO_TBLPTRL, 0xff, 0xff, 1, 1, pc, newValnum(), list);
11021     list = newDefmap (SPO_TBLPTRH, 0xff, 0xff, 1, 1, pc, newValnum(), list);
11022     list = newDefmap (SPO_TBLPTRU, 0xff, 0xff, 1, 1, pc, newValnum(), list);
11023     list = newDefmap (SPO_TABLAT, 0x00, 0xff, 0, 1, pc, newValnum(), list);
11024     break;
11025     
11026   case POC_TBLWT:
11027     list = newDefmap (SPO_TBLPTRL, 0xff, 0x00, 1, 0, pc, 0, list);
11028     list = newDefmap (SPO_TBLPTRH, 0xff, 0x00, 1, 0, pc, 0, list);
11029     list = newDefmap (SPO_TBLPTRU, 0xff, 0x00, 1, 0, pc, 0, list);
11030     list = newDefmap (SPO_TABLAT, 0xff, 0x00, 1, 0, pc, 0, list);
11031     break;
11032     
11033   case POC_TBLWT_POSTINC:
11034   case POC_TBLWT_POSTDEC:
11035   case POC_TBLWT_PREINC:
11036     list = newDefmap (SPO_TBLPTRL, 0xff, 0xff, 1, 1, pc, newValnum(), list);
11037     list = newDefmap (SPO_TBLPTRH, 0xff, 0xff, 1, 1, pc, newValnum(), list);
11038     list = newDefmap (SPO_TBLPTRU, 0xff, 0xff, 1, 1, pc, newValnum(), list);
11039     list = newDefmap (SPO_TABLAT, 0xff, 0x00, 1, 0, pc, 0, list);
11040     break;
11041     
11042   default:
11043     /* many instruction implicitly read BSR... -- THIS IS IGNORED! */
11044     break;
11045   } // switch
11046
11047   /* handle explicit arguments */
11048   inCond = pci->inCond;
11049   outCond = pci->outCond;
11050   cond = inCond | outCond;
11051   if (cond & PCC_W) {
11052     list = newDefmap (symFromStr ("WREG"), mask, mask, inCond & PCC_W, outCond & PCC_W, pc, newValnum (), list);
11053   } // if
11054
11055   /* keep STATUS read BEFORE STATUS write in the list (still neccessary?) */
11056   if (inCond & PCC_STATUS) {
11057     smask = 0;
11058     if (inCond & PCC_C) smask |= 1U << PIC_C_BIT;
11059     if (inCond & PCC_DC) smask |= 1U << PIC_DC_BIT;
11060     if (inCond & PCC_Z) smask |= 1U << PIC_Z_BIT;
11061     if (inCond & PCC_OV) smask |= 1U << PIC_OV_BIT;
11062     if (inCond & PCC_N) smask |= 1U << PIC_N_BIT;
11063
11064     list = newDefmap (symFromStr ("STATUS"), smask, 0x00, 1, 0, pc, 0, list);
11065     //fprintf (stderr, "pc %p: def STATUS & %02x\n", pc, smask);
11066   } // if
11067   
11068   if (outCond & PCC_STATUS) {
11069     smask = 0;
11070     if (outCond & PCC_C) smask |= 1U << PIC_C_BIT;
11071     if (outCond & PCC_DC) smask |= 1U << PIC_DC_BIT;
11072     if (outCond & PCC_Z) smask |= 1U << PIC_Z_BIT;
11073     if (outCond & PCC_OV) smask |= 1U << PIC_OV_BIT;
11074     if (outCond & PCC_N) smask |= 1U << PIC_N_BIT;
11075
11076     list = newDefmap (symFromStr ("STATUS"), 0x00, smask, 0, 1, pc, newValnum (), list);
11077     //fprintf (stderr, "pc %p: def STATUS & %02x\n", pc, smask);
11078   } // if
11079   
11080   isSpecial = isSpecial2 = 0;
11081   sym = sym2 = 0;
11082   if (cond & PCC_REGISTER) {
11083     name = pic16_get_op (pci->pcop, NULL, 0);
11084     sym = symFromStr (name);
11085     isSpecial = fixupSpecialOperands (sym, mask, mask, pc, newValnum(), &list, inCond & PCC_REGISTER, outCond & PCC_REGISTER);
11086     //fprintf (stderr, "pc %p: def REG %s(%x) & %02x\n", pc, name, sym, mask);
11087   }
11088
11089   if (cond & PCC_REGISTER2) {
11090     name = pic16_get_op2 (pci->pcop, NULL, 0);
11091     sym2 = symFromStr (name);
11092     isSpecial2 = fixupSpecialOperands (sym2, mask, mask, pc, newValnum(), &list, inCond & PCC_REGISTER2, outCond & PCC_REGISTER2);
11093     //fprintf (stderr, "pc %p: def REG2 %s(%x) & %02x\n", pc, name, sym2, mask);
11094   }
11095
11096  
11097   /* make sure there is at least one entry for each pc (needed by list traversal routines) */
11098   list = newDefmap (0, 0x00, 0x00, 0, 0, pc, 0, list);
11099
11100   mergeDefmapSymbols (list);
11101   
11102   return list;
11103 }
11104
11105 #if 0
11106 static void printDefmap (defmap_t *map) {
11107   defmap_t *curr;
11108
11109   curr = map;
11110   fprintf (stderr, "defmap @ %p:\n", curr);
11111   while (curr) {
11112     fprintf (stderr, "%s%s: %4x|%4x / %02x|%02x, sym %s(%x) @ pc %p\n",
11113                     curr->acc.access.isRead ? "R" : " ",
11114                     curr->acc.access.isWrite ? "W": " ",
11115                     curr->in_val, curr->val,
11116                     curr->acc.access.in_mask, curr->acc.access.mask,
11117                     strFromSym(curr->sym), curr->sym,
11118                     curr->pc);
11119     curr = curr->next;
11120   } // while
11121   fprintf (stderr, "<EOL>\n");
11122 }
11123 #endif
11124
11125 /* Add "additional" definitions to uniq.
11126  * This can be used to merge the in_values and the flow's defmap to create an in_value-list for the flow's successors.
11127  * This can also be used to create a uniq (out)list from a flow's defmap by passing *uniq==NULL.
11128  *
11129  * If symbols defined in additional are not present in uniq, a definition is created.
11130  * Otherwise the present definition is altered to reflect the newer assignments.
11131  *
11132  * flow: <uniq> --> assign1 --> assign2 --> assign3 --> ... --> <uniq'>
11133  *       before     `------- noted in additional --------'      after
11134  *
11135  * I assume that each symbol occurs AT MOST ONCE in uniq.
11136  *
11137  */
11138 static int defmapUpdateUniqueSym (defmap_t **uniq, defmap_t *additional) {
11139   defmap_t *curr;
11140   defmap_t *old;
11141   int change = 0;
11142
11143   //fprintf (stderr, "%s: merging %p & %p\n", __FUNCTION__, *uniq, additional);
11144   /* find tail of additional list (holds the first assignment) */
11145   curr = additional;
11146   while (curr && curr->next) curr = curr->next;
11147
11148   /* update uniq */
11149   do {
11150     /* find next assignment in additionals */
11151     while (curr && !curr->acc.access.isWrite) curr = curr->prev;
11152
11153     if (!curr) break;
11154
11155     /* find item in uniq */
11156     old = *uniq;
11157     //printDefmap (*uniq);
11158     while (old && (old->sym != curr->sym)) old = old->next;
11159
11160     if (old) {
11161       /* definition found -- replace */
11162       if (old->val != curr->val) {
11163         old->val = curr->val;
11164         change++;
11165       } // if
11166     } else {
11167       /* new definition */
11168       *uniq = newDefmap (curr->sym, 0x00, 0xff, 0, 1, NULL, curr->val, *uniq);
11169       change++;
11170     }
11171
11172     curr = curr->prev;
11173   } while (1);
11174
11175   /* return 0 iff uniq remained unchanged */
11176   return change;
11177 }
11178
11179 /* Creates the in_value list of a flow by (iteratively) merging the out_value
11180  * lists of its predecessor flows. 
11181  * Initially *combined should be NULL, alt_in will be copied to combined.
11182  * If *combined != NULL, combined will be altered:
11183  * - for symbols defined in *combined but not in alt_in,
11184  *   *combined is altered to 0 (value unknown, either *combined or INIT).
11185  * - for symbols defined in alt_in but not in *combined,
11186  *   a 0 definition is created (value unknown, either INIT or alt).
11187  * - for symbols defined in both, *combined is:
11188  *   > left unchanged if *combined->val == alt_in->val or
11189  *   > modified to 0 otherwise (value unknown, either alt or *combined).
11190  * 
11191  * I assume that each symbol occurs AT MOST ONCE in each list!
11192  */
11193 static int defmapCombineFlows (defmap_t **combined, defmap_t *alt_in, pBlock *pb) {
11194   defmap_t *curr;
11195   defmap_t *old;
11196   int change = 0;
11197   valnum_t val;
11198
11199   //fprintf (stderr, "%s: merging %p & %p\n", __FUNCTION__, *combined, alt_in);
11200   
11201   if (!(*combined)) {
11202     return defmapUpdateUniqueSym (combined, alt_in);
11203   } // if
11204   
11205   /* merge the two */
11206   curr = alt_in;
11207   while (curr) {
11208     /* find symbols definition in *combined */
11209     old = *combined;
11210     while (old && (old->sym != curr->sym)) old = old->next;
11211
11212     if (old) {
11213       /* definition found */
11214       if (old->val && (old->val != curr->val)) {
11215         old->val = 0; /* value unknown */
11216         change++;
11217       }
11218     } else {
11219       /* no definition found -- can be either INIT or alt_in's value */
11220       val = pic16_pBlockAddInval (pb, curr->sym)->val;
11221       *combined = newDefmap (curr->sym, 0x00, 0xff, 0, 1, NULL, (val == curr->val) ? val : 0, *combined);
11222       if (val != curr->val) change++;
11223     }
11224
11225     curr = curr->next;
11226   } // while (curr)
11227
11228   /* update symbols from *combined that are NOT defined in alt_in -- can be either *combined's value or INIT */
11229   old = *combined;
11230   while (old) {
11231     if (old->val != 0) {
11232       /* find definition in alt_in */
11233       curr = alt_in;
11234       while (curr && curr->sym != old->sym) curr = curr->next;
11235       if (!curr) {
11236         /* symbol defined in *combined only -- can be either INIT or *combined */
11237         val = pic16_pBlockAddInval (pb, old->sym)->val;
11238         if (old->val != val) {
11239           old->val = 0;
11240           change++;
11241         }
11242       } // if
11243     } // if
11244
11245     old = old->next;
11246   } // while
11247
11248   return change;
11249 }
11250
11251 static int defmapCompareUnique (defmap_t *map1, defmap_t *map2) {
11252   defmap_t *curr1, *curr2;
11253   symbol_t sym;
11254   
11255   /* identical maps are equal */
11256   if (map1 == map2) return 0;
11257
11258   if (!map1) return -1;
11259   if (!map2) return 1;
11260
11261   //fprintf (stderr, "%s: comparing %p & %p\n", __FUNCTION__, map1, map2);
11262   
11263   /* check length */
11264   curr1 = map1;
11265   curr2 = map2;
11266   while (curr1 && curr2) {
11267     curr1 = curr1->next;
11268     curr2 = curr2->next;
11269   } // while
11270
11271   /* one of them longer? */
11272   if (curr1) return 1;
11273   if (curr2) return -1;
11274
11275   /* both lists are of equal length -- compare (in O(n^2)) */
11276   curr1 = map1;
11277   while (curr1) {
11278     sym = curr1->sym;
11279     curr2 = map2;
11280     while (curr2 && curr2->sym != sym) curr2 = curr2->next;
11281     if (!curr2) return 1; // symbol not found in curr2
11282     if (curr2->val != curr1->val) return 1; // values differ
11283
11284     /* compare next symbol */
11285     curr1 = curr1->next;
11286   } // while
11287
11288   /* no difference found */
11289   return 0;
11290 }
11291
11292
11293 /* Prepare a list of all reaching definitions per flow.
11294  * This is done using a forward dataflow analysis.
11295  */
11296 static void createReachingDefinitions (pBlock *pb) {
11297   defmap_t *out_vals, *in_vals;
11298   pCode *pc;
11299   pCodeFlow *pcfl;
11300   pCodeFlowLink *link;
11301   set *todo;
11302   set *blacklist;
11303
11304   /* initialize out_vals to unique'fied defmaps per pCodeFlow */
11305   for (pc = pic16_findNextInstruction (pb->pcHead); pc; pc = pic16_findNextInstruction (pc->next)) {
11306     if (isPCFL(pc)) {
11307       deleteDefmapChain (&PCFL(pc)->in_vals);
11308       deleteDefmapChain (&PCFL(pc)->out_vals);
11309       defmapUpdateUniqueSym (&PCFL(pc)->out_vals, PCFL(pc)->defmap);
11310     } // if
11311   } // for
11312   
11313   pc = pic16_findNextInstruction (pb->pcHead);
11314   todo = NULL; blacklist = NULL;
11315   addSetHead (&todo, PCI(pc)->pcflow);
11316
11317   //fprintf (stderr, "%s: function %s()\n", __FUNCTION__, pic16_pBlockGetFunctionName (pb));
11318   while (elementsInSet (todo)) {
11319     //fprintf (stderr, "%u items in todo-set\n", elementsInSet (todo));
11320     pcfl = PCFL(indexSet (todo, 0));
11321     deleteSetItem (&todo, pcfl);
11322     //fprintf (stderr, "%s: checking %p\n", __FUNCTION__, pcfl);
11323     in_vals = NULL;
11324     out_vals = NULL;
11325
11326     if (isinSet (blacklist, pcfl)) {
11327             fprintf (stderr, "ignoring blacklisted flow\n");
11328       continue;
11329     }
11330     
11331     /* create in_vals from predecessors out_vals */
11332     link = setFirstItem (pcfl->from);
11333     while (link) {
11334       defmapCombineFlows (&in_vals, link->pcflow->out_vals, pb);
11335       link = setNextItem (pcfl->from);
11336     } // while
11337
11338     //printDefmap (in_vals); 
11339     //printDefmap (pcfl->in_vals); 
11340
11341     if (!pcfl->in_vals || !pcfl->out_vals || defmapCompareUnique (in_vals, pcfl->in_vals)) {
11342       //fprintf (stderr, "in_vals changed\n");
11343       /* in_vals changed -- update out_vals */
11344       deleteDefmapChain (&pcfl->in_vals);
11345       pcfl->in_vals = in_vals;
11346
11347       /* create out_val from in_val and defmap */
11348       out_vals = NULL;
11349       defmapUpdateUniqueSym (&out_vals, in_vals);
11350       defmapUpdateUniqueSym (&out_vals, pcfl->defmap);
11351
11352       /* is out_vals different from pcfl->out_vals */
11353       if (!pcfl->out_vals || defmapCompareUnique (out_vals, pcfl->out_vals)) {
11354         //fprintf (stderr, "out_vals changed\n");
11355         deleteDefmapChain (&pcfl->out_vals);
11356         pcfl->out_vals = out_vals;
11357
11358         if (pcfl->out_vals == NULL && pcfl->in_vals == NULL) {
11359           addSet (&blacklist, pcfl);
11360         } // if
11361         
11362         /* reschedule all successors */
11363         link = setFirstItem (pcfl->to);
11364         while (link) {
11365           //fprintf (stderr, "  %p --> %p\n", pcfl, link->pcflow);
11366           addSetIfnotP (&todo, link->pcflow);
11367           link = setNextItem (pcfl->to);
11368         } // while
11369       } else {
11370         deleteDefmapChain (&out_vals);        
11371       }// if
11372     } else {
11373       deleteDefmapChain (&in_vals);         
11374     } // if
11375   } // while
11376 }
11377
11378 #if 0
11379 static void showAllDefs (symbol_t sym, pCode *pc) {
11380   defmap_t *map;
11381   int count;
11382
11383   assert (isPCI(pc));
11384   count = defmapFindAll (sym, pc, &map);
11385
11386   fprintf (stderr, "sym %s(%x) @ %p defined as (val@pc): ", strFromSym(sym), sym, pc);
11387   while (map) {
11388 #if 1
11389     fprintf (stderr, "(%x @ %p) ", map->val, map->pc);
11390 #else
11391     { char buf[256];
11392     pic16_pCode2str (buf, 256, map->pc);
11393     fprintf (stderr, "\n    (%x @ %p(%s)) ", map->val, map->pc, buf);
11394 #endif
11395     map = map->next;
11396   }
11397   deleteDefmapChain (&map);
11398 }
11399 #endif
11400
11401 /* safepCodeUnlink and remove pc from defmap. */
11402 static int pic16_safepCodeRemove (pCode *pc, char *comment) {
11403   defmap_t *map, *next, **head;
11404   int res, ispci;
11405   
11406   ispci = isPCI(pc);
11407   map = isPCI(pc) ? PCI(pc)->pcflow->defmap : NULL;
11408   head = isPCI(pc) ? &PCI(pc)->pcflow->defmap : NULL;
11409   res = pic16_safepCodeUnlink (pc, comment);
11410
11411   if (res && map) {
11412     /* remove pc from defmap */
11413     while (map) {
11414       next = map->next;
11415       if (map->pc == pc) {
11416         if (!map->prev && head) *head = map->next;
11417         deleteDefmap (map);
11418       } // if
11419       map = next;
11420     }
11421   }
11422
11423   return res;
11424 }
11425       
11426 void pic16_fixDefmap (pCode *pc, pCode *newpc) {
11427   defmap_t *map;
11428   /* This breaks the defmap chain's references to pCodes... fix it! */
11429   map = PCI(pc)->pcflow->defmap;
11430
11431   while (map && map->pc != pc) map = map->next;
11432   
11433   while (map && map->pc == pc) {
11434     map->pc = newpc;
11435     map = map->next;
11436   } // while
11437 }
11438
11439 /* Replace a defmap entry for sym with newsym for read accesses (isRead == 1) or
11440  * write accesses (isRead == 0). */
11441 void defmapReplaceSymRef (pCode *pc, symbol_t sym, symbol_t newsym, int isRead) {
11442   defmap_t *map, *map_start;
11443   defmap_t *copy;
11444   if (!isPCI(pc)) return;
11445   if (sym == newsym) return;
11446   
11447   map = PCI(pc)->pcflow->defmap;
11448
11449   while (map && map->pc != pc) map = map->next;
11450   map_start = map;
11451   while (map && map->pc == pc) {
11452     if (map->sym == sym) {
11453       assert ((isRead && map->acc.access.isRead) || ((!isRead) && (map->acc.access.isWrite)));
11454       if (!(map->acc.access.isRead && map->acc.access.isWrite)) {
11455         /* only one kind of access handled... this is easy */
11456         map->sym = newsym;
11457       } else {
11458         /* must copy defmap entry before replacing symbol... */
11459         copy = copyDefmap (map);
11460         if (isRead) {
11461           map->acc.access.isRead = 0;
11462           copy->acc.access.isWrite = 0;
11463         } else {
11464           map->acc.access.isWrite = 0;
11465           copy->acc.access.isRead = 0;
11466         }
11467         copy->sym = newsym;
11468         /* insert copy into defmap chain */
11469         defmapInsertAfter (map, copy);
11470       }
11471     }
11472     map = map->next;
11473   } // while
11474
11475   /* as this might introduce multiple defmap entries for newsym... */
11476   mergeDefmapSymbols (map_start);
11477 }
11478
11479 /* Assign "better" valnums to results. */
11480 static void assignValnums (pCode *pc) {
11481   pCodeInstruction *pci;
11482   pCode *newpc;
11483   symbol_t sym1, sym2;
11484   int cond, isSpecial1, isSpecial2, count, mask, lit;
11485   defmap_t *list, *val, *oldval, *dummy;
11486   regs *reg1 = NULL, *reg2 = NULL;
11487   valnum_t litnum;
11488
11489   /* only works for pCodeInstructions... */
11490   if (!isPCI(pc)) return;
11491
11492   pci = PCI(pc);
11493   cond = pci->inCond | pci->outCond;
11494   list = pci->pcflow->defmap;
11495   sym1 = sym2 = isSpecial1 = isSpecial2 = 0;
11496
11497   if (cond & PCC_REGISTER) {
11498     sym1 = symFromStr (pic16_get_op (pci->pcop, NULL, 0));
11499     reg1 = pic16_getRegFromInstruction (pc);
11500     isSpecial1 = pic16_symIsSpecial (sym1);
11501   }
11502   if (cond & PCC_REGISTER2) {
11503     sym2 = symFromStr (pic16_get_op2 (pci->pcop, NULL, 0));
11504     reg2 = pic16_getRegFromInstruction (pc);
11505     isSpecial2 = pic16_symIsSpecial (sym2);
11506   }
11507
11508   /* determine input values */
11509   val = list;
11510   while (val && val->pc != pc) val = val->next;
11511   //list = val; /* might save some time later... */
11512   while (val && val->pc == pc) {
11513     val->in_val = 0;
11514     if (val->sym != 0 && (1 || val->acc.access.isRead)) {
11515       /* get valnum for sym */
11516       count = defmapFindAll (val->sym, pc, &oldval);
11517       //fprintf (stderr, "%d defs for sym %s\n", count, strFromSym (val->sym));
11518       if (count == 1) {
11519         if ((val->acc.access.in_mask & oldval->acc.access.mask) == val->acc.access.in_mask) {
11520           val->in_val = oldval->val;
11521         } else {
11522           val->in_val = 0;
11523         }
11524       } else if (count == 0) {
11525         /* no definition found */
11526         val->in_val = 0;
11527       } else {
11528         /* multiple definition(s) found -- value not known (unless always the same valnum) */
11529         assert (oldval);
11530         dummy = oldval->next;
11531         mask = oldval->acc.access.mask;
11532         val->in_val = oldval->val;
11533         while (dummy && (dummy->val == val->in_val)) {
11534           mask &= dummy->acc.access.mask;
11535           dummy = dummy->next;
11536         } // while
11537
11538         /* found other values or to restictive mask */
11539         if (dummy || ((mask & val->acc.access.in_mask) != val->acc.access.in_mask)) {
11540           val->in_val = 0;
11541         }
11542       }
11543       if (count > 0) deleteDefmapChain (&oldval);
11544     } // if
11545     val = val->next;
11546   }
11547
11548   /* handle valnum assignment */
11549   switch (pci->op) {
11550   case POC_CLRF: /* modifies STATUS (Z) */
11551     if (!isSpecial1 && pic16_regIsLocal (reg1)) {
11552       oldval = defmapCurr (list, sym1, pc);
11553       if (oldval && (litFromValnum (oldval->in_val) == 0)) {
11554         //fprintf (stderr, "%s: REG (%s) already set up correctly (%x)\n", pci->mnemonic, strFromSym(sym1), oldval->in_val);
11555         if (!pic16_isAlive (SPO_STATUS, pc)) pic16_safepCodeRemove (pc, "=DF= redundant CLRF removed");
11556       }
11557       defmapUpdate (list, sym1, pc, valnumFromLit(0));
11558     }
11559     break;
11560
11561   case POC_SETF: /* SETF does not touch STATUS */
11562     if (!isSpecial1 && pic16_regIsLocal (reg1)) {
11563       oldval = defmapCurr (list, sym1, pc);
11564       if (oldval && (litFromValnum (oldval->in_val) == 0x00FF)) {
11565         //fprintf (stderr, "%s: REG (%s) already set up correctly (%x)\n", pci->mnemonic, strFromSym(sym1), oldval->in_val);
11566         pic16_safepCodeRemove (pc, "=DF= redundant SETF removed");
11567       }
11568       defmapUpdate (list, sym1, pc, valnumFromLit (0x00FF));
11569     }
11570     break;
11571     
11572   case POC_MOVLW: /* does not touch STATUS */
11573     oldval = defmapCurr (list, SPO_WREG, pc);
11574     if (pci->pcop->type == PO_LITERAL) {
11575       //fprintf (stderr, "MOVLW: literal %u\n", PCOL(pci->pcop)->lit);
11576       litnum = valnumFromLit ((unsigned char)PCOL(pci->pcop)->lit);
11577     } else {
11578       //fprintf (stderr, "MOVLW: %s\n", pic16_get_op (pci->pcop, NULL, 0));
11579       litnum = valnumFromStr (pic16_get_op (pci->pcop, NULL, 0));
11580     }
11581     if (oldval && oldval->in_val == litnum) {
11582       //fprintf (stderr, "%s: W already set up correctly (%x)\n", PCI(pc)->mnemonic, oldval->in_val);
11583       pic16_safepCodeRemove (pc, "=DF= redundant MOVLW removed");
11584     }
11585     defmapUpdate (list, SPO_WREG, pc, litnum);
11586     break;
11587
11588   case POC_ANDLW: /* modifies STATUS (Z,N) */
11589   case POC_IORLW: /* modifies STATUS (Z,N) */
11590   case POC_XORLW: /* modifies STATUS (Z,N) */
11591     /* can be optimized iff WREG contains a known literal (0x100 - 0x1FF) */
11592     if (pci->pcop->type == PO_LITERAL) {
11593       int vallit = -1;
11594       lit = (unsigned char) PCOL(pci->pcop)->lit;
11595       val = defmapCurr (list, SPO_WREG, pc);
11596       if (val) vallit = litFromValnum (val->in_val);
11597       if (vallit != -1) {
11598         /* xxxLW <literal>, WREG contains a known literal */
11599         //fprintf (stderr, "%s 0x%02x, WREG: 0x%x\n", pci->mnemonic, lit, vallit);
11600         if (pci->op == POC_ANDLW) {
11601           lit &= vallit;
11602         } else if (pci->op == POC_IORLW) {
11603           lit |= vallit;
11604         } else if (pci->op == POC_XORLW) {
11605           lit ^= vallit;
11606         } else {
11607           assert (0 && "invalid operation");
11608         }
11609         if (vallit == lit) {
11610           //fprintf (stderr, "%s: W already set up correctly (%x = val %x)\n", pci->mnemonic, vallit, val->in_val);
11611           if (!pic16_isAlive (SPO_STATUS, pc)) pic16_safepCodeRemove (pc, "=DF= redundant ANDLW/IORLW/XORLW removed");
11612         }
11613         defmapUpdate (list, SPO_WREG, pc, valnumFromLit (lit));
11614       } // if
11615     }
11616     break;
11617
11618   case POC_LFSR:
11619     {
11620       /* check if old value matches new value */
11621       int lit;
11622       int ok = 1;
11623       assert (pci->pcop->type == PO_LITERAL);
11624       
11625       lit = PCOL(pci->pcop)->lit;
11626       
11627       val = defmapCurr (list, pic16_fsrsym_idx[lit][0], pc);
11628       
11629       if (val && (val->in_val != 0) && (val->in_val == val->val)) {
11630         //fprintf (stderr, "FSR%dL already set up correctly at %p (%x)\n", lit, pc, val->val);
11631       } else {
11632         /* cannot remove this LFSR */
11633         ok = 0;      
11634       } // if
11635       
11636       val = defmapCurr (list, pic16_fsrsym_idx[lit][1], pc);
11637       if (val && (val->in_val != 0) && (val->in_val == val->val)) {
11638         //fprintf (stderr, "FSR%dH already set up correctly at %p (%x)\n", lit, pc, val->val);
11639       } else {
11640         ok = 0;
11641       } // if
11642
11643       if (ok) {
11644         pic16_safepCodeRemove (pc, "=DF= redundant LFSR removed");
11645       }
11646     }
11647     break;
11648     
11649   case POC_MOVWF: /* does not touch flags */
11650     /* find value of WREG */
11651     val = defmapCurr (list, SPO_WREG, pc);
11652     oldval = defmapCurr (list, sym1, pc);
11653     if (val) lit = litFromValnum (val->in_val);
11654     else lit = -1;
11655     //fprintf (stderr, "MOVWF: lit: %i (%x, %x)\n", lit, lit, val->in_val);
11656     
11657     if ((lit == 0 || lit == 0x0ff) && !pic16_isAlive (SPO_STATUS, pc)) {
11658       /* might replace with CLRF/SETF (will possibly make previous MOVLW 0x00/0xff unneccessary --> dead code elimination) */
11659       //fprintf (stderr, "replacing MOVWF with CLRF/SETF\n");
11660       if (lit == 0) {
11661         newpc = pic16_newpCode (POC_CLRF, pic16_pCodeOpCopy (pci->pcop));
11662       } else {
11663         assert (lit == 0x0ff);
11664         newpc = pic16_newpCode (POC_SETF, pic16_pCodeOpCopy (pci->pcop));
11665       }
11666       if (pic16_debug_verbose || pic16_pcode_verbose) pic16_InsertCommentAfter (pc->prev, "=DF= MOVWF: replaced by CLRF/SETF");
11667       pic16_pCodeReplace (pc, newpc);
11668       defmapReplaceSymRef (pc, SPO_WREG, 0, 1);
11669       pic16_fixDefmap (pc, newpc);
11670       pc = newpc;
11671         
11672       /* This breaks the defmap chain's references to pCodes... fix it! */
11673       if (!val->prev) PCI(pc)->pcflow->defmap = val->next;
11674       if (!val->acc.access.isWrite) {
11675         deleteDefmap (val);     // delete reference to WREG as in value
11676         val = NULL;
11677       } else {
11678         val->acc.access.isRead = 0;     // delete reference to WREG as in value
11679       }
11680       oldval = PCI(pc)->pcflow->defmap;
11681       while (oldval) {
11682         if (oldval->pc == pc) oldval->pc = newpc;
11683           oldval = oldval->next;
11684       } // while
11685     } else if (!isSpecial1 && pic16_regIsLocal (reg1) && val && oldval && (val->in_val != 0) && (val->in_val == oldval->in_val)) {
11686       //fprintf (stderr, "MOVWF: F (%s) already set up correctly (%x) at %p\n", strFromSym (sym1), oldval->in_val, pc);
11687       pic16_safepCodeRemove (pc, "=DF= redundant MOVWF removed");
11688     }
11689     if (val) defmapUpdate (list, sym1, pc, val->in_val);
11690     break;
11691     
11692   case POC_MOVFW: /* modifies STATUS (Z,N) */
11693     /* find value of REG */
11694     if (!isSpecial1 && pic16_regIsLocal (reg1)) {
11695       val = defmapCurr (list, sym1, pc);
11696       oldval = defmapCurr (list, SPO_WREG, pc);
11697       if (val && oldval && (val->in_val != 0) && (val->in_val == oldval->in_val)) {
11698         //fprintf (stderr, "MOVFW: W already set up correctly (%x) at %p\n", oldval->in_val, pc);
11699         if (!pic16_isAlive (SPO_STATUS, pc)) pic16_safepCodeRemove (pc, "=DF= redundant MOVFW removed");
11700       }
11701       if (val) defmapUpdate (list, SPO_WREG, pc, val->in_val);
11702     }
11703     break;
11704
11705   case POC_MOVFF: /* does not touch STATUS */
11706     /* find value of REG */
11707     val = defmapCurr (list, sym1, pc);
11708     oldval = defmapCurr (list, sym2, pc);
11709     if (val) lit = litFromValnum (val->in_val);
11710     else lit = -1;
11711     newpc = NULL;
11712     if (!isSpecial1 && pic16_regIsLocal (reg1) && val && oldval && !pic16_isAlive (SPO_STATUS, pc)) {
11713       //pc->print (stderr, pc); fprintf (stderr, "lit: %d (%x, %x)\n", lit, lit, val->in_val);
11714       if (lit == 0) {
11715         newpc = pic16_newpCode (POC_CLRF, PCOP2(pci->pcop)->pcopR);
11716       } else if (lit == 0x00ff) {
11717         newpc = pic16_newpCode (POC_SETF, PCOP2(pci->pcop)->pcopR);
11718       } else {
11719         newpc = NULL;
11720       }
11721       if (newpc) {
11722         pic16_InsertCommentAfter (pc->prev, "=DF= MOVFF: replaced by CRLF/SETF");
11723         pic16_df_saved_bytes += PCI(pc)->isize - PCI(newpc)->isize;
11724         pic16_pCodeReplace (pc, newpc); 
11725         defmapReplaceSymRef (pc, sym1, 0, 1);
11726         pic16_fixDefmap (pc, newpc);
11727         pc = newpc;
11728         break; // do not process instruction as MOVFF...
11729       }
11730     } else if (!isSpecial1 && !isSpecial2
11731                 && pic16_regIsLocal (reg1) && pic16_regIsLocal (reg2)
11732                 && val && oldval && (val->in_val != 0)) {
11733       if (val->in_val == oldval->in_val) {
11734         //fprintf (stderr, "MOVFF: F2 (%s) already set up correctly (%x) at %p\n", strFromSym (sym2), oldval->in_val, pc);
11735         pic16_safepCodeRemove (pc, "=DF= redundant MOVFF removed");
11736       } else {
11737         if (!pic16_isAlive (sym1, pc)) {
11738           defmap_t *copy = NULL;
11739           /* If there is another symbol S storing sym1's value we should assign from S thus shortening the liferange of sym1.
11740            * This should help eliminate
11741            *   MOVFF A,B
11742            *   <do something not changing A or using B>
11743            *   MOVFF B,C
11744            *   <B is not alive anymore>
11745            * and turn it into
11746            *   <do something not changing A or using B>
11747            *   MOVFF A,C
11748            */
11749
11750           /* scan defmap for symbols storing sym1's value */
11751           while (oldval && (oldval->pc == pc || oldval->in_val != val->in_val)) oldval = oldval->next;
11752           if (oldval && (oldval->sym != sym1) && defmapFindAll (oldval->sym, pc, &copy) == 1) {
11753             /* unique reaching definition for sym found */
11754             if (copy->val && copy->val == val->in_val) {
11755               //fprintf (stderr, "found replacement symbol for %s (val %x) <-- %s (assigned %x @ %p)\n", strFromSym(sym1), val->in_val, strFromSym(copy->sym), copy->val, copy->pc);
11756               if (copy->sym == SPO_WREG) {
11757                 newpc = pic16_newpCode (POC_MOVWF, pic16_pCodeOpCopy (PCOP2(pci->pcop)->pcopR));
11758               } else {
11759                 pCodeOp *pcop = NULL;
11760                 /* the code below fails if we try to replace
11761                  *   MOVFF PRODL, r0x03
11762                  *   MOVFF r0x03, PCLATU
11763                  * with
11764                  *   MOVFF PRODL, PCLATU
11765                  * as copy(PRODL) contains has pc==NULL, by name fails...
11766                  */
11767                 if (!copy->pc || !PCI(copy->pc)->pcop) break;
11768                 
11769                 if (copy->pc && PCI(copy->pc)->pcop)
11770                   pcop = PCI(copy->pc)->pcop;
11771 #if 0
11772                 /* This code is broken--see above. */
11773                 else
11774                 {
11775                   const char *symname = strFromSym(copy->sym);
11776                   
11777                   assert( symname );
11778                   pic16_InsertCommentAfter (pc->prev, "BUG-ME");
11779                   pic16_InsertCommentAfter (pc->prev, "=DF= MOVFF: newpCodeOpregFromStr(%s)", (char *)symname);
11780                   //pcop = pic16_newpCodeOpRegFromStr((char *)symname);
11781                 }
11782 #endif
11783                 assert( pcop );
11784                 newpc = pic16_newpCode(POC_MOVFF, pic16_popGet2p(
11785                         pcop,
11786                         pic16_pCodeOpCopy (PCOP2(pci->pcop)->pcopR)));
11787               }
11788               pic16_InsertCommentAfter (pc->prev, "=DF= MOVFF: SRC op %s replaced by %s", strFromSym(sym1), strFromSym(copy->sym));
11789               pic16_df_saved_bytes += PCI(pc)->isize - PCI(newpc)->isize;
11790               pic16_pCodeReplace (pc, newpc); 
11791               assert (val->sym == sym1 && val->acc.access.isRead && !val->acc.access.isWrite);
11792               defmapReplaceSymRef (pc, sym1, copy->sym, 1);
11793               pic16_fixDefmap (pc, newpc);
11794               pc = newpc;
11795             }
11796           }
11797           deleteDefmapChain (&copy);
11798         }
11799       }
11800       if (val) defmapUpdate (list, sym2, pc, val->in_val);
11801     }
11802     break;
11803
11804   default:
11805     /* cannot optimize */
11806     break;
11807   } // switch
11808 }
11809
11810 static void pic16_destructDF (pBlock *pb) {
11811   pCode *pc, *next;
11812
11813   /* remove old defmaps */
11814   pc = pic16_findNextInstruction (pb->pcHead);
11815   while (pc) {
11816     next = pic16_findNextInstruction (pc->next);
11817
11818     assert (isPCI(pc) || isPCAD(pc));
11819     assert (PCI(pc)->pcflow);
11820     deleteDefmapChain (&PCI(pc)->pcflow->defmap);
11821     deleteDefmapChain (&PCI(pc)->pcflow->in_vals);
11822     deleteDefmapChain (&PCI(pc)->pcflow->out_vals);
11823     
11824     pc = next;
11825   } // while
11826   
11827   if (defmap_free || defmap_free_count) {
11828     //fprintf (stderr, "released defmaps: %u -- freeing up memory\n", defmap_free_count);
11829     freeDefmap (&defmap_free);
11830     defmap_free_count = 0;
11831   }
11832 }
11833
11834 /* Checks whether a pBlock contains ASMDIRs. */
11835 static int pic16_pBlockHasAsmdirs (pBlock *pb) {
11836   pCode *pc;
11837
11838   pc = pic16_findNextInstruction (pb->pcHead);
11839   while (pc) {
11840     if (isPCAD(pc)) return 1;
11841
11842     pc = pic16_findNextInstruction (pc->next);
11843   } // while
11844
11845   /* no PCADs found */
11846   return 0;
11847 }
11848
11849 #if 1
11850 /* Remove MOVFF r0x??, POSTDEC1 and MOVFF PREINC1, r0x?? for otherwise unused registers. */
11851 static int pic16_removeUnusedRegistersDF () {
11852   pCode *pc, *pc2;
11853   pBlock *pb;
11854   regs *reg1, *reg2, *reg3;
11855   set *seenRegs = NULL;
11856   int cond, i;
11857   int islocal, change = 0;
11858
11859   /* no pBlocks? */
11860   if (!the_pFile || !the_pFile->pbHead) return 0;
11861   
11862   for (pb = the_pFile->pbHead; pb; pb = pb->next) {
11863     //fprintf (stderr, "%s: examining function %s\n", __FUNCTION__, pic16_pBlockGetFunctionName (pb));
11864 #if 1
11865     /* find set of using pCodes per register */
11866     for (pc = pic16_findNextInstruction (pb->pcHead); pc;
11867                     pc = pic16_findNextInstruction(pc->next)) {
11868
11869       cond = PCI(pc)->inCond | PCI(pc)->outCond;
11870       reg1 = reg2 = NULL;
11871       if (cond & PCC_REGISTER) reg1 = pic16_getRegFromInstruction (pc);
11872       if (cond & PCC_REGISTER2) reg2 = pic16_getRegFromInstruction2 (pc);
11873
11874       if (reg1) {
11875         if (!isinSet (seenRegs, reg1)) reg1->reglives.usedpCodes = NULL;
11876         addSetIfnotP (&seenRegs, reg1);
11877         addSetIfnotP (&reg1->reglives.usedpCodes, pc);
11878       }
11879       if (reg2) {
11880         if (!isinSet (seenRegs, reg2)) reg2->reglives.usedpCodes = NULL;
11881         addSetIfnotP (&seenRegs, reg2);
11882         addSetIfnotP (&reg2->reglives.usedpCodes, pc);
11883       }
11884     } // for pc
11885 #endif
11886     for (reg1 = setFirstItem (seenRegs); reg1; reg1 = setNextItem (seenRegs)) {
11887       /* may not use pic16_regIsLocal() here -- in interrupt routines
11888        * WREG, PRODx, FSR0x must be saved */
11889       islocal = (reg1->isLocal || reg1->rIdx == pic16_framepnt_lo->rIdx || reg1->rIdx == pic16_framepnt_hi->rIdx);
11890       if (islocal && elementsInSet (reg1->reglives.usedpCodes) == 2) {
11891         pc = pc2 = NULL;
11892         for (i=0; i < 2; i++) {
11893           pc = (pCode *) indexSet(reg1->reglives.usedpCodes, i);
11894           if (!pc2) pc2 = pc;
11895           if (!isPCI(pc) || !PCI(pc)->op == POC_MOVFF) continue;
11896           reg2 = pic16_getRegFromInstruction (pc);
11897           reg3 = pic16_getRegFromInstruction2 (pc);
11898           if (!reg2 || !reg3
11899               || (reg2->rIdx != pic16_stack_preinc->rIdx
11900                   && reg3->rIdx != pic16_stack_postdec->rIdx)) break;
11901           if (i == 1) {
11902             /* both pCodes are MOVFF R,POSTDEC1 / MOVFF PREINC1,R */
11903             //fprintf (stderr, "%s: removing local register %s from %s\n", __FUNCTION__, reg1->name, pic16_pBlockGetFunctionName (pb));
11904             pic16_safepCodeRemove (pc, "removed unused local reg IN");
11905             pic16_safepCodeRemove (pc2, "removed unused local reg OUT");
11906           }
11907         } // for
11908       } // if
11909       deleteSet (&reg1->reglives.usedpCodes);
11910     } // for reg1
11911
11912     deleteSet (&seenRegs);
11913   } // for pb
11914
11915   return change;
11916 }
11917 #endif
11918
11919 /* Set up pCodeFlow's defmap_ts. 
11920  * Needs correctly set up to/from fields. */
11921 static void pic16_createDF (pBlock *pb) {
11922   pCode *pc, *next;
11923   int change=0;
11924
11925   //fprintf (stderr, "creating DF for pb %p (%s)\n", pb, pic16_pBlockGetFunctionName (pb));
11926
11927   pic16_destructDF (pb);
11928
11929   /* check pBlock: do not analyze pBlocks with ASMDIRs (for now...) */
11930   if (pic16_pBlockHasAsmdirs (pb)) {
11931     //fprintf (stderr, "%s: pBlock contains ASMDIRs -- data flow analysis not performed!\n", __FUNCTION__);
11932     return;
11933   }
11934
11935   /* integrity check -- we need to reach all flows to guarantee
11936    * correct data flow analysis (reaching definitions, aliveness) */
11937 #if 0
11938   if (!verifyAllFlowsReachable (pb)) {
11939     fprintf (stderr, "not all flows reachable -- aborting dataflow analysis for %s!\n", pic16_pBlockGetFunctionName (pb));
11940     return;
11941   }
11942 #endif
11943   
11944   /* establish new defmaps */
11945   pc = pic16_findNextInstruction (pb->pcHead);
11946   while (pc) {
11947     next = pic16_findNextInstruction (pc->next);
11948
11949     assert (PCI(pc)->pcflow);
11950     PCI(pc)->pcflow->defmap = createDefmap (pc, PCI(pc)->pcflow->defmap);
11951
11952     pc = next;
11953   } // while
11954
11955   //fprintf (stderr, "%s: creating reaching definitions...\n", __FUNCTION__);
11956   createReachingDefinitions (pb);
11957   
11958 #if 1
11959   /* assign better valnums */
11960   //fprintf (stderr, "assigning valnums for pb %p\n", pb);
11961   pc = pic16_findNextInstruction (pb->pcHead);
11962   while (pc) {
11963     next = pic16_findNextInstruction (pc->next);
11964
11965     assert (PCI(pc)->pcflow);
11966     assignValnums (pc);
11967
11968     pc = next;
11969   } // while
11970 #endif
11971
11972 #if 1
11973   /* remove dead pCodes */
11974   //fprintf (stderr, "removing dead pCodes in %p (%s)\n", pb, pic16_pBlockGetFunctionName (pb));
11975   do {
11976     change = 0;
11977     pc = pic16_findNextInstruction (pb->pcHead);
11978     while (pc) {
11979       next = pic16_findNextInstruction (pc->next);
11980
11981       if (isPCI(pc) && !isPCI_BRANCH(pc) && !pic16_pCodeIsAlive (pc)) {
11982         change += pic16_safepCodeRemove (pc, "=DF= removed dead pCode");
11983       }
11984
11985       pc = next;
11986     } // while
11987   } while (change);
11988 #endif
11989 }
11990
11991 /* ======================================================================== */
11992 /* === VCG DUMPER ROUTINES ================================================ */
11993 /* ======================================================================== */
11994 #if defined (DUMP_DF_GRAPHS) && DUMP_DF_GRAPHS > 0
11995 hTab *dumpedNodes = NULL;
11996
11997 /** Dump VCG header into of. */
11998 static void pic16_vcg_init (FILE *of) {
11999   /* graph defaults */
12000   fprintf (of, "graph:{\n");
12001   fprintf (of, "title:\"graph1\"\n");
12002   fprintf (of, "label:\"graph1\"\n");
12003   fprintf (of, "color:white\n");
12004   fprintf (of, "textcolor:black\n");
12005   fprintf (of, "bordercolor:black\n");
12006   fprintf (of, "borderwidth:1\n");
12007   fprintf (of, "textmode:center\n");
12008
12009   fprintf (of, "layoutalgorithm:dfs\n");
12010   fprintf (of, "late_edge_labels:yes\n");
12011   fprintf (of, "display_edge_labels:yes\n");
12012   fprintf (of, "dirty_edge_labels:yes\n");
12013   fprintf (of, "finetuning:yes\n");
12014   fprintf (of, "ignoresingles:no\n");
12015   fprintf (of, "straight_phase:yes\n");
12016   fprintf (of, "priority_phase:yes\n");
12017   fprintf (of, "manhattan_edges:yes\n");
12018   fprintf (of, "smanhattan_edges:no\n");
12019   fprintf (of, "nearedges:no\n");
12020   fprintf (of, "node_alignment:center\n"); // bottom|top|center
12021   fprintf (of, "port_sharing:no\n");
12022   fprintf (of, "arrowmode:free\n"); // fixed|free
12023   fprintf (of, "crossingphase2:yes\n");
12024   fprintf (of, "crossingoptimization:yes\n");
12025   fprintf (of, "edges:yes\n");
12026   fprintf (of, "nodes:yes\n");
12027   fprintf (of, "splines:no\n");
12028   
12029   /* node defaults */
12030   fprintf (of, "node.color:lightyellow\n");
12031   fprintf (of, "node.textcolor:black\n");
12032   fprintf (of, "node.textmode:center\n");
12033   fprintf (of, "node.shape:box\n");
12034   fprintf (of, "node.bordercolor:black\n");
12035   fprintf (of, "node.borderwidth:1\n");
12036
12037   /* edge defaults */
12038   fprintf (of, "edge.textcolor:black\n");
12039   fprintf (of, "edge.color:black\n");
12040   fprintf (of, "edge.thickness:1\n");
12041   fprintf (of, "edge.arrowcolor:black\n");
12042   fprintf (of, "edge.backarrowcolor:black\n");
12043   fprintf (of, "edge.arrowsize:15\n");
12044   fprintf (of, "edge.backarrowsize:15\n");
12045   fprintf (of, "edge.arrowstyle:line\n"); // none|solid|line
12046   fprintf (of, "edge.backarrowstyle:none\n"); // none|solid|line
12047   fprintf (of, "edge.linestyle:continuous\n"); // continuous|solid|dotted|dashed|invisible
12048   
12049   fprintf (of, "\n");
12050
12051   /* prepare data structures */
12052   if (dumpedNodes) {
12053     hTabDeleteAll (dumpedNodes);
12054     dumpedNodes = NULL;
12055   }
12056   dumpedNodes = newHashTable (128);
12057 }
12058
12059 /** Dump VCG footer into of. */
12060 static void pic16_vcg_close (FILE *of) {
12061   fprintf (of, "}\n");
12062 }
12063
12064 #define BUF_SIZE 128
12065 #define pcTitle(pc) (SNPRINTF (buf, BUF_SIZE, "n_%p, %p/%u", PCODE(pc), isPCI(pc) ? PCI(pc)->pcflow : NULL, PCODE(pc)->seq), &buf[0])
12066
12067 #if 0
12068 static int ptrcmp (const void *p1, const void *p2) {
12069   return p1 == p2;
12070 }
12071 #endif
12072
12073 /** Dump a pCode node as VCG to of. */
12074 static void pic16_vcg_dumpnode (pCode *pc, FILE *of) {
12075   char buf[BUF_SIZE];
12076
12077   if (hTabFindByKey (dumpedNodes, (((char *) pc - (char *) 0)>>2) % 128, pc, ptrcmp)) {
12078     // dumped already
12079     return;
12080   }
12081   hTabAddItemLong (&dumpedNodes, (((char *) pc - (char *) 0)>>2) % 128, pc, pc);
12082   //fprintf (stderr, "dumping %p\n", pc);
12083  
12084   /* only dump pCodeInstructions and Flow nodes */
12085   if (!isPCI(pc) && !isPCAD(pc) && !isPCFL(pc)) return;
12086     
12087   /* emit node */
12088   fprintf (of, "node:{");
12089   fprintf (of, "title:\"%s\" ", pcTitle(pc));
12090   fprintf (of, "label:\"%s\n", pcTitle(pc));
12091   if (isPCFL(pc)) {
12092     fprintf (of, "<PCFLOW>");
12093   } else if (isPCI(pc) || isPCAD(pc)) {
12094     pc->print (of, pc);
12095   } else {
12096     fprintf (of, "<!PCI>");
12097   }
12098   fprintf (of, "\" ");
12099   fprintf (of, "}\n");
12100   
12101   if (1 && isPCFL(pc)) {
12102     defmap_t *map, *prev;
12103     unsigned int i;
12104     map = PCFL(pc)->defmap;
12105     i=0;
12106     while (map) {
12107       if (map->sym != 0) {
12108         i++;
12109       
12110         /* emit definition node */
12111         fprintf (of, "node:{title:\"%s_def%u\" ", pcTitle(pc), i);
12112         fprintf (of, "label:\"");
12113
12114         prev = map;
12115         do {
12116           fprintf (of, "%s%c%c: val %4x|%4x & %02x|%02x, sym %s", (prev == map) ? "" : "\n", map->acc.access.isRead ? 'R' : ' ', map->acc.access.isWrite ? 'W' : ' ', map->in_val, map->val, map->acc.access.in_mask, map->acc.access.mask, strFromSym (map->sym));
12117           prev = map;
12118           map = map->next;
12119         } while (map && prev->pc == map->pc);
12120         map = prev;
12121         
12122         fprintf (of, "\" ");
12123       
12124         fprintf (of, "color:green ");
12125         fprintf (of, "}\n");
12126
12127         /* emit edge to previous definition */
12128         fprintf (of, "edge:{sourcename:\"%s_def%u\" ", pcTitle(pc), i);
12129         if (i == 1) {
12130           fprintf (of, "targetname:\"%s\" ", pcTitle(pc));
12131         } else {
12132           fprintf (of, "targetname:\"%s_def%u\" ", pcTitle(pc), i-1);
12133         }
12134         fprintf (of, "color:green ");
12135         fprintf (of, "}\n");
12136
12137         if (map->pc) {
12138           pic16_vcg_dumpnode (map->pc, of);
12139           fprintf (of, "edge:{sourcename:\"%s_def%u\" ", pcTitle(pc), i);
12140           fprintf (of, "targetname:\"%s\" linestyle:dashed color:lightgreen}\n", pcTitle(map->pc));
12141         }
12142       }
12143       map = map->next;
12144     } // while
12145   }
12146
12147   /* emit additional nodes (e.g. operands) */
12148 }
12149
12150 /** Dump a pCode's edges (control flow/data flow) as VCG to of. */
12151 static void pic16_vcg_dumpedges (pCode *pc, FILE *of) {
12152   char buf[BUF_SIZE];
12153   pCodeInstruction *pci;
12154   pBranch *curr;
12155   int i;
12156   
12157   if (1 && isPCFL(pc)) {
12158     /* emit edges to flow successors */
12159     void *pcfl;
12160     //fprintf (stderr, "PCFLOWe @ %p\n", pc);
12161     pcfl = setFirstItem (PCFL(pc)->to);
12162     while (pcfl) {
12163       pcfl = ((pCodeFlowLink *) (pcfl))->pcflow;
12164       pic16_vcg_dumpnode (pc, of);
12165       pic16_vcg_dumpnode ((pCode *) pcfl, of);
12166       fprintf (of, "edge:{sourcename:\"%s\" ", pcTitle(pc));
12167       fprintf (of, "targetname:\"%s\" color:lightred linestyle:dashed}\n", pcTitle(pcfl));
12168       pcfl = setNextItem (PCFL(pc)->to);
12169     } // while
12170   } // if
12171   
12172   if (!isPCI(pc) && !isPCAD(pc)) return;
12173
12174   pci = PCI(pc);
12175   
12176   /* emit control flow edges (forward only) */
12177   curr = pci->to;
12178   i=0;
12179   while (curr) {
12180     pic16_vcg_dumpnode (curr->pc, of);
12181     fprintf (of, "edge:{");
12182     fprintf (of, "sourcename:\"%s\" ", pcTitle(pc));
12183     fprintf (of, "targetname:\"%s\" ", pcTitle(curr->pc));
12184     fprintf (of, "color:red ");
12185     fprintf (of, "}\n");
12186     curr = curr->next;
12187   } // while
12188
12189 #if 1
12190   /* dump "flow" edge (link pCode according to pBlock order) */
12191   {
12192     pCode *pcnext;
12193     pcnext = pic16_findNextInstruction (pc->next);
12194     if (pcnext) {
12195       pic16_vcg_dumpnode (pcnext, of);
12196       fprintf (of, "edge:{sourcename:\"%s\" ", pcTitle(pc));
12197       fprintf (of, "targetname:\"%s\" color:red linestyle:solid}\n", pcTitle(pcnext));
12198     }
12199   }
12200 #endif
12201   
12202 #if 0
12203   /* emit flow */
12204   if (pci->pcflow) {
12205     pic16_vcg_dumpnode (&pci->pcflow->pc, of);
12206     fprintf (of, "edge:{sourcename:\"%s\" ", pcTitle(pc));
12207     fprintf (of, "targetname:\"%s\" color:lightblue linestyle:dashed}\n", pcTitle (pci->pcflow));
12208   }
12209 #endif
12210   
12211   /* emit data flow edges (backward only) */
12212   /* TODO: gather data flow information... */
12213 }
12214
12215 static void pic16_vcg_dump (FILE *of, pBlock *pb) {
12216   pCode *pc;
12217
12218   /* check pBlock: do not analyze pBlocks with ASMDIRs (for now...) */
12219   if (pic16_pBlockHasAsmdirs (pb)) {
12220     //fprintf (stderr, "%s: pBlock contains ASMDIRs -- data flow analysis not performed!\n", __FUNCTION__);
12221     return;
12222   }
12223
12224   for (pc=pb->pcHead; pc; pc = pc->next) {
12225     pic16_vcg_dumpnode (pc, of);
12226   } // for pc
12227   
12228   for (pc=pb->pcHead; pc; pc = pc->next) {
12229     pic16_vcg_dumpedges (pc, of);
12230   } // for pc
12231 }
12232
12233 static void pic16_vcg_dump_default (pBlock *pb) {
12234   FILE *of;
12235   char buf[BUF_SIZE];
12236   pCode *pc;
12237
12238   /* get function name */
12239   pc = pb->pcHead;
12240   while (pc && !isPCF(pc)) pc = pc->next;
12241   if (pc) {
12242     SNPRINTF (buf, BUF_SIZE, "%s_%s.vcg", PCF(pc)->modname, PCF(pc)->fname);
12243   } else {
12244     SNPRINTF (buf, BUF_SIZE, "pb_%p.vcg", pb);
12245   }
12246
12247   //fprintf (stderr, "now dumping %s\n", buf);
12248   of = fopen (buf, "w");
12249   pic16_vcg_init (of);
12250   pic16_vcg_dump (of, pb);
12251   pic16_vcg_close (of);
12252   fclose (of);
12253 }
12254 #endif
12255
12256 /*** END of helpers for pCode dataflow optimizations ***/