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