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