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