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