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