48c1928f5f6d14a719476f405b71ce29d5a20526
[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);
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, int shared);
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 PIC_device *init_pic(char *);
1342
1343 void  pCodeInitRegisters(void)
1344 {
1345         static int initialized=0;
1346         int shareBankAddress, stkSize, haveShared;
1347         PIC_device *pic;
1348         
1349         if(initialized)
1350                 return;
1351         initialized = 1;
1352         
1353         pic = init_pic(port->processor);
1354         haveShared = pic14_getSharedStack(NULL, &shareBankAddress, &stkSize);
1355         /* Set pseudo stack size to SHAREBANKSIZE - 3.
1356          * On multi memory bank ICs this leaves room for WSAVE/SSAVE/PSAVE
1357          * (used for interrupts) to fit into the shared portion of the
1358          * memory bank. */
1359         stkSize = stkSize - 3;
1360         assert(stkSize >= 0);
1361         initStack(shareBankAddress, stkSize, haveShared);
1362         
1363         /* TODO: Read aliases for SFRs from regmap lines in device description. */
1364         pc_status.r = allocProcessorRegister(IDX_STATUS,"STATUS", PO_STATUS, 0x180);
1365         pc_pcl.r = allocProcessorRegister(IDX_PCL,"PCL", PO_PCL, 0x80);
1366         pc_pclath.r = allocProcessorRegister(IDX_PCLATH,"PCLATH", PO_PCLATH, 0x180);
1367         pc_fsr.r = allocProcessorRegister(IDX_FSR,"FSR", PO_FSR, 0x180);
1368         pc_indf.r = allocProcessorRegister(IDX_INDF,"INDF", PO_INDF, 0x180);
1369         pc_intcon.r = allocProcessorRegister(IDX_INTCON,"INTCON", PO_INTCON, 0x180);
1370         
1371         pc_status.rIdx = IDX_STATUS;
1372         pc_fsr.rIdx = IDX_FSR;
1373         pc_indf.rIdx = IDX_INDF;
1374         pc_intcon.rIdx = IDX_INTCON;
1375         pc_pcl.rIdx = IDX_PCL;
1376         pc_pclath.rIdx = IDX_PCLATH;
1377         
1378         /* Interrupt storage for working register - must be same address in all banks ie section SHAREBANK. */
1379         pc_wsave.r = allocInternalRegister(IDX_WSAVE,pc_wsave.pcop.name,pc_wsave.pcop.type, pic ? pic->bankMask : 0x180);
1380         /* Interrupt storage for status register. */
1381         pc_ssave.r = allocInternalRegister(IDX_SSAVE,pc_ssave.pcop.name,pc_ssave.pcop.type, (pic && haveShared) ? pic->bankMask : 0);
1382         /* Interrupt storage for pclath register. */
1383         pc_psave.r = allocInternalRegister(IDX_PSAVE,pc_psave.pcop.name,pc_psave.pcop.type, (pic && haveShared) ? pic->bankMask : 0);
1384         
1385         pc_wsave.rIdx = pc_wsave.r->rIdx;
1386         pc_ssave.rIdx = pc_ssave.r->rIdx;
1387         pc_psave.rIdx = pc_psave.r->rIdx;
1388         
1389         pc_wsave.r->isFixed = 1; /* Some PIC ICs do not have a sharebank - this register needs to be reserved across all banks. */
1390         pc_wsave.r->address = shareBankAddress-stkSize;
1391         pc_ssave.r->isFixed = 1; /* This register must be in the first bank. */
1392         pc_ssave.r->address = shareBankAddress-stkSize-1;
1393         pc_psave.r->isFixed = 1; /* This register must be in the first bank. */
1394         pc_psave.r->address = shareBankAddress-stkSize-2;
1395         
1396         /* probably should put this in a separate initialization routine */
1397         pb_dead_pcodes = newpBlock();
1398         
1399 }
1400
1401 /*-----------------------------------------------------------------*/
1402 /*  mnem2key - convert a pic mnemonic into a hash key              */
1403 /*   (BTW - this spreads the mnemonics quite well)                 */
1404 /*                                                                 */
1405 /*-----------------------------------------------------------------*/
1406
1407 int mnem2key(unsigned char const *mnem)
1408 {
1409         int key = 0;
1410         
1411         if(!mnem)
1412                 return 0;
1413         
1414         while(*mnem) {
1415                 
1416                 key += toupper(*mnem++) +1;
1417                 
1418         }
1419         
1420         return (key & 0x1f);
1421         
1422 }
1423
1424 void pic14initMnemonics(void)
1425 {
1426         int i = 0;
1427         int key;
1428         //  char *str;
1429         pCodeInstruction *pci;
1430         
1431         if(mnemonics_initialized)
1432                 return;
1433         
1434         //FIXME - probably should NULL out the array before making the assignments
1435         //since we check the array contents below this initialization.
1436         
1437         pic14Mnemonics[POC_ADDLW] = &pciADDLW;
1438         pic14Mnemonics[POC_ADDWF] = &pciADDWF;
1439         pic14Mnemonics[POC_ADDFW] = &pciADDFW;
1440         pic14Mnemonics[POC_ANDLW] = &pciANDLW;
1441         pic14Mnemonics[POC_ANDWF] = &pciANDWF;
1442         pic14Mnemonics[POC_ANDFW] = &pciANDFW;
1443         pic14Mnemonics[POC_BCF] = &pciBCF;
1444         pic14Mnemonics[POC_BSF] = &pciBSF;
1445         pic14Mnemonics[POC_BTFSC] = &pciBTFSC;
1446         pic14Mnemonics[POC_BTFSS] = &pciBTFSS;
1447         pic14Mnemonics[POC_CALL] = &pciCALL;
1448         pic14Mnemonics[POC_COMF] = &pciCOMF;
1449         pic14Mnemonics[POC_COMFW] = &pciCOMFW;
1450         pic14Mnemonics[POC_CLRF] = &pciCLRF;
1451         pic14Mnemonics[POC_CLRW] = &pciCLRW;
1452         pic14Mnemonics[POC_CLRWDT] = &pciCLRWDT;
1453         pic14Mnemonics[POC_DECF] = &pciDECF;
1454         pic14Mnemonics[POC_DECFW] = &pciDECFW;
1455         pic14Mnemonics[POC_DECFSZ] = &pciDECFSZ;
1456         pic14Mnemonics[POC_DECFSZW] = &pciDECFSZW;
1457         pic14Mnemonics[POC_GOTO] = &pciGOTO;
1458         pic14Mnemonics[POC_INCF] = &pciINCF;
1459         pic14Mnemonics[POC_INCFW] = &pciINCFW;
1460         pic14Mnemonics[POC_INCFSZ] = &pciINCFSZ;
1461         pic14Mnemonics[POC_INCFSZW] = &pciINCFSZW;
1462         pic14Mnemonics[POC_IORLW] = &pciIORLW;
1463         pic14Mnemonics[POC_IORWF] = &pciIORWF;
1464         pic14Mnemonics[POC_IORFW] = &pciIORFW;
1465         pic14Mnemonics[POC_MOVF] = &pciMOVF;
1466         pic14Mnemonics[POC_MOVFW] = &pciMOVFW;
1467         pic14Mnemonics[POC_MOVLW] = &pciMOVLW;
1468         pic14Mnemonics[POC_MOVWF] = &pciMOVWF;
1469         pic14Mnemonics[POC_NOP] = &pciNOP;
1470         pic14Mnemonics[POC_RETFIE] = &pciRETFIE;
1471         pic14Mnemonics[POC_RETLW] = &pciRETLW;
1472         pic14Mnemonics[POC_RETURN] = &pciRETURN;
1473         pic14Mnemonics[POC_RLF] = &pciRLF;
1474         pic14Mnemonics[POC_RLFW] = &pciRLFW;
1475         pic14Mnemonics[POC_RRF] = &pciRRF;
1476         pic14Mnemonics[POC_RRFW] = &pciRRFW;
1477         pic14Mnemonics[POC_SUBLW] = &pciSUBLW;
1478         pic14Mnemonics[POC_SUBWF] = &pciSUBWF;
1479         pic14Mnemonics[POC_SUBFW] = &pciSUBFW;
1480         pic14Mnemonics[POC_SWAPF] = &pciSWAPF;
1481         pic14Mnemonics[POC_SWAPFW] = &pciSWAPFW;
1482         pic14Mnemonics[POC_TRIS] = &pciTRIS;
1483         pic14Mnemonics[POC_XORLW] = &pciXORLW;
1484         pic14Mnemonics[POC_XORWF] = &pciXORWF;
1485         pic14Mnemonics[POC_XORFW] = &pciXORFW;
1486         pic14Mnemonics[POC_BANKSEL] = &pciBANKSEL;
1487         pic14Mnemonics[POC_PAGESEL] = &pciPAGESEL;
1488         
1489         for(i=0; i<MAX_PIC14MNEMONICS; i++)
1490                 if(pic14Mnemonics[i])
1491                         hTabAddItem(&pic14MnemonicsHash, mnem2key((unsigned char *)pic14Mnemonics[i]->mnemonic), pic14Mnemonics[i]);
1492                 pci = hTabFirstItem(pic14MnemonicsHash, &key);
1493                 
1494                 while(pci) {
1495                         DFPRINTF((stderr, "element %d key %d, mnem %s\n",i++,key,pci->mnemonic));
1496                         pci = hTabNextItem(pic14MnemonicsHash, &key);
1497                 }
1498                 
1499                 mnemonics_initialized = 1;
1500 }
1501
1502 int getpCodePeepCommand(char *cmd);
1503
1504 int getpCode(char *mnem,unsigned dest)
1505 {
1506         
1507         pCodeInstruction *pci;
1508         int key = mnem2key((unsigned char *)mnem);
1509         
1510         if(!mnemonics_initialized)
1511                 pic14initMnemonics();
1512         
1513         pci = hTabFirstItemWK(pic14MnemonicsHash, key);
1514         
1515         while(pci) {
1516                 
1517                 if(STRCASECMP(pci->mnemonic, mnem) == 0) {
1518                         if((pci->num_ops <= 1) || (pci->isModReg == dest) || (pci->isBitInst))
1519                                 return(pci->op);
1520                 }
1521                 
1522                 pci = hTabNextItemWK (pic14MnemonicsHash);
1523                 
1524         }
1525         
1526         return -1;
1527 }
1528
1529 /*-----------------------------------------------------------------*
1530 * pic14initpCodePeepCommands
1531 *
1532 *-----------------------------------------------------------------*/
1533 void pic14initpCodePeepCommands(void)
1534 {
1535         
1536         int key, i;
1537         peepCommand *pcmd;
1538         
1539         i = 0;
1540         do {
1541                 hTabAddItem(&pic14pCodePeepCommandsHash, 
1542                         mnem2key((unsigned char *)peepCommands[i].cmd), &peepCommands[i]);
1543                 i++;
1544         } while (peepCommands[i].cmd);
1545         
1546         pcmd = hTabFirstItem(pic14pCodePeepCommandsHash, &key);
1547         
1548         while(pcmd) {
1549                 //fprintf(stderr, "peep command %s  key %d\n",pcmd->cmd,pcmd->id);
1550                 pcmd = hTabNextItem(pic14pCodePeepCommandsHash, &key);
1551         }
1552         
1553 }
1554
1555 /*-----------------------------------------------------------------
1556 *
1557 *
1558 *-----------------------------------------------------------------*/
1559
1560 int getpCodePeepCommand(char *cmd)
1561 {
1562         
1563         peepCommand *pcmd;
1564         int key = mnem2key((unsigned char *)cmd);
1565         
1566         
1567         pcmd = hTabFirstItemWK(pic14pCodePeepCommandsHash, key);
1568         
1569         while(pcmd) {
1570                 // fprintf(stderr," comparing %s to %s\n",pcmd->cmd,cmd);
1571                 if(STRCASECMP(pcmd->cmd, cmd) == 0) {
1572                         return pcmd->id;
1573                 }
1574                 
1575                 pcmd = hTabNextItemWK (pic14pCodePeepCommandsHash);
1576                 
1577         }
1578         
1579         return -1;
1580 }
1581
1582 char getpBlock_dbName(pBlock *pb)
1583 {
1584         if(!pb)
1585                 return 0;
1586         
1587         if(pb->cmemmap)
1588                 return pb->cmemmap->dbName;
1589         
1590         return pb->dbName;
1591 }
1592 void pBlockConvert2ISR(pBlock *pb)
1593 {
1594         if(!pb)
1595                 return;
1596         
1597         if(pb->cmemmap)
1598                 pb->cmemmap = NULL;
1599         
1600         pb->dbName = 'I';
1601 }
1602
1603 /*-----------------------------------------------------------------*/
1604 /* movepBlock2Head - given the dbname of a pBlock, move all        */
1605 /*                   instances to the front of the doubly linked   */
1606 /*                   list of pBlocks                               */
1607 /*-----------------------------------------------------------------*/
1608
1609 void movepBlock2Head(char dbName)
1610 {
1611         pBlock *pb;
1612         
1613         if (!the_pFile)
1614                 return;
1615         
1616         pb = the_pFile->pbHead;
1617         
1618         while(pb) {
1619                 
1620                 if(getpBlock_dbName(pb) == dbName) {
1621                         pBlock *pbn = pb->next;
1622                         pb->next = the_pFile->pbHead;
1623                         the_pFile->pbHead->prev = pb;
1624                         the_pFile->pbHead = pb;
1625                         
1626                         if(pb->prev)
1627                                 pb->prev->next = pbn;
1628                         
1629                         // If the pBlock that we just moved was the last
1630                         // one in the link of all of the pBlocks, then we
1631                         // need to point the tail to the block just before
1632                         // the one we moved.
1633                         // Note: if pb->next is NULL, then pb must have 
1634                         // been the last pBlock in the chain.
1635                         
1636                         if(pbn)
1637                                 pbn->prev = pb->prev;
1638                         else
1639                                 the_pFile->pbTail = pb->prev;
1640                         
1641                         pb = pbn;
1642                         
1643                 } else
1644                         pb = pb->next;
1645                 
1646         }
1647         
1648 }
1649
1650 void copypCode(FILE *of, char dbName)
1651 {
1652         pBlock *pb;
1653         
1654         if(!of || !the_pFile)
1655                 return;
1656
1657         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1658                 if(getpBlock_dbName(pb) == dbName) {
1659                         pBlockStats(of,pb);
1660                         printpBlock(of,pb);
1661                         fprintf (of, "\n");
1662                 }
1663         }
1664         
1665 }
1666
1667 void resetpCodeStatistics (void)
1668 {
1669   pcode_insns = pcode_doubles = 0;
1670 }
1671
1672 void dumppCodeStatistics (FILE *of)
1673 {
1674         /* dump statistics */
1675         fprintf (of, "\n");
1676         fprintf (of, ";\tcode size estimation:\n");
1677         fprintf (of, ";\t%5u+%5u = %5u instructions (%5u byte)\n", pcode_insns, pcode_doubles, pcode_insns + pcode_doubles, 2*(pcode_insns + 2*pcode_doubles));
1678         fprintf (of, "\n");
1679 }
1680
1681 void pcode_test(void)
1682 {
1683         
1684         DFPRINTF((stderr,"pcode is alive!\n"));
1685         
1686         //initMnemonics();
1687         
1688         if(the_pFile) {
1689                 
1690                 pBlock *pb;
1691                 FILE *pFile;
1692                 char buffer[100];
1693                 
1694                 /* create the file name */
1695                 strcpy(buffer,dstFileName);
1696                 strcat(buffer,".p");
1697                 
1698                 if( !(pFile = fopen(buffer, "w" ))) {
1699                         werror(E_FILE_OPEN_ERR,buffer);
1700                         exit(1);
1701                 }
1702                 
1703                 fprintf(pFile,"pcode dump\n\n");
1704                 
1705                 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
1706                         fprintf(pFile,"\n\tNew pBlock\n\n");
1707                         if(pb->cmemmap)
1708                                 fprintf(pFile,"%s",pb->cmemmap->sname);
1709                         else
1710                                 fprintf(pFile,"internal pblock");
1711                         
1712                         fprintf(pFile,", dbName =%c\n",getpBlock_dbName(pb));
1713                         printpBlock(pFile,pb);
1714                 }
1715         }
1716 }
1717 /*-----------------------------------------------------------------*/
1718 /* int RegCond(pCodeOp *pcop) - if pcop points to the STATUS reg-  */
1719 /*      ister, RegCond will return the bit being referenced.       */
1720 /*                                                                 */
1721 /* fixme - why not just OR in the pcop bit field                   */
1722 /*-----------------------------------------------------------------*/
1723
1724 static int RegCond(pCodeOp *pcop)
1725 {
1726         
1727         if(!pcop)
1728                 return 0;
1729         
1730         if (pcop->type == PO_GPR_BIT) {
1731                 char *name = pcop->name;
1732                 if (!name) 
1733                         name = PCOR(pcop)->r->name;
1734                 if (strcmp(name, pc_status.pcop.name) == 0)
1735                 {
1736                         switch(PCORB(pcop)->bit) {
1737                         case PIC_C_BIT:
1738                                 return PCC_C;
1739                         case PIC_DC_BIT:
1740                                 return PCC_DC;
1741                         case PIC_Z_BIT:
1742                                 return PCC_Z;
1743                         }
1744                 }
1745         }
1746         
1747         return 0;
1748 }
1749
1750 /*-----------------------------------------------------------------*/
1751 /* newpCode - create and return a newly initialized pCode          */
1752 /*                                                                 */
1753 /*  fixme - rename this                                            */
1754 /*                                                                 */
1755 /* The purpose of this routine is to create a new Instruction      */
1756 /* pCode. This is called by gen.c while the assembly code is being */
1757 /* generated.                                                      */
1758 /*                                                                 */
1759 /* Inouts:                                                         */
1760 /*  PIC_OPCODE op - the assembly instruction we wish to create.    */
1761 /*                  (note that the op is analogous to but not the  */
1762 /*                  same thing as the opcode of the instruction.)  */
1763 /*  pCdoeOp *pcop - pointer to the operand of the instruction.     */
1764 /*                                                                 */
1765 /* Outputs:                                                        */
1766 /*  a pointer to the new malloc'd pCode is returned.               */
1767 /*                                                                 */
1768 /*                                                                 */
1769 /*                                                                 */
1770 /*-----------------------------------------------------------------*/
1771 pCode *newpCode (PIC_OPCODE op, pCodeOp *pcop)
1772 {
1773         pCodeInstruction *pci ;
1774         
1775         if(!mnemonics_initialized)
1776                 pic14initMnemonics();
1777         
1778         pci = Safe_calloc(1, sizeof(pCodeInstruction));
1779         
1780         if((op>=0) && (op < MAX_PIC14MNEMONICS) && pic14Mnemonics[op]) {
1781                 memcpy(pci, pic14Mnemonics[op], sizeof(pCodeInstruction));
1782                 pci->pc.id = PCodeID();
1783                 pci->pcop = pcop;
1784                 
1785                 if(pci->inCond & PCC_EXAMINE_PCOP)
1786                         pci->inCond  |= RegCond(pcop);
1787                 
1788                 if(pci->outCond & PCC_EXAMINE_PCOP)
1789                         pci->outCond  |= RegCond(pcop);
1790                 
1791                 pci->pc.prev = pci->pc.next = NULL;
1792                 return (pCode *)pci;
1793         }
1794         
1795         fprintf(stderr, "pCode mnemonic error %s,%d\n",__FUNCTION__,__LINE__);
1796         exit(1);
1797         
1798         return NULL;
1799 }       
1800
1801 /*-----------------------------------------------------------------*/
1802 /* newpCodeWild - create a "wild" as in wild card pCode            */
1803 /*                                                                 */
1804 /* Wild pcodes are used during the peep hole optimizer to serve    */
1805 /* as place holders for any instruction. When a snippet of code is */
1806 /* compared to a peep hole rule, the wild card opcode will match   */
1807 /* any instruction. However, the optional operand and label are    */
1808 /* additional qualifiers that must also be matched before the      */
1809 /* line (of assembly code) is declared matched. Note that the      */
1810 /* operand may be wild too.                                        */
1811 /*                                                                 */
1812 /*   Note, a wild instruction is specified just like a wild var:   */
1813 /*      %4     ; A wild instruction,                               */
1814 /*  See the peeph.def file for additional examples                 */
1815 /*                                                                 */
1816 /*-----------------------------------------------------------------*/
1817
1818 pCode *newpCodeWild(int pCodeID, pCodeOp *optional_operand, pCodeOp *optional_label)
1819 {
1820         
1821         pCodeWild *pcw;
1822         
1823         pcw = Safe_calloc(1,sizeof(pCodeWild));
1824         
1825         pcw->pci.pc.type = PC_WILD;
1826         pcw->pci.pc.prev = pcw->pci.pc.next = NULL;
1827         pcw->id = PCodeID();
1828         pcw->pci.from = pcw->pci.to = pcw->pci.label = NULL;
1829         pcw->pci.pc.pb = NULL;
1830         
1831         //  pcw->pci.pc.analyze = genericAnalyze;
1832         pcw->pci.pc.destruct = genericDestruct;
1833         pcw->pci.pc.print = genericPrint;
1834         
1835         pcw->id = pCodeID;              // this is the 'n' in %n
1836         pcw->operand = optional_operand;
1837         pcw->label   = optional_label;
1838         
1839         pcw->mustBeBitSkipInst = 0;
1840         pcw->mustNotBeBitSkipInst = 0;
1841         pcw->invertBitSkipInst = 0;
1842         
1843         return ( (pCode *)pcw);
1844         
1845 }
1846
1847 /*-----------------------------------------------------------------*/
1848 /* newPcodeInlineP - create a new pCode from a char string           */
1849 /*-----------------------------------------------------------------*/
1850
1851
1852 pCode *newpCodeInlineP(char *cP)
1853 {
1854         
1855         pCodeComment *pcc ;
1856         
1857         pcc = Safe_calloc(1,sizeof(pCodeComment));
1858         
1859         pcc->pc.type = PC_INLINE;
1860         pcc->pc.prev = pcc->pc.next = NULL;
1861         pcc->pc.id = PCodeID();
1862         //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1863         pcc->pc.pb = NULL;
1864         
1865         //  pcc->pc.analyze = genericAnalyze;
1866         pcc->pc.destruct = genericDestruct;
1867         pcc->pc.print = genericPrint;
1868         
1869         if(cP)
1870                 pcc->comment = Safe_strdup(cP);
1871         else
1872                 pcc->comment = NULL;
1873         
1874         return ( (pCode *)pcc);
1875         
1876 }
1877
1878 /*-----------------------------------------------------------------*/
1879 /* newPcodeCharP - create a new pCode from a char string           */
1880 /*-----------------------------------------------------------------*/
1881
1882 pCode *newpCodeCharP(char *cP)
1883 {
1884         
1885         pCodeComment *pcc ;
1886         
1887         pcc = Safe_calloc(1,sizeof(pCodeComment));
1888         
1889         pcc->pc.type = PC_COMMENT;
1890         pcc->pc.prev = pcc->pc.next = NULL;
1891         pcc->pc.id = PCodeID();
1892         //pcc->pc.from = pcc->pc.to = pcc->pc.label = NULL;
1893         pcc->pc.pb = NULL;
1894         
1895         //  pcc->pc.analyze = genericAnalyze;
1896         pcc->pc.destruct = genericDestruct;
1897         pcc->pc.print = genericPrint;
1898         
1899         if(cP)
1900                 pcc->comment = Safe_strdup(cP);
1901         else
1902                 pcc->comment = NULL;
1903         
1904         return ( (pCode *)pcc);
1905         
1906 }
1907
1908 /*-----------------------------------------------------------------*/
1909 /* newpCodeFunction -                                              */
1910 /*-----------------------------------------------------------------*/
1911
1912
1913 pCode *newpCodeFunction(char *mod,char *f,int isPublic)
1914 {
1915         pCodeFunction *pcf;
1916         
1917         pcf = Safe_calloc(1,sizeof(pCodeFunction));
1918         //_ALLOC(pcf,sizeof(pCodeFunction));
1919         
1920         pcf->pc.type = PC_FUNCTION;
1921         pcf->pc.prev = pcf->pc.next = NULL;
1922         pcf->pc.id = PCodeID();
1923         //pcf->pc.from = pcf->pc.to = pcf->pc.label = NULL;
1924         pcf->pc.pb = NULL;
1925         
1926         //  pcf->pc.analyze = genericAnalyze;
1927         pcf->pc.destruct = genericDestruct;
1928         pcf->pc.print = pCodePrintFunction;
1929         
1930         pcf->ncalled = 0;
1931         
1932         if(mod) {
1933                 //_ALLOC_ATOMIC(pcf->modname,strlen(mod)+1);
1934                 pcf->modname = Safe_calloc(1,strlen(mod)+1);
1935                 strcpy(pcf->modname,mod);
1936         } else
1937                 pcf->modname = NULL;
1938         
1939         if(f) {
1940                 //_ALLOC_ATOMIC(pcf->fname,strlen(f)+1);
1941                 pcf->fname = Safe_calloc(1,strlen(f)+1);
1942                 strcpy(pcf->fname,f);
1943         } else
1944                 pcf->fname = NULL;
1945         
1946         pcf->isPublic = (unsigned)isPublic;
1947         
1948         return ( (pCode *)pcf);
1949         
1950 }
1951
1952 /*-----------------------------------------------------------------*/
1953 /* newpCodeFlow                                                    */
1954 /*-----------------------------------------------------------------*/
1955 void destructpCodeFlow(pCode *pc)
1956 {
1957         if(!pc || !isPCFL(pc))
1958                 return;
1959         
1960                 /*
1961                 if(PCFL(pc)->from)
1962                 if(PCFL(pc)->to)
1963         */
1964         unlinkpCode(pc);
1965         
1966         deleteSet(&PCFL(pc)->registers);
1967         deleteSet(&PCFL(pc)->from);
1968         deleteSet(&PCFL(pc)->to);
1969         free(pc);
1970         
1971 }
1972
1973 pCode *newpCodeFlow(void )
1974 {
1975         pCodeFlow *pcflow;
1976         
1977         //_ALLOC(pcflow,sizeof(pCodeFlow));
1978         pcflow = Safe_calloc(1,sizeof(pCodeFlow));
1979         
1980         pcflow->pc.type = PC_FLOW;
1981         pcflow->pc.prev = pcflow->pc.next = NULL;
1982         pcflow->pc.pb = NULL;
1983         
1984         //  pcflow->pc.analyze = genericAnalyze;
1985         pcflow->pc.destruct = destructpCodeFlow;
1986         pcflow->pc.print = genericPrint;
1987         
1988         pcflow->pc.seq = GpcFlowSeq++;
1989         
1990         pcflow->from = pcflow->to = NULL;
1991         
1992         pcflow->inCond = PCC_NONE;
1993         pcflow->outCond = PCC_NONE;
1994         
1995         pcflow->firstBank = 'U'; /* Undetermined */
1996         pcflow->lastBank = 'U'; /* Undetermined */
1997         
1998         pcflow->FromConflicts = 0;
1999         pcflow->ToConflicts = 0;
2000         
2001         pcflow->end = NULL;
2002         
2003         pcflow->registers = newSet();
2004         
2005         return ( (pCode *)pcflow);
2006         
2007 }
2008
2009 /*-----------------------------------------------------------------*/
2010 /*-----------------------------------------------------------------*/
2011 pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow)
2012 {
2013         pCodeFlowLink *pcflowLink;
2014         
2015         pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink));
2016         
2017         pcflowLink->pcflow = pcflow;
2018         pcflowLink->bank_conflict = 0;
2019         
2020         return pcflowLink;
2021 }
2022
2023 /*-----------------------------------------------------------------*/
2024 /* newpCodeCSource - create a new pCode Source Symbol              */
2025 /*-----------------------------------------------------------------*/
2026
2027 pCode *newpCodeCSource(int ln, char *f, const char *l)
2028 {
2029         
2030         pCodeCSource *pccs;
2031         
2032         pccs = Safe_calloc(1,sizeof(pCodeCSource));
2033         
2034         pccs->pc.type = PC_CSOURCE;
2035         pccs->pc.prev = pccs->pc.next = NULL;
2036         pccs->pc.id = PCodeID();
2037         pccs->pc.pb = NULL;
2038         
2039         pccs->pc.destruct = genericDestruct;
2040         pccs->pc.print = genericPrint;
2041         
2042         pccs->line_number = ln;
2043         if(l)
2044                 pccs->line = Safe_strdup(l);
2045         else
2046                 pccs->line = NULL;
2047         
2048         if(f)
2049                 pccs->file_name = Safe_strdup(f);
2050         else
2051                 pccs->file_name = NULL;
2052         
2053         return ( (pCode *)pccs);
2054         
2055 }
2056
2057 /*******************************************************************/
2058 /* pic16_newpCodeAsmDir - create a new pCode Assembler Directive   */
2059 /*                        added by VR 6-Jun-2003                   */
2060 /*******************************************************************/
2061
2062 pCode *newpCodeAsmDir(char *asdir, char *argfmt, ...)
2063 {
2064   pCodeAsmDir *pcad;
2065   va_list ap;
2066   char buffer[512];
2067   char *lbp=buffer;
2068
2069   pcad = Safe_calloc(1, sizeof(pCodeAsmDir));
2070   pcad->pci.pc.type = PC_ASMDIR;
2071   pcad->pci.pc.prev = pcad->pci.pc.next = NULL;
2072   pcad->pci.pc.pb = NULL;
2073   pcad->pci.pc.destruct = genericDestruct;
2074   pcad->pci.pc.print = genericPrint;
2075
2076   if(asdir && *asdir) {
2077
2078     while(isspace((unsigned char)*asdir))asdir++;       // strip any white space from the beginning
2079
2080     pcad->directive = Safe_strdup( asdir );
2081   }
2082
2083   va_start(ap, argfmt);
2084
2085   memset(buffer, 0, sizeof(buffer));
2086   if(argfmt && *argfmt)
2087     vsprintf(buffer, argfmt, ap);
2088
2089   va_end(ap);
2090
2091   while(isspace((unsigned char)*lbp))lbp++;
2092
2093   if(lbp && *lbp)
2094     pcad->arg = Safe_strdup( lbp );
2095
2096   return ((pCode *)pcad);
2097 }
2098
2099 /*-----------------------------------------------------------------*/
2100 /* pCodeLabelDestruct - free memory used by a label.               */
2101 /*-----------------------------------------------------------------*/
2102 static void pCodeLabelDestruct(pCode *pc)
2103 {
2104         
2105         if(!pc)
2106                 return;
2107         
2108         if((pc->type == PC_LABEL) && PCL(pc)->label)
2109                 free(PCL(pc)->label);
2110         
2111         free(pc);
2112         
2113 }
2114
2115 pCode *newpCodeLabel(char *name, int key)
2116 {
2117         
2118         char *s = buffer;
2119         pCodeLabel *pcl;
2120         
2121         pcl = Safe_calloc(1,sizeof(pCodeLabel) );
2122         
2123         pcl->pc.type = PC_LABEL;
2124         pcl->pc.prev = pcl->pc.next = NULL;
2125         pcl->pc.id = PCodeID();
2126         //pcl->pc.from = pcl->pc.to = pcl->pc.label = NULL;
2127         pcl->pc.pb = NULL;
2128         
2129         //  pcl->pc.analyze = genericAnalyze;
2130         pcl->pc.destruct = pCodeLabelDestruct;
2131         pcl->pc.print = pCodePrintLabel;
2132         
2133         pcl->key = key;
2134         
2135         pcl->label = NULL;
2136         if(key>0) {
2137                 sprintf(s,"_%05d_DS_",key);
2138         } else
2139                 s = name;
2140         
2141         if(s)
2142                 pcl->label = Safe_strdup(s);
2143         
2144         //fprintf(stderr,"newpCodeLabel: key=%d, name=%s\n",key, ((s)?s:""));
2145         return ( (pCode *)pcl);
2146         
2147 }
2148
2149
2150 /*-----------------------------------------------------------------*/
2151 /* newpBlock - create and return a pointer to a new pBlock         */
2152 /*-----------------------------------------------------------------*/
2153 pBlock *newpBlock(void)
2154 {
2155         
2156         pBlock *PpB;
2157         
2158         PpB = Safe_calloc(1,sizeof(pBlock) );
2159         PpB->next = PpB->prev = NULL;
2160         
2161         PpB->function_entries = PpB->function_exits = PpB->function_calls = NULL;
2162         PpB->tregisters = NULL;
2163         PpB->visited = 0;
2164         PpB->FlowTree = NULL;
2165         
2166         return PpB;
2167         
2168 }
2169
2170 /*-----------------------------------------------------------------*/
2171 /* newpCodeChain - create a new chain of pCodes                    */
2172 /*-----------------------------------------------------------------*
2173 *
2174 *  This function will create a new pBlock and the pointer to the
2175 *  pCode that is passed in will be the first pCode in the block.
2176 *-----------------------------------------------------------------*/
2177
2178
2179 pBlock *newpCodeChain(memmap *cm,char c, pCode *pc)
2180 {
2181         
2182         pBlock *pB  = newpBlock();
2183         
2184         pB->pcHead  = pB->pcTail = pc;
2185         pB->cmemmap = cm;
2186         pB->dbName  = c;
2187         
2188         return pB;
2189 }
2190
2191 /*-----------------------------------------------------------------*/
2192 /* newpCodeOpLabel - Create a new label given the key              */
2193 /*  Note, a negative key means that the label is part of wild card */
2194 /*  (and hence a wild card label) used in the pCodePeep            */
2195 /*   optimizations).                                               */
2196 /*-----------------------------------------------------------------*/
2197
2198 pCodeOp *newpCodeOpLabel(char *name, int key)
2199 {
2200         char *s=NULL;
2201         static int label_key=-1;
2202         
2203         pCodeOp *pcop;
2204         
2205         pcop = Safe_calloc(1,sizeof(pCodeOpLabel) );
2206         pcop->type = PO_LABEL;
2207         
2208         pcop->name = NULL;
2209         
2210         if(key>0)
2211                 sprintf(s=buffer,"_%05d_DS_",key);
2212         else 
2213                 s = name, key = label_key--;
2214         
2215         PCOLAB(pcop)->offset = 0;
2216         if(s)
2217                 pcop->name = Safe_strdup(s);
2218         
2219         ((pCodeOpLabel *)pcop)->key = key;
2220         
2221         //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
2222         return pcop;
2223 }
2224
2225 /*-----------------------------------------------------------------*/
2226 /*-----------------------------------------------------------------*/
2227 pCodeOp *newpCodeOpLit(int lit)
2228 {
2229         char *s = buffer;
2230         pCodeOp *pcop;
2231         
2232         
2233         pcop = Safe_calloc(1,sizeof(pCodeOpLit) );
2234         pcop->type = PO_LITERAL;
2235         
2236         pcop->name = NULL;
2237         if(lit>=0) {
2238                 sprintf(s,"0x%02x", (unsigned char)lit);
2239                 if(s)
2240                         pcop->name = Safe_strdup(s);
2241         }
2242         
2243         ((pCodeOpLit *)pcop)->lit = (unsigned char)lit;
2244         
2245         return pcop;
2246 }
2247
2248 /*-----------------------------------------------------------------*/
2249 /*-----------------------------------------------------------------*/
2250 pCodeOp *newpCodeOpImmd(char *name, int offset, int index, int code_space, int is_func)
2251 {
2252         pCodeOp *pcop;
2253         
2254         pcop = Safe_calloc(1,sizeof(pCodeOpImmd) );
2255         pcop->type = PO_IMMEDIATE;
2256         if(name) {
2257                 regs *r = NULL;
2258                 pcop->name = Safe_strdup(name);
2259                 
2260                 if(!is_func) 
2261                         r = dirregWithName(name);
2262                 
2263                 PCOI(pcop)->r = r;
2264                 if(r) {
2265                         //fprintf(stderr, " newpCodeOpImmd reg %s exists\n",name);
2266                         PCOI(pcop)->rIdx = r->rIdx;
2267                 } else {
2268                         //fprintf(stderr, " newpCodeOpImmd reg %s doesn't exist\n",name);
2269                         PCOI(pcop)->rIdx = -1;
2270                 }
2271                 //fprintf(stderr,"%s %s %d\n",__FUNCTION__,name,offset);
2272         } else {
2273                 pcop->name = NULL;
2274         }
2275         
2276         PCOI(pcop)->index = index;
2277         PCOI(pcop)->offset = offset;
2278         PCOI(pcop)->_const = code_space;
2279         PCOI(pcop)->_function = is_func;
2280         
2281         return pcop;
2282 }
2283
2284 /*-----------------------------------------------------------------*/
2285 /*-----------------------------------------------------------------*/
2286 pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype)
2287 {
2288         char *s = buffer;
2289         pCodeOp *pcop;
2290         
2291         
2292         if(!pcwb || !subtype) {
2293                 fprintf(stderr, "Wild opcode declaration error: %s-%d\n",__FILE__,__LINE__);
2294                 exit(1);
2295         }
2296         
2297         pcop = Safe_calloc(1,sizeof(pCodeOpWild));
2298         pcop->type = PO_WILD;
2299         sprintf(s,"%%%d",id);
2300         pcop->name = Safe_strdup(s);
2301         
2302         PCOW(pcop)->id = id;
2303         PCOW(pcop)->pcwb = pcwb;
2304         PCOW(pcop)->subtype = subtype;
2305         PCOW(pcop)->matched = NULL;
2306         
2307         return pcop;
2308 }
2309 /*-----------------------------------------------------------------*/
2310 /* Find a symbol with matching name                                */
2311 /*-----------------------------------------------------------------*/
2312 static symbol *symFindWithName(memmap * map, const char *name)
2313 {
2314         symbol *sym;
2315         
2316         for (sym = setFirstItem(map->syms); sym; sym = setNextItem (map->syms)) {
2317                 if (sym->rname && (strcmp(sym->rname,name)==0))
2318                         return sym;
2319         }
2320         return 0;
2321 }
2322
2323 /*-----------------------------------------------------------------*/
2324 /*-----------------------------------------------------------------*/
2325 pCodeOp *newpCodeOpBit(char *name, int ibit, int inBitSpace)
2326 {
2327         pCodeOp *pcop;
2328         struct regs *r = 0;
2329         
2330         pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2331         pcop->type = PO_GPR_BIT;
2332         
2333         PCORB(pcop)->bit = ibit;
2334         PCORB(pcop)->inBitSpace = inBitSpace;
2335         
2336         if (name) r = regFindWithName(name);
2337         if (!r) {
2338                 // Register has not been allocated - check for symbol information
2339                 symbol *sym;
2340                 sym = symFindWithName(bit, name);
2341                 if (!sym) sym = symFindWithName(sfrbit, name);
2342                 if (!sym) sym = symFindWithName(sfr, name);
2343                 if (!sym) sym = symFindWithName(reg, name);
2344                 // Hack to fix accesses to _INTCON_bits (e.g. GIE=0), see #1579535.
2345                 // XXX: This ignores nesting levels, but works for globals...
2346                 if (!sym) sym = findSym(SymbolTab, NULL, name);
2347                 if (!sym && name && name[0] == '_') sym = findSym(SymbolTab, NULL, &name[1]);
2348                 if (sym) {
2349                         r = allocNewDirReg(sym->etype,name);
2350                 }
2351         }
2352         if (r) {
2353                 pcop->name = NULL;
2354                 PCOR(pcop)->r = r;
2355                 PCOR(pcop)->rIdx = r->rIdx;
2356         } else {
2357                 pcop->name = Safe_strdup(name);   
2358                 PCOR(pcop)->r = NULL;
2359                 PCOR(pcop)->rIdx = 0;
2360         }
2361         return pcop;
2362 }
2363
2364 #if 0
2365 pCodeOp *newpCodeOpBitReg(regs *reg, int ibit, int inBitSpace)
2366 {
2367     pCodeOp *pcop;
2368
2369     assert(reg);
2370
2371     pcop = Safe_calloc(1,sizeof(pCodeOpRegBit));
2372     pcop->name = reg->name;
2373     pcop->type = PO_GPR_BIT;
2374     PCORB(pcop)->bit = ibit;
2375     PCORB(pcop)->inBitSpace = inBitSpace;
2376     PCOR(pcop)->r = reg;
2377     PCOR(pcop)->index = 0;
2378     PCOR(pcop)->rIdx = reg->rIdx;
2379     return pcop;
2380 }
2381 #endif
2382
2383 /*-----------------------------------------------------------------*
2384 * pCodeOp *newpCodeOpReg(int rIdx) - allocate a new register
2385 *
2386 * If rIdx >=0 then a specific register from the set of registers
2387 * will be selected. If rIdx <0, then a new register will be searched
2388 * for.
2389 *-----------------------------------------------------------------*/
2390
2391 pCodeOp *newpCodeOpReg(int rIdx)
2392 {
2393         pCodeOp *pcop;
2394         
2395         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2396         
2397         pcop->name = NULL;
2398         
2399         if(rIdx >= 0) {
2400                 PCOR(pcop)->rIdx = rIdx;
2401                 PCOR(pcop)->r = pic14_regWithIdx(rIdx);
2402         } else {
2403                 PCOR(pcop)->r = pic14_findFreeReg(REG_GPR);
2404                 
2405                 if(PCOR(pcop)->r)
2406                         PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2407         }
2408         
2409         if(PCOR(pcop)->r)
2410                 pcop->type = PCOR(pcop)->r->pc_type;
2411         
2412         return pcop;
2413 }
2414
2415 pCodeOp *newpCodeOpRegFromStr(char *name)
2416 {
2417         pCodeOp *pcop;
2418         
2419         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
2420         PCOR(pcop)->r = allocRegByName(name, 1);
2421         PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
2422         pcop->type = PCOR(pcop)->r->pc_type;
2423         pcop->name = PCOR(pcop)->r->name;
2424         
2425         return pcop;
2426 }
2427
2428 pCodeOp *newpCodeOpStr(char *name)
2429 {
2430         pCodeOp *pcop;
2431         
2432         pcop = Safe_calloc(1,sizeof(pCodeOpStr));
2433         pcop->type = PO_STR;
2434         pcop->name = Safe_strdup(name);   
2435         
2436         PCOS(pcop)->isPublic = 0;
2437         
2438         return pcop;
2439 }
2440
2441
2442 /*-----------------------------------------------------------------*/
2443 /*-----------------------------------------------------------------*/
2444
2445 pCodeOp *newpCodeOp(char *name, PIC_OPTYPE type)
2446 {
2447         pCodeOp *pcop;
2448         
2449         switch(type) {
2450         case PO_BIT:
2451         case PO_GPR_BIT:
2452                 pcop = newpCodeOpBit(name, -1,0);
2453                 break;
2454                 
2455         case PO_LITERAL:
2456                 pcop = newpCodeOpLit(-1);
2457                 break;
2458                 
2459         case PO_LABEL:
2460                 pcop = newpCodeOpLabel(NULL,-1);
2461                 break;
2462                 
2463         case PO_GPR_TEMP:
2464                 pcop = newpCodeOpReg(-1);
2465                 break;
2466                 
2467         case PO_GPR_POINTER:
2468         case PO_GPR_REGISTER:
2469                 if(name)
2470                         pcop = newpCodeOpRegFromStr(name);
2471                 else
2472                         pcop = newpCodeOpReg(-1);
2473                 break;
2474                 
2475         case PO_STR:
2476                 pcop = newpCodeOpStr(name);
2477                 break;
2478                 
2479         default:
2480                 pcop = Safe_calloc(1,sizeof(pCodeOp) );
2481                 pcop->type = type;
2482                 if(name)
2483                         pcop->name = Safe_strdup(name);   
2484                 else
2485                         pcop->name = NULL;
2486         }
2487         
2488         return pcop;
2489 }
2490
2491 /*-----------------------------------------------------------------*/
2492 /*-----------------------------------------------------------------*/
2493 void pCodeConstString(char *name, char *value)
2494 {
2495         pBlock *pb;
2496         unsigned i;
2497         
2498         //  fprintf(stderr, " %s  %s  %s\n",__FUNCTION__,name,value);
2499         
2500         if(!name || !value)
2501                 return;
2502         
2503         pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2504         
2505         addpBlock(pb);
2506         
2507         sprintf(buffer,"; %s = %s",name,value);
2508         for (i=strlen(buffer); i--; ) {
2509                 unsigned char c = buffer[i];
2510                 if (c=='\r' || c=='\n') {
2511                         memmove(buffer+i+1,buffer+i,strlen(buffer)-i+1);
2512                         buffer[i] = '\\';
2513                         if (c=='\r') buffer[i+1] = 'r';
2514                         else if (c=='\n') buffer[i+1] = 'n';
2515                 }
2516         }
2517         
2518         addpCode2pBlock(pb,newpCodeCharP(buffer));
2519         addpCode2pBlock(pb,newpCodeLabel(name,-1));
2520         
2521         do {
2522                 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(*value)));
2523         }while (*value++);
2524         
2525         
2526 }
2527
2528 /*-----------------------------------------------------------------*/
2529 /*-----------------------------------------------------------------*/
2530 void pCodeReadCodeTable(void)
2531 {
2532         pBlock *pb;
2533         
2534         fprintf(stderr, " %s\n",__FUNCTION__);
2535         
2536         pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block"));
2537         
2538         addpBlock(pb);
2539         
2540         addpCode2pBlock(pb,newpCodeCharP("; ReadCodeTable - built in function"));
2541         addpCode2pBlock(pb,newpCodeCharP("; Inputs: temp1,temp2 = code pointer"));
2542         addpCode2pBlock(pb,newpCodeCharP("; Outpus: W (from RETLW at temp2:temp1)"));
2543         addpCode2pBlock(pb,newpCodeLabel("ReadCodeTable:",-1));
2544         
2545         addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp2")));
2546         addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCLATH")));
2547         addpCode2pBlock(pb,newpCode(POC_MOVFW,newpCodeOpRegFromStr("temp1")));
2548         addpCode2pBlock(pb,newpCode(POC_MOVWF,newpCodeOpRegFromStr("PCL")));
2549         
2550         
2551 }
2552
2553 /*-----------------------------------------------------------------*/
2554 /* addpCode2pBlock - place the pCode into the pBlock linked list   */
2555 /*-----------------------------------------------------------------*/
2556 void addpCode2pBlock(pBlock *pb, pCode *pc)
2557 {
2558         
2559         if(!pc)
2560                 return;
2561         
2562         if(!pb->pcHead) {
2563         /* If this is the first pcode to be added to a block that
2564         * was initialized with a NULL pcode, then go ahead and
2565                 * make this pcode the head and tail */
2566                 pb->pcHead  = pb->pcTail = pc;
2567         } else {
2568                 //    if(pb->pcTail)
2569                 pb->pcTail->next = pc;
2570                 
2571                 pc->prev = pb->pcTail;
2572                 pc->pb = pb;
2573                 
2574                 pb->pcTail = pc;
2575         }
2576 }
2577
2578 /*-----------------------------------------------------------------*/
2579 /* addpBlock - place a pBlock into the pFile                       */
2580 /*-----------------------------------------------------------------*/
2581 void addpBlock(pBlock *pb)
2582 {
2583         // fprintf(stderr," Adding pBlock: dbName =%c\n",getpBlock_dbName(pb));
2584         
2585         if(!the_pFile) {
2586                 /* First time called, we'll pass through here. */
2587                 //_ALLOC(the_pFile,sizeof(pFile));
2588                 the_pFile = Safe_calloc(1,sizeof(pFile));
2589                 the_pFile->pbHead = the_pFile->pbTail = pb;
2590                 the_pFile->functions = NULL;
2591                 return;
2592         }
2593         
2594         the_pFile->pbTail->next = pb;
2595         pb->prev = the_pFile->pbTail;
2596         pb->next = NULL;
2597         the_pFile->pbTail = pb;
2598 }
2599
2600 /*-----------------------------------------------------------------*/
2601 /* removepBlock - remove a pBlock from the pFile                   */
2602 /*-----------------------------------------------------------------*/
2603 void removepBlock(pBlock *pb)
2604 {
2605         pBlock *pbs;
2606         
2607         if(!the_pFile)
2608                 return;
2609         
2610         
2611         //fprintf(stderr," Removing pBlock: dbName =%c\n",getpBlock_dbName(pb));
2612         
2613         for(pbs = the_pFile->pbHead; pbs; pbs = pbs->next) {
2614                 if(pbs == pb) {
2615                         
2616                         if(pbs == the_pFile->pbHead)
2617                                 the_pFile->pbHead = pbs->next;
2618                         
2619                         if (pbs == the_pFile->pbTail) 
2620                                 the_pFile->pbTail = pbs->prev;
2621                         
2622                         if(pbs->next)
2623                                 pbs->next->prev = pbs->prev;
2624                         
2625                         if(pbs->prev)
2626                                 pbs->prev->next = pbs->next;
2627                         
2628                         return;
2629                         
2630                 }
2631         }
2632         
2633         fprintf(stderr, "Warning: call to %s:%s didn't find pBlock\n",__FILE__,__FUNCTION__);
2634         
2635 }
2636
2637 /*-----------------------------------------------------------------*/
2638 /* printpCode - write the contents of a pCode to a file            */
2639 /*-----------------------------------------------------------------*/
2640 void printpCode(FILE *of, pCode *pc)
2641 {
2642         
2643         if(!pc || !of)
2644                 return;
2645         
2646         if(pc->print) {
2647                 pc->print(of,pc);
2648                 return;
2649         }
2650         
2651         fprintf(of,"warning - unable to print pCode\n");
2652 }
2653
2654 /*-----------------------------------------------------------------*/
2655 /* printpBlock - write the contents of a pBlock to a file          */
2656 /*-----------------------------------------------------------------*/
2657 void printpBlock(FILE *of, pBlock *pb)
2658 {
2659         pCode *pc;
2660         
2661         if(!pb)
2662                 return;
2663         
2664         if(!of)
2665                 of = stderr;
2666         
2667         for(pc = pb->pcHead; pc; pc = pc->next) {
2668                 printpCode(of,pc);
2669
2670                 if (isPCI(pc))
2671                 {
2672                         if (isPCI(pc) && (PCI(pc)->op == POC_PAGESEL || PCI(pc)->op == POC_BANKSEL)) {
2673                                 pcode_doubles++;
2674                         } else {
2675                                 pcode_insns++;
2676                         }
2677                 }
2678         } // for
2679
2680 }
2681
2682 /*-----------------------------------------------------------------*/
2683 /*                                                                 */
2684 /*       pCode processing                                          */
2685 /*                                                                 */
2686 /*                                                                 */
2687 /*                                                                 */
2688 /*-----------------------------------------------------------------*/
2689
2690 void unlinkpCode(pCode *pc)
2691 {
2692         
2693         
2694         if(pc) {
2695 #ifdef PCODE_DEBUG
2696                 fprintf(stderr,"Unlinking: ");
2697                 printpCode(stderr, pc);
2698 #endif
2699                 if(pc->prev) 
2700                         pc->prev->next = pc->next;
2701                 if(pc->next)
2702                         pc->next->prev = pc->prev;
2703
2704 #if 0
2705                 /* RN: I believe this should be right here, but this did not
2706                  *     cure the bug I was hunting... */
2707                 /* must keep labels -- attach to following instruction */
2708                 if (isPCI(pc) && PCI(pc)->label && pc->next)
2709                 {
2710                   pCodeInstruction *pcnext = PCI(findNextInstruction (pc->next));
2711                   if (pcnext)
2712                   {
2713                     pBranchAppend (pcnext->label, PCI(pc)->label);
2714                   }
2715                 }
2716 #endif
2717                 pc->prev = pc->next = NULL;
2718         }
2719 }
2720
2721 /*-----------------------------------------------------------------*/
2722 /*-----------------------------------------------------------------*/
2723
2724 static void genericDestruct(pCode *pc)
2725 {
2726         
2727         unlinkpCode(pc);
2728         
2729         if(isPCI(pc)) {
2730         /* For instructions, tell the register (if there's one used)
2731                 * that it's no longer needed */
2732                 regs *reg = getRegFromInstruction(pc);
2733                 if(reg)
2734                         deleteSetItem (&(reg->reglives.usedpCodes),pc);
2735         }
2736         
2737         /* Instead of deleting the memory used by this pCode, mark
2738         * the object as bad so that if there's a pointer to this pCode
2739         * dangling around somewhere then (hopefully) when the type is
2740         * checked we'll catch it.
2741         */
2742         
2743         pc->type = PC_BAD;
2744         
2745         addpCode2pBlock(pb_dead_pcodes, pc);
2746         
2747         //free(pc);
2748         
2749 }
2750
2751
2752 /*-----------------------------------------------------------------*/
2753 /*  Copies the pCodeInstruction flow pointer from source pCode     */
2754 /*-----------------------------------------------------------------*/
2755 static void CopyFlow(pCodeInstruction *pcd, pCode *pcs) {
2756         pCode *p;
2757         pCodeFlow *pcflow = 0;
2758         for (p=pcs; p; p=p->prev) {
2759                 if (isPCI(p)) {
2760                         pcflow = PCI(p)->pcflow;
2761                         break;
2762                 }
2763                 if (isPCF(p)) {
2764                         pcflow = (pCodeFlow*)p;
2765                         break;
2766                 }
2767         }
2768         PCI(pcd)->pcflow = pcflow;
2769 }
2770
2771 /*-----------------------------------------------------------------*/
2772 /*  pCodeInsertAfter - splice in the pCode chain starting with pc2 */
2773 /*                     into the pCode chain containing pc1         */
2774 /*-----------------------------------------------------------------*/
2775 void pCodeInsertAfter(pCode *pc1, pCode *pc2)
2776 {
2777         
2778         if(!pc1 || !pc2)
2779                 return;
2780         
2781         pc2->next = pc1->next;
2782         if(pc1->next)
2783                 pc1->next->prev = pc2;
2784         
2785         pc2->pb = pc1->pb;
2786         pc2->prev = pc1;
2787         pc1->next = pc2;
2788         
2789         /* If this is an instrution type propogate the flow */
2790         if (isPCI(pc2))
2791                 CopyFlow(PCI(pc2),pc1);
2792 }
2793
2794 /*------------------------------------------------------------------*/
2795 /*  pCodeInsertBefore - splice in the pCode chain starting with pc2 */
2796 /*                      into the pCode chain containing pc1         */
2797 /*------------------------------------------------------------------*/
2798 void pCodeInsertBefore(pCode *pc1, pCode *pc2)
2799 {
2800         
2801         if(!pc1 || !pc2)
2802                 return;
2803         
2804         pc2->prev = pc1->prev;
2805         if(pc1->prev)
2806                 pc1->prev->next = pc2;
2807         
2808         pc2->pb = pc1->pb;
2809         pc2->next = pc1;
2810         pc1->prev = pc2;
2811         
2812         /* If this is an instrution type propogate the flow */
2813         if (isPCI(pc2))
2814                 CopyFlow(PCI(pc2),pc1);
2815 }
2816
2817 /*-----------------------------------------------------------------*/
2818 /* pCodeOpCopy - copy a pcode operator                             */
2819 /*-----------------------------------------------------------------*/
2820 pCodeOp *pCodeOpCopy(pCodeOp *pcop)
2821 {
2822         pCodeOp *pcopnew=NULL;
2823         
2824         if(!pcop)
2825                 return NULL;
2826         
2827         switch(pcop->type) { 
2828         case PO_NONE:
2829         case PO_STR:
2830                 pcopnew = Safe_calloc (1, sizeof (pCodeOp));
2831                 memcpy (pcopnew, pcop, sizeof (pCodeOp));
2832                 break;
2833                 
2834         case PO_W:
2835         case PO_STATUS:
2836         case PO_FSR:
2837         case PO_INDF:
2838         case PO_INTCON:
2839         case PO_GPR_REGISTER:
2840         case PO_GPR_TEMP:
2841         case PO_GPR_POINTER:
2842         case PO_SFR_REGISTER:
2843         case PO_PCL:
2844         case PO_PCLATH:
2845         case PO_DIR:
2846                 //DFPRINTF((stderr,"pCodeOpCopy GPR register\n"));
2847                 pcopnew = Safe_calloc(1,sizeof(pCodeOpReg) );
2848                 memcpy (pcopnew, pcop, sizeof (pCodeOpReg));
2849                 DFPRINTF((stderr," register index %d\n", PCOR(pcop)->r->rIdx));
2850                 break;
2851
2852         case PO_LITERAL:
2853                 //DFPRINTF((stderr,"pCodeOpCopy lit\n"));
2854                 pcopnew = Safe_calloc(1,sizeof(pCodeOpLit) );
2855                 memcpy (pcopnew, pcop, sizeof (pCodeOpLit));
2856                 break;
2857                 
2858         case PO_IMMEDIATE:
2859                 pcopnew = Safe_calloc(1,sizeof(pCodeOpImmd) );
2860                 memcpy (pcopnew, pcop, sizeof (pCodeOpImmd));
2861                 break;
2862                 
2863         case PO_GPR_BIT:
2864         case PO_CRY:
2865         case PO_BIT:
2866                 //DFPRINTF((stderr,"pCodeOpCopy bit\n"));
2867                 pcopnew = Safe_calloc(1,sizeof(pCodeOpRegBit) );
2868                 memcpy (pcopnew, pcop, sizeof (pCodeOpRegBit));
2869                 break;
2870
2871         case PO_LABEL:
2872                 //DFPRINTF((stderr,"pCodeOpCopy label\n"));
2873                 pcopnew = Safe_calloc(1,sizeof(pCodeOpLabel) );
2874                 memcpy (pcopnew, pcop, sizeof(pCodeOpLabel));
2875                 break;
2876                 
2877         case PO_WILD:
2878                 /* Here we expand the wild card into the appropriate type: */
2879                 /* By recursively calling pCodeOpCopy */
2880                 //DFPRINTF((stderr,"pCodeOpCopy wild\n"));
2881                 if(PCOW(pcop)->matched)
2882                         pcopnew = pCodeOpCopy(PCOW(pcop)->matched);
2883                 else {
2884                         // Probably a label
2885                         pcopnew = pCodeOpCopy(PCOW(pcop)->subtype);
2886                         pcopnew->name = Safe_strdup(PCOW(pcop)->pcwb->vars[PCOW(pcop)->id]);
2887                         //DFPRINTF((stderr,"copied a wild op named %s\n",pcopnew->name));
2888                 }
2889                 
2890                 return pcopnew;
2891                 break;
2892
2893         default:
2894                 assert ( !"unhandled pCodeOp type copied" );
2895                 break;
2896         } // switch
2897         
2898         if(pcop->name)
2899                 pcopnew->name = Safe_strdup(pcop->name);
2900         else
2901                 pcopnew->name = NULL;
2902         
2903         return pcopnew;
2904 }
2905
2906 /*-----------------------------------------------------------------*/
2907 /* popCopyReg - copy a pcode operator                              */
2908 /*-----------------------------------------------------------------*/
2909 pCodeOp *popCopyReg(pCodeOpReg *pc)
2910 {
2911         pCodeOpReg *pcor;
2912         
2913         pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
2914         pcor->pcop.type = pc->pcop.type;
2915         if(pc->pcop.name) {
2916                 if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
2917                         fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
2918         } else
2919                 pcor->pcop.name = NULL;
2920         
2921         if (pcor->pcop.type == PO_IMMEDIATE){
2922                 PCOL(pcor)->lit = PCOL(pc)->lit;
2923         } else {
2924                 pcor->r = pc->r;
2925                 pcor->rIdx = pc->rIdx;
2926                 if (pcor->r)
2927                         pcor->r->wasUsed=1;
2928         }       
2929         //DEBUGpic14_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
2930         
2931         return PCOP(pcor);
2932 }
2933
2934 /*-----------------------------------------------------------------*/
2935 /* pCodeInstructionCopy - copy a pCodeInstructionCopy              */
2936 /*-----------------------------------------------------------------*/
2937 pCode *pCodeInstructionCopy(pCodeInstruction *pci,int invert)
2938 {
2939         pCodeInstruction *new_pci;
2940         
2941         if(invert)
2942                 new_pci = PCI(newpCode(pci->inverted_op,pci->pcop));
2943         else
2944                 new_pci = PCI(newpCode(pci->op,pci->pcop));
2945         
2946         new_pci->pc.pb = pci->pc.pb;
2947         new_pci->from = pci->from;
2948         new_pci->to   = pci->to;
2949         new_pci->label = pci->label;
2950         new_pci->pcflow = pci->pcflow;
2951         
2952         return PCODE(new_pci);
2953 }
2954
2955 /*-----------------------------------------------------------------*/
2956 /*-----------------------------------------------------------------*/
2957 void pCodeDeleteChain(pCode *f,pCode *t)
2958 {
2959         pCode *pc;
2960         
2961         while(f && f!=t) {
2962                 DFPRINTF((stderr,"delete pCode:\n"));
2963                 pc = f->next;
2964                 //f->print(stderr,f);
2965                 //f->delete(f);  this dumps core...
2966                 f = pc;
2967         }
2968 }
2969
2970 /*-----------------------------------------------------------------*/
2971 /*-----------------------------------------------------------------*/
2972 void pBlockRegs(FILE *of, pBlock *pb)
2973 {
2974         
2975         regs  *r;
2976         
2977         r = setFirstItem(pb->tregisters);
2978         while (r) {
2979                 r = setNextItem(pb->tregisters);
2980         }
2981 }
2982
2983
2984 /*-----------------------------------------------------------------*/
2985 /*-----------------------------------------------------------------*/
2986 char *get_op(pCodeOp *pcop,char *buffer, size_t size)
2987 {
2988         regs *r;
2989         static char b[50];
2990         char *s;
2991         int use_buffer = 1;    // copy the string to the passed buffer pointer
2992         
2993         if(!buffer) {
2994                 buffer = b;
2995                 size = sizeof(b);
2996                 use_buffer = 0;     // Don't bother copying the string to the buffer.
2997         } 
2998         
2999         if(pcop) {
3000                 switch(pcop->type) {
3001                 case PO_INDF:
3002                 case PO_FSR:
3003                         if(use_buffer) {
3004                                 SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3005                                 return buffer;
3006                         }
3007                         //return PCOR(pcop)->r->name;
3008                         return pcop->name;
3009                         break;
3010                 case PO_GPR_TEMP:
3011                         if (PCOR(pcop)->r->type == REG_STK)
3012                                 r = typeRegWithIdx(PCOR(pcop)->r->rIdx,REG_STK,1);
3013                         else
3014                                 r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
3015                         
3016                         if(use_buffer) {
3017                                 SAFE_snprintf(&buffer,&size,"%s",r->name);
3018                                 return buffer;
3019                         }
3020                         
3021                         return r->name;
3022                         
3023                         
3024                 case PO_IMMEDIATE:
3025                         s = buffer;
3026                         if(PCOI(pcop)->_const) {
3027                                 
3028                                 if( PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset<4) {
3029                                         switch(PCOI(pcop)->offset) {
3030                                         case 0:
3031                                                 SAFE_snprintf(&s,&size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
3032                                                 break;
3033                                         case 1:
3034                                                 SAFE_snprintf(&s,&size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
3035                                                 break;
3036                                         case 2:
3037                                                 SAFE_snprintf(&s,&size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
3038                                                 break;
3039                                         default:
3040                                                 fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset);
3041                                                 assert ( !"offset too large" );
3042                                                 SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
3043                                                         pcop->name,
3044                                                         PCOI(pcop)->index,
3045                                                         8 * PCOI(pcop)->offset );
3046                                         }
3047                                 } else
3048                                         SAFE_snprintf(&s,&size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
3049                         } else {
3050                                 if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4) 
3051                                         SAFE_snprintf(&s,&size,"(%s + %d)",
3052                                                 pcop->name,
3053                                                 PCOI(pcop)->index);
3054                                 } else {
3055                                         switch(PCOI(pcop)->offset) {
3056                                         case 0:
3057                                                 SAFE_snprintf(&s,&size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
3058                                                 break;
3059                                         case 1:
3060                                                 SAFE_snprintf(&s,&size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
3061                                                 break;
3062                                         case 2:
3063                                                 SAFE_snprintf(&s,&size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
3064                                                 break;
3065                                         default:
3066                                                 fprintf (stderr, "PO_IMMEDIATE/mutable/offset=%d\n", PCOI(pcop)->offset);
3067                                                 assert ( !"offset too large" );
3068                                                 SAFE_snprintf(&s,&size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
3069                                                 break;
3070                                         }
3071                                 }
3072                         }
3073                         
3074                         return buffer;
3075                         
3076                 case PO_DIR:
3077                         s = buffer;
3078                         //size = sizeof(buffer);
3079                         if( PCOR(pcop)->instance) {
3080                                 SAFE_snprintf(&s,&size,"(%s + %d)",
3081                                         pcop->name,
3082                                         PCOR(pcop)->instance );
3083                                 //fprintf(stderr,"PO_DIR %s\n",buffer);
3084                         } else
3085                                 SAFE_snprintf(&s,&size,"%s",pcop->name);
3086                         return buffer;
3087                         
3088                 case PO_LABEL:
3089                         s = buffer;
3090                         if  (pcop->name) {
3091                                 if(PCOLAB(pcop)->offset == 1)
3092                                         SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
3093                                 else
3094                                         SAFE_snprintf(&s,&size,"%s",pcop->name);
3095                         }
3096                         return buffer;
3097
3098                 case PO_GPR_BIT:
3099                         if(PCOR(pcop)->r) {
3100                                 if(use_buffer) {
3101                                         SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
3102                                         return buffer;
3103                                 }
3104                                 return PCOR(pcop)->r->name;
3105                         }
3106                         
3107                         /* fall through to the default case */
3108                 default:
3109                         if(pcop->name) {
3110                                 if(use_buffer) {
3111                                         SAFE_snprintf(&buffer,&size,"%s",pcop->name);
3112                                         return buffer;
3113                                 }
3114                                 return pcop->name;
3115                         }
3116                 }
3117         }
3118
3119         printf("PIC port internal warning: (%s:%d(%s)) %s not found\n",
3120           __FILE__, __LINE__, __FUNCTION__,
3121           pCodeOpType(pcop));
3122
3123         return "NO operand";
3124
3125 }
3126
3127 /*-----------------------------------------------------------------*/
3128 /*-----------------------------------------------------------------*/
3129 static char *get_op_from_instruction( pCodeInstruction *pcc)
3130 {
3131         
3132         if(pcc)
3133                 return get_op(pcc->pcop,NULL,0);
3134         
3135         return ("ERROR Null: get_op_from_instruction");
3136         
3137 }
3138
3139 /*-----------------------------------------------------------------*/
3140 /*-----------------------------------------------------------------*/
3141 static void pCodeOpPrint(FILE *of, pCodeOp *pcop)
3142 {
3143         fprintf(of,"pcodeopprint- not implemented\n");
3144 }
3145
3146 /*-----------------------------------------------------------------*/
3147 /* pCode2str - convert a pCode instruction to string               */
3148 /*-----------------------------------------------------------------*/
3149 char *pCode2str(char *str, size_t size, pCode *pc)
3150 {
3151   char *s = str;
3152
3153   switch(pc->type) {
3154
3155   case PC_OPCODE:
3156
3157     SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
3158
3159     if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
3160
3161       if(PCI(pc)->isBitInst) {
3162         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3163           char *name = PCI(pc)->pcop->name;
3164           if (!name)
3165             name = PCOR(PCI(pc)->pcop)->r->name;
3166           if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
3167             SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name);
3168           else
3169             SAFE_snprintf(&s,&size,"%s,%d", name, 
3170             (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
3171         } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3172           SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
3173       } else
3174           SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
3175         //PCI(pc)->pcop->t.bit );
3176       } else {
3177         if(PCI(pc)->pcop->type == PO_GPR_BIT) {
3178           if( PCI(pc)->num_ops == 2)
3179             SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
3180           else
3181             SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
3182         } else {
3183           SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
3184           if( PCI(pc)->num_ops == 2)
3185             SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
3186         }
3187       }
3188     }
3189     break;
3190
3191   case PC_COMMENT:
3192     /* assuming that comment ends with a \n */
3193     SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
3194     break;
3195
3196   case PC_INLINE:
3197     /* assuming that inline code ends with a \n */
3198     SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
3199     break;
3200
3201   case PC_LABEL:
3202     SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
3203     break;
3204   case PC_FUNCTION:
3205     SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
3206     break;
3207   case PC_WILD:
3208     SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
3209     break;
3210   case PC_FLOW:
3211     SAFE_snprintf(&s,&size,";\t--FLOW change\n");
3212     break;
3213   case PC_CSOURCE:
3214 //    SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3215     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);
3216     break;
3217   case PC_ASMDIR:
3218     if(PCAD(pc)->directive) {
3219       SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3220     } else if(PCAD(pc)->arg) {
3221       /* special case to handle inline labels without a tab */
3222       SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
3223     }
3224     break;
3225
3226   case PC_BAD:
3227     SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
3228   }
3229
3230   return str;
3231 }
3232
3233 /*-----------------------------------------------------------------*/
3234 /* genericPrint - the contents of a pCode to a file                */
3235 /*-----------------------------------------------------------------*/
3236 static void genericPrint(FILE *of, pCode *pc)
3237 {
3238   if(!pc || !of)
3239     return;
3240
3241   switch(pc->type) {
3242   case PC_COMMENT:
3243     fprintf(of,";%s\n", ((pCodeComment *)pc)->comment);
3244     break;
3245
3246   case PC_INLINE:
3247     fprintf(of,"%s\n", ((pCodeComment *)pc)->comment);
3248     break;
3249
3250   case PC_OPCODE:
3251     // If the opcode has a label, print that first
3252     {
3253       char str[256];
3254       pCodeInstruction *pci = PCI(pc);
3255       pBranch *pbl = pci->label;
3256       while(pbl && pbl->pc) {
3257         if(pbl->pc->type == PC_LABEL)
3258           pCodePrintLabel(of, pbl->pc);
3259         pbl = pbl->next;
3260       }
3261
3262       if(pci->cline)
3263         genericPrint(of,PCODE(pci->cline));
3264
3265
3266       pCode2str(str, 256, pc);
3267
3268       fprintf(of,"%s",str);
3269
3270       /* Debug */
3271       if(debug_verbose) {
3272         pCodeOpReg *pcor = PCOR(pci->pcop);
3273         fprintf(of, "\t;id=%u,key=%03x,inCond:%x,outCond:%x",pc->id,pc->seq, pci->inCond, pci->outCond);
3274         if(pci->pcflow)
3275           fprintf(of,",flow seq=%03x",pci->pcflow->pc.seq);
3276         if (pcor && pcor->pcop.type==PO_GPR_TEMP && !pcor->r->isFixed)
3277           fprintf(of,",rIdx=r0x%X",pcor->rIdx);
3278       }
3279     }
3280 #if 0
3281     {
3282       pBranch *dpb = pc->to;   // debug
3283       while(dpb) {
3284         switch ( dpb->pc->type) {
3285         case PC_OPCODE:
3286           fprintf(of, "\t;%s", PCI(dpb->pc)->mnemonic);
3287           break;
3288         case PC_LABEL:
3289           fprintf(of, "\t;label %d", PCL(dpb->pc)->key);
3290           break;
3291         case PC_FUNCTION:
3292           fprintf(of, "\t;function %s", ( (PCF(dpb->pc)->fname) ? (PCF(dpb->pc)->fname) : "[END]"));
3293           break;
3294         case PC_FLOW:
3295           fprintf(of, "\t;flow");
3296           break;
3297         case PC_COMMENT:
3298         case PC_WILD:
3299           break;
3300         }
3301         dpb = dpb->next;
3302       }
3303     }
3304 #endif
3305     fprintf(of,"\n");
3306     break;
3307
3308   case PC_WILD:
3309     fprintf(of,";\tWild opcode: id=%d\n",PCW(pc)->id);
3310     if(PCW(pc)->pci.label)
3311       pCodePrintLabel(of, PCW(pc)->pci.label->pc);
3312     
3313     if(PCW(pc)->operand) {
3314       fprintf(of,";\toperand  ");
3315       pCodeOpPrint(of,PCW(pc)->operand );
3316     }
3317     break;
3318
3319   case PC_FLOW:
3320     if(debug_verbose) {
3321       fprintf(of,";<>Start of new flow, seq=0x%x",pc->seq);
3322       if(PCFL(pc)->ancestor)
3323         fprintf(of," ancestor = 0x%x", PCODE(PCFL(pc)->ancestor)->seq);
3324       fprintf(of,"\n");
3325       fprintf(of,";  from: ");
3326       {
3327         pCodeFlowLink *link;
3328         for (link = setFirstItem(PCFL(pc)->from); link; link = setNextItem (PCFL(pc)->from))
3329         {
3330           fprintf(of,"%03x ",link->pcflow->pc.seq);
3331         }
3332       }
3333       fprintf(of,"; to: ");
3334       {
3335         pCodeFlowLink *link;
3336         for (link = setFirstItem(PCFL(pc)->to); link; link = setNextItem (PCFL(pc)->to))
3337         {
3338           fprintf(of,"%03x ",link->pcflow->pc.seq);
3339         }
3340       }
3341       fprintf(of,"\n");
3342     }
3343     break;
3344
3345   case PC_CSOURCE:
3346 //    fprintf(of,";#CSRC\t%s %d\n;  %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
3347     fprintf(of,"%s\t.line\t%d; \"%s\"\t%s\n", (options.debug?"":";"), PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
3348     break;
3349
3350   case PC_ASMDIR:
3351     {
3352       pBranch *pbl = PCAD(pc)->pci.label;
3353       while(pbl && pbl->pc) {
3354         if(pbl->pc->type == PC_LABEL)
3355           pCodePrintLabel(of, pbl->pc);
3356         pbl = pbl->next;
3357       }
3358     }
3359     if(PCAD(pc)->directive) {
3360       fprintf(of, "\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
3361     } else
3362     if(PCAD(pc)->arg) {
3363       /* special case to handle inline labels without tab */
3364       fprintf(of, "%s\n", PCAD(pc)->arg);
3365     }
3366     break;
3367
3368   case PC_LABEL:
3369   default:
3370     fprintf(of,"unknown pCode type %d\n",pc->type);
3371   }
3372 }
3373
3374 /*-----------------------------------------------------------------*/
3375 /* pCodePrintFunction - prints function begin/end                  */
3376 /*-----------------------------------------------------------------*/
3377
3378 static void pCodePrintFunction(FILE *of, pCode *pc)
3379 {
3380         
3381         if(!pc || !of)
3382                 return;
3383         
3384         if( ((pCodeFunction *)pc)->modname) 
3385                 fprintf(of,"F_%s",((pCodeFunction *)pc)->modname);
3386         
3387         if(PCF(pc)->fname) {
3388                 pBranch *exits = PCF(pc)->to;
3389                 int i=0;
3390                 fprintf(of,"%s\t;Function start\n",PCF(pc)->fname);
3391                 while(exits) {
3392                         i++;
3393                         exits = exits->next;
3394                 }
3395                 //if(i) i--;
3396                 fprintf(of,"; %d exit point%c\n",i, ((i==1) ? ' ':'s'));
3397                 
3398         }else {
3399                 if((PCF(pc)->from && 
3400                         PCF(pc)->from->pc->type == PC_FUNCTION &&
3401                         PCF(PCF(pc)->from->pc)->fname) )
3402                         fprintf(of,"; exit point of %s\n",PCF(PCF(pc)->from->pc)->fname);
3403                 else
3404                         fprintf(of,"; exit point [can't find entry point]\n");
3405         }
3406 }
3407 /*-----------------------------------------------------------------*/
3408 /* pCodePrintLabel - prints label                                  */
3409 /*-----------------------------------------------------------------*/
3410
3411 static void pCodePrintLabel(FILE *of, pCode *pc)
3412 {
3413         
3414         if(!pc || !of)
3415                 return;
3416         
3417         if(PCL(pc)->label) 
3418                 fprintf(of,"%s\n",PCL(pc)->label);
3419         else if (PCL(pc)->key >=0) 
3420                 fprintf(of,"_%05d_DS_:\n",PCL(pc)->key);
3421         else
3422                 fprintf(of,";wild card label: id=%d\n",-PCL(pc)->key);
3423         
3424 }
3425
3426 /*-----------------------------------------------------------------*/
3427 /* unlinkpCodeFromBranch - Search for a label in a pBranch and     */
3428 /*                         remove it if it is found.               */
3429 /*-----------------------------------------------------------------*/
3430 static void unlinkpCodeFromBranch(pCode *pcl , pCode *pc)
3431 {
3432   pBranch *b, *bprev;
3433
3434   bprev = NULL;
3435
3436   if(pcl->type == PC_OPCODE || pcl->type == PC_INLINE || pcl->type == PC_ASMDIR)
3437     b = PCI(pcl)->label;
3438   else {
3439     fprintf(stderr, "LINE %d. can't unlink from non opcode\n",__LINE__);
3440     exit(1);
3441   }
3442   
3443   //fprintf (stderr, "%s \n",__FUNCTION__);
3444   //pcl->print(stderr,pcl);
3445   //pc->print(stderr,pc);
3446   while(b) {
3447     if(b->pc == pc) {
3448       //fprintf (stderr, "found label\n");
3449       
3450       /* Found a label */
3451       if(bprev) {
3452         bprev->next = b->next;  /* Not first pCode in chain */
3453         free(b);
3454       } else {
3455         pc->destruct(pc);
3456         PCI(pcl)->label = b->next;   /* First pCode in chain */
3457         free(b);
3458       }
3459       return;  /* A label can't occur more than once */
3460     }
3461     bprev = b;
3462     b = b->next;
3463   }
3464 }
3465
3466 /*-----------------------------------------------------------------*/
3467 /*-----------------------------------------------------------------*/
3468 pBranch * pBranchAppend(pBranch *h, pBranch *n)
3469 {
3470         pBranch *b;
3471         
3472         if(!h)
3473                 return n;
3474         
3475         if(h == n)
3476                 return n;
3477         
3478         b = h;
3479         while(b->next)
3480                 b = b->next;
3481         
3482         b->next = n;
3483         
3484         return h;
3485         
3486 }  
3487 /*-----------------------------------------------------------------*/
3488 /* pBranchLink - given two pcodes, this function will link them    */
3489 /*               together through their pBranches                  */
3490 /*-----------------------------------------------------------------*/
3491 static void pBranchLink(pCodeFunction *f, pCodeFunction *t)
3492 {
3493         pBranch *b;
3494         
3495         // Declare a new branch object for the 'from' pCode.
3496         
3497         //_ALLOC(b,sizeof(pBranch));
3498         b = Safe_calloc(1,sizeof(pBranch));
3499         b->pc = PCODE(t);             // The link to the 'to' pCode.
3500         b->next = NULL;
3501         
3502         f->to = pBranchAppend(f->to,b);
3503         
3504         // Now do the same for the 'to' pCode.
3505         
3506         //_ALLOC(b,sizeof(pBranch));
3507         b = Safe_calloc(1,sizeof(pBranch));
3508         b->pc = PCODE(f);
3509         b->next = NULL;
3510         
3511         t->from = pBranchAppend(t->from,b);
3512         
3513 }
3514
3515 #if 0
3516 /*-----------------------------------------------------------------*/
3517 /* pBranchFind - find the pBranch in a pBranch chain that contains */
3518 /*               a pCode                                           */
3519 /*-----------------------------------------------------------------*/
3520 static pBranch *pBranchFind(pBranch *pb,pCode *pc)
3521 {
3522         while(pb) {
3523                 
3524                 if(pb->pc == pc)
3525                         return pb;
3526                 
3527                 pb = pb->next;
3528         }
3529         
3530         return NULL;
3531 }
3532
3533 /*-----------------------------------------------------------------*/
3534 /* pCodeUnlink - Unlink the given pCode from its pCode chain.      */
3535 /*-----------------------------------------------------------------*/
3536 static void pCodeUnlink(pCode *pc)
3537 {
3538         pBranch *pb1,*pb2;
3539         pCode *pc1;
3540         
3541         if(!pc->prev || !pc->next) {
3542                 fprintf(stderr,"unlinking bad pCode in %s:%d\n",__FILE__,__LINE__);
3543                 exit(1);
3544         }
3545         
3546         /* first remove the pCode from the chain */
3547         pc->prev->next = pc->next;
3548         pc->next->prev = pc->prev;
3549         
3550         /* Now for the hard part... */
3551         
3552         /* Remove the branches */
3553         
3554         pb1 = pc->from;
3555         while(pb1) {
3556         pc1 = pb1->pc;    /* Get the pCode that branches to the
3557         * one we're unlinking */
3558         
3559         /* search for the link back to this pCode (the one we're
3560         * unlinking) */
3561         if(pb2 = pBranchFind(pc1->to,pc)) {
3562                 pb2->pc = pc->to->pc;  // make the replacement
3563                 
3564                                                            /* if the pCode we're unlinking contains multiple 'to'
3565                                                            * branches (e.g. this a skip instruction) then we need
3566                 * to copy these extra branches to the chain. */
3567                 if(pc->to->next)
3568                         pBranchAppend(pb2, pc->to->next);
3569         }
3570         
3571         pb1 = pb1->next;
3572         }
3573         
3574         
3575 }
3576 #endif
3577 /*-----------------------------------------------------------------*/
3578 /*-----------------------------------------------------------------*/
3579 #if 0
3580 static void genericAnalyze(pCode *pc)
3581 {
3582         switch(pc->type) {
3583         case PC_WILD:
3584         case PC_COMMENT:
3585                 return;
3586         case PC_LABEL:
3587         case PC_FUNCTION:
3588         case PC_OPCODE:
3589                 {
3590                         // Go through the pCodes that are in pCode chain and link
3591                         // them together through the pBranches. Note, the pCodes
3592                         // are linked together as a contiguous stream like the 
3593                         // assembly source code lines. The linking here mimics this
3594                         // except that comments are not linked in.
3595                         // 
3596                         pCode *npc = pc->next;
3597                         while(npc) {
3598                                 if(npc->type == PC_OPCODE || npc->type == PC_LABEL) {
3599                                         pBranchLink(pc,npc);
3600                                         return;
3601                                 } else
3602                                         npc = npc->next;
3603                         }
3604                         /* reached the end of the pcode chain without finding
3605                         * an instruction we could link to. */
3606                 }
3607                 break;
3608         case PC_FLOW:
3609                 fprintf(stderr,"analyze PC_FLOW\n");
3610                 
3611                 return;
3612         case PC_BAD:
3613                 fprintf(stderr,";A bad pCode is being used\n");
3614                 
3615         }
3616 }
3617 #endif
3618
3619 /*-----------------------------------------------------------------*/
3620 /*-----------------------------------------------------------------*/
3621 int compareLabel(pCode *pc, pCodeOpLabel *pcop_label)
3622 {
3623   pBranch *pbr;
3624   
3625   if(pc->type == PC_LABEL) {
3626     if( ((pCodeLabel *)pc)->key ==  pcop_label->key)
3627       return TRUE;
3628   }
3629   if(pc->type == PC_OPCODE || pc->type == PC_ASMDIR) {
3630     pbr = PCI(pc)->label;
3631     while(pbr) {
3632       if(pbr->pc->type == PC_LABEL) {
3633         if( ((pCodeLabel *)(pbr->pc))->key ==  pcop_label->key)
3634           return TRUE;
3635       }
3636       pbr = pbr->next;
3637     }
3638   }
3639   
3640   return FALSE;
3641 }
3642
3643 /*-----------------------------------------------------------------*/
3644 /*-----------------------------------------------------------------*/
3645 int checkLabel(pCode *pc)
3646 {
3647         pBranch *pbr;
3648         
3649         if(pc && isPCI(pc)) {
3650                 pbr = PCI(pc)->label;
3651                 while(pbr) {
3652                         if(isPCL(pbr->pc) && (PCL(pbr->pc)->key >= 0))
3653                                 return TRUE;
3654                         
3655                         pbr = pbr->next;
3656                 }
3657         }
3658         
3659         return FALSE;
3660 }
3661
3662 /*-----------------------------------------------------------------*/
3663 /* findLabelinpBlock - Search the pCode for a particular label     */
3664 /*-----------------------------------------------------------------*/
3665 pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label)
3666 {
3667         pCode  *pc;
3668         
3669         if(!pb)
3670                 return NULL;
3671         
3672         for(pc = pb->pcHead; pc; pc = pc->next) 
3673                 if(compareLabel(pc,pcop_label))
3674                         return pc;
3675                 
3676                 return NULL;
3677 }
3678
3679 /*-----------------------------------------------------------------*/
3680 /* findLabel - Search the pCode for a particular label             */
3681 /*-----------------------------------------------------------------*/
3682 pCode * findLabel(pCodeOpLabel *pcop_label)
3683 {
3684         pBlock *pb;
3685         pCode  *pc;
3686         
3687         if(!the_pFile)
3688                 return NULL;
3689         
3690         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
3691                 if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL)
3692                         return pc;
3693         }
3694         
3695         fprintf(stderr,"Couldn't find label %s\n", pcop_label->pcop.name);
3696         return NULL;
3697 }
3698
3699 /*-----------------------------------------------------------------*/
3700 /* findNextpCode - given a pCode, find the next of type 'pct'      */
3701 /*                 in the linked list                              */
3702 /*-----------------------------------------------------------------*/
3703 pCode * findNextpCode(pCode *pc, PC_TYPE pct)
3704 {
3705         
3706         while(pc) {
3707                 if(pc->type == pct)
3708                         return pc;
3709                 
3710                 pc = pc->next;
3711         }
3712         
3713         return NULL;
3714 }
3715
3716 /*-----------------------------------------------------------------*/
3717 /* findPrevpCode - given a pCode, find the previous of type 'pct'  */
3718 /*                 in the linked list                              */
3719 /*-----------------------------------------------------------------*/
3720 pCode * findPrevpCode(pCode *pc, PC_TYPE pct)
3721 {
3722         
3723         while(pc) {
3724                 if(pc->type == pct) {
3725                         /*
3726                         static unsigned int stop;
3727                         if (pc->id == 524)
3728                                 stop++; // Place break point here
3729                         */
3730                         return pc;
3731                 }
3732                 
3733                 pc = pc->prev;
3734         }
3735         
3736         return NULL;
3737 }
3738
3739 /*-----------------------------------------------------------------*/
3740 /* findNextInstruction - given a pCode, find the next instruction  */
3741 /*                       in the linked list                        */
3742 /*-----------------------------------------------------------------*/
3743 pCode * findNextInstruction(pCode *pci)
3744 {
3745   pCode *pc = pci;
3746
3747   while(pc) {
3748   if((pc->type == PC_OPCODE)
3749     || (pc->type == PC_WILD)
3750     || (pc->type == PC_ASMDIR))
3751       return pc;
3752
3753 #ifdef PCODE_DEBUG
3754     fprintf(stderr,"findNextInstruction:  ");
3755     printpCode(stderr, pc);
3756 #endif
3757     pc = pc->next;
3758   }
3759
3760   //fprintf(stderr,"Couldn't find instruction\n");
3761   return NULL;
3762 }
3763
3764 /*-----------------------------------------------------------------*/
3765 /* findNextInstruction - given a pCode, find the next instruction  */
3766 /*                       in the linked list                        */
3767 /*-----------------------------------------------------------------*/
3768 pCode * findPrevInstruction(pCode *pci)
3769 {
3770   pCode *pc = pci;
3771
3772   while(pc) {
3773
3774     if((pc->type == PC_OPCODE)
3775       || (pc->type == PC_WILD)
3776       || (pc->type == PC_ASMDIR))
3777       return pc;
3778       
3779
3780 #ifdef PCODE_DEBUG
3781     fprintf(stderr,"pic16_findPrevInstruction:  ");
3782     printpCode(stderr, pc);
3783 #endif
3784     pc = pc->prev;
3785   }
3786
3787   //fprintf(stderr,"Couldn't find instruction\n");
3788   return NULL;
3789 }
3790
3791 /*-----------------------------------------------------------------*/
3792 /* findFunctionEnd - given a pCode find the end of the function    */
3793 /*                   that contains it                              */
3794 /*-----------------------------------------------------------------*/
3795 pCode * findFunctionEnd(pCode *pc)
3796 {
3797         while(pc) {
3798                 if(pc->type == PC_FUNCTION &&  !(PCF(pc)->fname))
3799                         return pc;
3800                 
3801                 pc = pc->next;
3802         }
3803         
3804         fprintf(stderr,"Couldn't find function end\n");
3805         return NULL;
3806 }
3807
3808 #if 0
3809 /*-----------------------------------------------------------------*/
3810 /* AnalyzeLabel - if the pCode is a label, then merge it with the  */
3811 /*                instruction with which it is associated.         */
3812 /*-----------------------------------------------------------------*/
3813 static void AnalyzeLabel(pCode *pc)
3814 {
3815         
3816         pCodeUnlink(pc);
3817         
3818 }
3819 #endif
3820
3821 #if 0
3822 static void AnalyzeGOTO(pCode *pc)
3823 {
3824         
3825         pBranchLink(pc,findLabel( (pCodeOpLabel *) (PCI(pc)->pcop) ));
3826         
3827 }
3828
3829 static void AnalyzeSKIP(pCode *pc)
3830 {
3831         
3832         pBranchLink(pc,findNextInstruction(pc->next));
3833         pBranchLink(pc,findNextInstruction(pc->next->next));
3834         
3835 }
3836
3837 static void AnalyzeRETURN(pCode *pc)
3838 {
3839         
3840         //  branch_link(pc,findFunctionEnd(pc->next));
3841         
3842 }
3843
3844 #endif
3845
3846 /*-----------------------------------------------------------------*/
3847 /*-----------------------------------------------------------------*/
3848 regs * getRegFromInstruction(pCode *pc)
3849 {
3850         regs *r;
3851         if(!pc                   || 
3852                 !isPCI(pc)            ||
3853                 !PCI(pc)->pcop        ||
3854                 PCI(pc)->num_ops == 0 )
3855                 return NULL;
3856         
3857         switch(PCI(pc)->pcop->type) {
3858         case PO_STATUS:
3859         case PO_FSR:
3860         case PO_INDF:
3861         case PO_INTCON:
3862         case PO_BIT:
3863         case PO_GPR_TEMP:
3864         case PO_SFR_REGISTER:
3865         case PO_PCL:
3866         case PO_PCLATH:
3867                 return PCOR(PCI(pc)->pcop)->r;
3868         
3869         case PO_GPR_REGISTER:
3870         case PO_GPR_BIT:
3871         case PO_DIR:
3872                 r = PCOR(PCI(pc)->pcop)->r;
3873                 if (r)
3874                         return r;
3875                 return dirregWithName(PCI(pc)->pcop->name);
3876                 
3877         case PO_LITERAL:
3878                 break;
3879                 
3880         case PO_IMMEDIATE:
3881                 r = PCOI(PCI(pc)->pcop)->r;
3882                 if (r)
3883                         return r;
3884                 return dirregWithName(PCI(pc)->pcop->name);
3885                 
3886         default:
3887                 break;
3888         }
3889         
3890         return NULL;
3891         
3892 }
3893
3894 /*-----------------------------------------------------------------*/
3895 /*-----------------------------------------------------------------*/
3896
3897 void AnalyzepBlock(pBlock *pb)
3898 {
3899         pCode *pc;
3900         
3901         if(!pb)
3902                 return;
3903         
3904                 /* Find all of the registers used in this pBlock 
3905                 * by looking at each instruction and examining it's
3906                 * operands
3907         */
3908         for(pc = pb->pcHead; pc; pc = pc->next) {
3909                 
3910                 /* Is this an instruction with operands? */
3911                 if(pc->type == PC_OPCODE && PCI(pc)->pcop) {
3912                         
3913                         if((PCI(pc)->pcop->type == PO_GPR_TEMP) 
3914                                 || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) {
3915                                 
3916                                 /* Loop through all of the registers declared so far in
3917                                 this block and see if we find this one there */
3918                                 
3919                                 regs *r = setFirstItem(pb->tregisters);
3920                                 
3921                                 while(r) {
3922                                         if((r->rIdx == PCOR(PCI(pc)->pcop)->r->rIdx) && (r->type == PCOR(PCI(pc)->pcop)->r->type)) {
3923                                                 PCOR(PCI(pc)->pcop)->r = r;
3924                                                 break;
3925                                         }
3926                                         r = setNextItem(pb->tregisters);
3927                                 }
3928                                 
3929                                 if(!r) {
3930                                         /* register wasn't found */
3931                                         //r = Safe_calloc(1, sizeof(regs));
3932                                         //memcpy(r,PCOR(PCI(pc)->pcop)->r, sizeof(regs));
3933                                         //addSet(&pb->tregisters, r);
3934                                         addSet(&pb->tregisters, PCOR(PCI(pc)->pcop)->r);
3935                                         //PCOR(PCI(pc)->pcop)->r = r;
3936                                         //fprintf(stderr,"added register to pblock: reg %d\n",r->rIdx);
3937                                         }/* else 
3938                                          fprintf(stderr,"found register in pblock: reg %d\n",r->rIdx);
3939                                 */
3940                         }
3941                         if(PCI(pc)->pcop->type == PO_GPR_REGISTER) {
3942                                 if(PCOR(PCI(pc)->pcop)->r) {
3943                                         pic14_allocWithIdx (PCOR(PCI(pc)->pcop)->r->rIdx);
3944                                         DFPRINTF((stderr,"found register in pblock: reg 0x%x\n",PCOR(PCI(pc)->pcop)->r->rIdx));
3945                                 } else {
3946                                         if(PCI(pc)->pcop->name)
3947                                                 fprintf(stderr,"ERROR: %s is a NULL register\n",PCI(pc)->pcop->name );
3948                                         else
3949                                                 fprintf(stderr,"ERROR: NULL register\n");
3950                                 }
3951                         }
3952                 }
3953                 
3954                 
3955         }
3956 }
3957
3958 /*-----------------------------------------------------------------*/
3959 /* */
3960 /*-----------------------------------------------------------------*/
3961 void InsertpFlow(pCode *pc, pCode **pflow)
3962 {
3963         if(*pflow)
3964                 PCFL(*pflow)->end = pc;
3965         
3966         if(!pc || !pc->next)
3967                 return;
3968         
3969         *pflow = newpCodeFlow();
3970         pCodeInsertAfter(pc, *pflow);
3971 }
3972
3973 /*-----------------------------------------------------------------*/
3974 /* BuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
3975 /*                         the flow blocks.                        */
3976 /*
3977 * BuildFlow inserts pCodeFlow objects into the pCode chain at each
3978 * point the instruction flow changes. 
3979 */
3980 /*-----------------------------------------------------------------*/
3981 void BuildFlow(pBlock *pb)
3982 {
3983         pCode *pc;
3984         pCode *last_pci=NULL;
3985         pCode *pflow=NULL;
3986         int seq = 0;
3987         
3988         if(!pb)
3989                 return;
3990         
3991         //fprintf (stderr,"build flow start seq %d  ",GpcFlowSeq);
3992         /* Insert a pCodeFlow object at the beginning of a pBlock */
3993         
3994         InsertpFlow(pb->pcHead, &pflow);
3995         
3996         //pflow = newpCodeFlow();    /* Create a new Flow object */
3997         //pflow->next = pb->pcHead;  /* Make the current head the next object */
3998         //pb->pcHead->prev = pflow;  /* let the current head point back to the flow object */
3999         //pb->pcHead = pflow;        /* Make the Flow object the head */
4000         //pflow->pb = pb;
4001         
4002         for( pc = findNextInstruction(pb->pcHead);
4003         pc != NULL;
4004         pc=findNextInstruction(pc)) { 
4005                 
4006                 pc->seq = seq++;
4007                 PCI(pc)->pcflow = PCFL(pflow);
4008                 
4009                 //fprintf(stderr," build: ");
4010                 //pc->print(stderr, pc);
4011                 //pflow->print(stderr,pflow);
4012                 
4013                 if (checkLabel(pc)) { 
4014                         
4015                 /* This instruction marks the beginning of a
4016                         * new flow segment */
4017                         
4018                         pc->seq = 0;
4019                         seq = 1;
4020                         
4021                         /* If the previous pCode is not a flow object, then 
4022                         * insert a new flow object. (This check prevents 
4023                         * two consecutive flow objects from being insert in
4024                         * the case where a skip instruction preceeds an
4025                         * instruction containing a label.) */
4026
4027                         last_pci = findPrevInstruction (pc->prev);
4028                         
4029                         if(last_pci && (PCI(last_pci)->pcflow == PCFL(pflow)))
4030                                 InsertpFlow(last_pci, &pflow);
4031                         
4032                         PCI(pc)->pcflow = PCFL(pflow);
4033                         
4034                 }
4035
4036                 if(isPCI_SKIP(pc)) {
4037                         
4038                 /* The two instructions immediately following this one 
4039                         * mark the beginning of a new flow segment */
4040                         
4041                         while(pc && isPCI_SKIP(pc)) {
4042                                 
4043                                 PCI(pc)->pcflow = PCFL(pflow);
4044                                 pc->seq = seq-1;
4045                                 seq = 1;
4046                                 
4047                                 InsertpFlow(pc, &pflow);
4048                                 pc=findNextInstruction(pc->next);
4049                         }
4050                         
4051                         seq = 0;
4052                         
4053                         if(!pc)
4054                                 break;
4055                         
4056                         PCI(pc)->pcflow = PCFL(pflow);
4057                         pc->seq = 0;
4058                         InsertpFlow(pc, &pflow);
4059                         
4060                 } else if ( isPCI_BRANCH(pc) && !checkLabel(findNextInstruction(pc->next)))  {
4061                         
4062                         InsertpFlow(pc, &pflow);
4063                         seq = 0;
4064                         
4065                 }
4066                 
4067                 last_pci = pc;
4068                 pc = pc->next;
4069         }
4070         
4071         //fprintf (stderr,",end seq %d",GpcFlowSeq);
4072         if(pflow)
4073                 PCFL(pflow)->end = pb->pcTail;
4074 }
4075
4076 /*-------------------------------------------------------------------*/
4077 /* unBuildFlow(pBlock *pb) - examine the code in a pBlock and build  */
4078 /*                           the flow blocks.                        */
4079 /*
4080 * unBuildFlow removes pCodeFlow objects from a pCode chain
4081 */
4082 /*-----------------------------------------------------------------*/
4083 void unBuildFlow(pBlock *pb)
4084 {
4085         pCode *pc,*pcnext;
4086         
4087         if(!pb)
4088                 return;
4089         
4090         pc = pb->pcHead;
4091         
4092         while(pc) {
4093                 pcnext = pc->next;
4094                 
4095                 if(isPCI(pc)) {
4096                         
4097                         pc->seq = 0;
4098                         if(PCI(pc)->pcflow) {
4099                                 //free(PCI(pc)->pcflow);
4100                                 PCI(pc)->pcflow = NULL;
4101                         }
4102                         
4103                 } else if(isPCFL(pc) )
4104                         pc->destruct(pc);
4105                 
4106                 pc = pcnext;
4107         }
4108         
4109         
4110 }
4111
4112 /*-----------------------------------------------------------------*/
4113 /*-----------------------------------------------------------------*/
4114 void dumpCond(int cond)
4115 {
4116         
4117         static char *pcc_str[] = {
4118                 //"PCC_NONE",
4119                 "PCC_REGISTER",
4120                         "PCC_C",
4121                         "PCC_Z",
4122                         "PCC_DC",
4123                         "PCC_W",
4124                         "PCC_EXAMINE_PCOP",
4125                         "PCC_REG_BANK0",
4126                         "PCC_REG_BANK1",
4127                         "PCC_REG_BANK2",
4128                         "PCC_REG_BANK3"
4129         };
4130         
4131         int ncond = sizeof(pcc_str) / sizeof(char *);
4132         int i,j;
4133         
4134         fprintf(stderr, "0x%04X\n",cond);
4135         
4136         for(i=0,j=1; i<ncond; i++, j<<=1)
4137                 if(cond & j)
4138                         fprintf(stderr, "  %s\n",pcc_str[i]);
4139                 
4140 }
4141
4142 /*-----------------------------------------------------------------*/
4143 /*-----------------------------------------------------------------*/
4144 void FlowStats(pCodeFlow *pcflow)
4145 {
4146         
4147         pCode *pc;
4148         
4149         if(!isPCFL(pcflow))
4150                 return;
4151         
4152         fprintf(stderr, " FlowStats - flow block (seq=%d)\n", pcflow->pc.seq);
4153         
4154         pc = findNextpCode(PCODE(pcflow), PC_OPCODE); 
4155         
4156         if(!pc) {
4157                 fprintf(stderr, " FlowStats - empty flow (seq=%d)\n", pcflow->pc.seq);
4158                 return;
4159         }
4160         
4161         
4162         fprintf(stderr, "  FlowStats inCond: ");
4163         dumpCond(pcflow->inCond);
4164         fprintf(stderr, "  FlowStats outCond: ");
4165         dumpCond(pcflow->outCond);
4166         
4167 }
4168
4169 /*-----------------------------------------------------------------*
4170 * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine
4171 *    if it affects the banking bits. 
4172
4173 * return: -1 == Banking bits are unaffected by this pCode.
4174 *
4175 * return: > 0 == Banking bits are affected.
4176 *
4177 *  If the banking bits are affected, then the returned value describes
4178 * which bits are affected and how they're affected. The lower half
4179 * of the integer maps to the bits that are affected, the upper half
4180 * to whether they're set or cleared.
4181 *
4182 *-----------------------------------------------------------------*/
4183 /*
4184 #define SET_BANK_BIT (1 << 16)
4185 #define CLR_BANK_BIT 0
4186
4187 static int isBankInstruction(pCode *pc)
4188 {
4189         regs *reg;
4190         int bank = -1;
4191         
4192         if(!isPCI(pc))
4193                 return -1;
4194         
4195         if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) {
4196                 
4197                 // Check to see if the register banks are changing
4198                 if(PCI(pc)->isModReg) {
4199                         
4200                         pCodeOp *pcop = PCI(pc)->pcop;
4201                         switch(PCI(pc)->op) {
4202                                 
4203                         case POC_BSF:
4204                                 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4205                                         //fprintf(stderr, "  isBankInstruction - Set RP0\n");
4206                                         return  SET_BANK_BIT | PIC_RP0_BIT;
4207                                 }
4208                                 
4209                                 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4210                                         //fprintf(stderr, "  isBankInstruction - Set RP1\n");
4211                                         return  CLR_BANK_BIT | PIC_RP0_BIT;
4212                                 }
4213                                 break;
4214                                 
4215                         case POC_BCF:
4216                                 if(PCORB(pcop)->bit == PIC_RP0_BIT) {
4217                                         //fprintf(stderr, "  isBankInstruction - Clr RP0\n");
4218                                         return  CLR_BANK_BIT | PIC_RP1_BIT;
4219                                 }
4220                                 if(PCORB(pcop)->bit == PIC_RP1_BIT) {
4221                                         //fprintf(stderr, "  isBankInstruction - Clr RP1\n");
4222                                         return  CLR_BANK_BIT | PIC_RP1_BIT;
4223                                 }
4224                                 break;
4225                         default:
4226                                 //fprintf(stderr, "  isBankInstruction - Status register is getting Modified by:\n");
4227                                 //genericPrint(stderr, pc);
4228                                 ;
4229                         }
4230                 }
4231                 
4232                                 }
4233                                 
4234         return bank;
4235 }
4236 */
4237
4238 /*-----------------------------------------------------------------*/
4239 /*-----------------------------------------------------------------*/
4240 /*
4241 static void FillFlow(pCodeFlow *pcflow)
4242 {
4243         pCode *pc;
4244         int cur_bank;
4245         
4246         if(!isPCFL(pcflow))
4247                 return;
4248         
4249         //  fprintf(stderr, " FillFlow - flow block (seq=%d)\n", pcflow->pc.seq);
4250         
4251         pc = findNextpCode(PCODE(pcflow), PC_OPCODE); 
4252         
4253         if(!pc) {
4254                 //fprintf(stderr, " FillFlow - empty flow (seq=%d)\n", pcflow->pc.seq);
4255                 return;
4256         }
4257         
4258         cur_bank = -1;
4259         
4260         do {
4261                 isBankInstruction(pc);
4262                 pc = pc->next;
4263         } while (pc && (pc != pcflow->end) && !isPCFL(pc));
4264         / *
4265                 if(!pc ) {
4266                         fprintf(stderr, "  FillFlow - Bad end of flow\n");
4267                 } else {
4268                         fprintf(stderr, "  FillFlow - Ending flow with\n  ");
4269                         pc->print(stderr,pc);
4270                 }
4271                 
4272                 fprintf(stderr, "  FillFlow inCond: ");
4273                 dumpCond(pcflow->inCond);
4274                 fprintf(stderr, "  FillFlow outCond: ");
4275                 dumpCond(pcflow->outCond);
4276                 * /
4277 }
4278 */
4279
4280 /*-----------------------------------------------------------------*/
4281 /*-----------------------------------------------------------------*/
4282 void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to)
4283 {
4284         pCodeFlowLink *fromLink, *toLink;
4285 #if 0
4286         fprintf(stderr, "%s: linking ", __FUNCTION__ );
4287         if (from) from->pc.print(stderr, &from->pc);
4288         else fprintf(stderr, "(null)");
4289         fprintf(stderr, " -(%u)-> with -(%u)-> ",
4290                 from && from->pcflow ? from->pcflow->pc.seq : 0,
4291                 to && to->pcflow ? to->pcflow->pc.seq : 0);
4292         if (to) to->pc.print(stderr, &to->pc);
4293         else fprintf(stderr, "(null)");
4294 #endif
4295
4296         if(!from || !to || !to->pcflow || !from->pcflow)
4297                 return;
4298         
4299         fromLink = newpCodeFlowLink(from->pcflow);
4300         toLink   = newpCodeFlowLink(to->pcflow);
4301         
4302         addSetIfnotP(&(from->pcflow->to), toLink);   //to->pcflow);
4303         addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow);
4304         
4305 }
4306
4307 /*-----------------------------------------------------------------*
4308 * void LinkFlow(pBlock *pb)
4309 *
4310 * In BuildFlow, the PIC code has been partitioned into contiguous
4311 * non-branching segments. In LinkFlow, we determine the execution
4312 * order of these segments. For example, if one of the segments ends
4313 * with a skip, then we know that there are two possible flow segments
4314 * to which control may be passed.
4315 *-----------------------------------------------------------------*/
4316 void LinkFlow(pBlock *pb)
4317 {
4318         pCode *pc=NULL;
4319         pCode *pcflow;
4320         pCode *pct;
4321         
4322         //fprintf(stderr,"linkflow \n");
4323         
4324         for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4325         pcflow != NULL;
4326         pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4327                 
4328                 if(!isPCFL(pcflow))
4329                         fprintf(stderr, "LinkFlow - pcflow is not a flow object ");
4330                 
4331                 //fprintf(stderr," link: ");
4332                 //pcflow->print(stderr,pcflow);
4333                 
4334                 //FillFlow(PCFL(pcflow));
4335                 
4336                 /* find last instruction in flow */
4337                 pc = findPrevInstruction (PCFL(pcflow)->end);
4338                 if (!pc) {
4339                         fprintf(stderr, "%s: flow without end (%u)?\n",
4340                         __FUNCTION__, pcflow->seq );
4341                         continue;
4342                 }
4343                 
4344                 //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq);
4345                 //pc->print(stderr, pc);
4346                 if(isPCI_SKIP(pc)) {
4347                         //fprintf(stderr, "ends with skip\n");
4348                         //pc->print(stderr,pc);
4349                         pct=findNextInstruction(pc->next);
4350                         LinkFlow_pCode(PCI(pc),PCI(pct));
4351                         pct=findNextInstruction(pct->next);
4352                         LinkFlow_pCode(PCI(pc),PCI(pct));
4353                         continue;
4354                 }
4355                 
4356                 if(isPCI_BRANCH(pc)) {
4357                         pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4358                         
4359                         //fprintf(stderr, "ends with branch\n  ");
4360                         //pc->print(stderr,pc);
4361
4362                         if(!(pcol && isPCOLAB(pcol))) {
4363                                 if((PCI(pc)->op != POC_RETLW)
4364                                         && (PCI(pc)->op != POC_RETURN)
4365                                         && (PCI(pc)->op != POC_CALL)
4366                                         && (PCI(pc)->op != POC_RETFIE) )
4367                                 {
4368                                         pc->print(stderr,pc);
4369                                         fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__);
4370                                 }
4371                         } else {
4372                         
4373                                 if( (pct = findLabelinpBlock(pb,pcol)) != NULL)
4374                                         LinkFlow_pCode(PCI(pc),PCI(pct));
4375                                 else
4376                                         fprintf(stderr, "ERROR: %s, couldn't find label. key=%d,lab=%s\n",
4377                                         __FUNCTION__,pcol->key,((PCOP(pcol)->name)?PCOP(pcol)->name:"-"));
4378                                 //fprintf(stderr,"newpCodeOpLabel: key=%d, name=%s\n",key,((s)?s:""));
4379                         }
4380                         /* link CALLs to next instruction */
4381                         if (PCI(pc)->op != POC_CALL) continue;
4382                 }
4383                 
4384                 if(isPCI(pc)) {
4385                         //fprintf(stderr, "ends with non-branching instruction:\n");
4386                         //pc->print(stderr,pc);
4387                         
4388                         LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next)));
4389                         
4390                         continue;
4391                 }
4392                 
4393                 if(pc) {
4394                         //fprintf(stderr, "ends with unknown\n");
4395                         //pc->print(stderr,pc);
4396                         continue;
4397                 }
4398                 
4399                 fprintf(stderr, "ends with nothing: ERROR\n");
4400                 
4401         }
4402 }
4403 /*-----------------------------------------------------------------*/
4404 /*-----------------------------------------------------------------*/
4405
4406 /*-----------------------------------------------------------------*/
4407 /*-----------------------------------------------------------------*/
4408 int isPCinFlow(pCode *pc, pCode *pcflow)
4409 {
4410         
4411         if(!pc || !pcflow)
4412                 return 0;
4413         
4414         if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) )
4415                 return 0;
4416         
4417         if( PCI(pc)->pcflow->pc.seq == pcflow->seq)
4418                 return 1;
4419         
4420         return 0;
4421 }
4422
4423 /*-----------------------------------------------------------------*/
4424 /*-----------------------------------------------------------------*/
4425 /*
4426 static void BanksUsedFlow2(pCode *pcflow)
4427 {
4428         pCode *pc=NULL;
4429         
4430         int bank = -1;
4431         bool RegUsed = 0;
4432         
4433         regs *reg;
4434         
4435         if(!isPCFL(pcflow)) {
4436                 fprintf(stderr, "BanksUsed - pcflow is not a flow object ");
4437                 return;
4438         }
4439         
4440         pc = findNextInstruction(pcflow->next);
4441         
4442         PCFL(pcflow)->lastBank = -1;
4443         
4444         while(isPCinFlow(pc,pcflow)) {
4445                 
4446                 int bank_selected = isBankInstruction(pc);
4447                 
4448                 //if(PCI(pc)->pcflow) 
4449                 //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq);
4450                 
4451                 if(bank_selected > 0) {
4452                         //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected);
4453                         
4454                         // This instruction is modifying banking bits before accessing registers
4455                         if(!RegUsed)
4456                                 PCFL(pcflow)->firstBank = -1;
4457                         
4458                         if(PCFL(pcflow)->lastBank == -1)
4459                                 PCFL(pcflow)->lastBank = 0;
4460                         
4461                         bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT)));
4462                         if(bank_selected & SET_BANK_BIT)
4463                                 PCFL(pcflow)->lastBank |= bank;
4464                         
4465                         
4466                 } else { 
4467                         reg = getRegFromInstruction(pc);
4468                         
4469                         if(reg && !isREGinBank(reg, bank)) {
4470                                 int allbanks = REGallBanks(reg);
4471                                 if(bank == -1)
4472                                         PCFL(pcflow)->firstBank = allbanks;
4473                                 
4474                                 PCFL(pcflow)->lastBank = allbanks;
4475                                 
4476                                 bank = allbanks;
4477                         }
4478                         RegUsed = 1;
4479                                                                 }
4480                                                                 
4481                 pc = findNextInstruction(pc->next);
4482         }
4483         
4484         //  fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n",
4485         //    pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank);
4486 }
4487 */
4488 /*-----------------------------------------------------------------*/
4489 /*-----------------------------------------------------------------*/
4490 /*
4491 static void BanksUsedFlow(pBlock *pb)
4492 {
4493         pCode *pcflow;
4494         
4495         
4496         //pb->pcHead->print(stderr, pb->pcHead);
4497         
4498         pcflow = findNextpCode(pb->pcHead, PC_FLOW);
4499         //pcflow->print(stderr,pcflow);
4500         
4501         for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
4502         pcflow != NULL;
4503         pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
4504                 
4505                 BanksUsedFlow2(pcflow);
4506         }
4507         
4508 }
4509 */
4510
4511 void pCodeReplace (pCode *old, pCode *new)
4512 {
4513         pCodeInsertAfter (old, new);
4514
4515         /* special handling for pCodeInstructions */
4516         if (isPCI(new) && isPCI(old))
4517         {
4518                 //assert (!PCI(new)->from && !PCI(new)->to && !PCI(new)->label && /*!PCI(new)->pcflow && */!PCI(new)->cline);
4519                 PCI(new)->from = PCI(old)->from;
4520                 PCI(new)->to = PCI(old)->to;
4521                 PCI(new)->label = PCI(old)->label;
4522                 PCI(new)->pcflow = PCI(old)->pcflow;
4523                 PCI(new)->cline = PCI(old)->cline;
4524         } // if
4525
4526         old->destruct (old);
4527 }
4528
4529 /*-----------------------------------------------------------------*/
4530 /*-----------------------------------------------------------------*/
4531 void addpCodeComment(pCode *pc, const char *fmt, ...)
4532 {
4533     va_list ap;
4534     char buffer[4096];
4535     pCode *newpc;
4536
4537     va_start(ap, fmt);
4538     if (options.verbose || debug_verbose) {
4539         buffer[0] = ';';
4540         buffer[1] = ' ';
4541         vsprintf(&buffer[2], fmt, ap);
4542
4543         newpc = newpCodeCharP(&buffer[0]); // strdup's the string
4544         pCodeInsertAfter(pc, newpc);
4545     }
4546     va_end(ap);
4547 }
4548
4549 void pBlockMergeLabels(pBlock *pb);
4550 /*-----------------------------------------------------------------*/
4551 /* Inserts a new pCodeInstruction before an existing one           */
4552 /*-----------------------------------------------------------------*/
4553 static void insertPCodeInstruction(pCodeInstruction *pci, pCodeInstruction *new_pci)
4554 {
4555         pCode *pcprev;
4556
4557         pcprev = findPrevInstruction(pci->pc.prev);
4558         
4559         pCodeInsertAfter(pci->pc.prev, &new_pci->pc);
4560         
4561         /* Move the label, if there is one */
4562         
4563         if(pci->label) {
4564                 new_pci->label = pci->label;
4565                 pci->label = NULL;
4566         }
4567         
4568         /* Move the C code comment, if there is one */
4569         
4570         if(pci->cline) {
4571                 new_pci->cline = pci->cline;
4572                 pci->cline = NULL;
4573         }
4574         
4575         /* The new instruction has the same pcflow block */
4576         new_pci->pcflow = pci->pcflow;
4577
4578         /* Arrrrg: is pci's previous instruction is a skip, we need to
4579          * change that into a jump (over pci and the new instruction) ... */
4580         if (pcprev && isPCI_SKIP(pcprev))
4581         {
4582                 symbol *lbl = newiTempLabel (NULL);
4583                 pCode *label = newpCodeLabel (NULL, lbl->key);
4584                 pCode *jump = newpCode(POC_GOTO, newpCodeOpLabel(NULL, lbl->key));
4585
4586                 pCodeInsertAfter (pcprev, jump);
4587
4588                 // Yuck: Cannot simply replace INCFSZ/INCFSZW/DECFSZ/DECFSZW
4589                 // We replace them with INCF/INCFW/DECF/DECFW followed by 'BTFSS STATUS, Z'
4590                 switch (PCI(pcprev)->op) {
4591                 case POC_INCFSZ:
4592                 case POC_INCFSZW:
4593                 case POC_DECFSZ:
4594                 case POC_DECFSZW:
4595                     // These are turned into non-skipping instructions, so
4596                     // insert 'BTFSC STATUS, Z' after pcprev
4597                     pCodeInsertAfter (jump->prev, newpCode(POC_BTFSC, popCopyGPR2Bit(PCOP(&pc_status), PIC_Z_BIT)));
4598                     break;
4599                 default:
4600                     // no special actions required
4601                     break;
4602                 }
4603                 pCodeReplace (pcprev, pCodeInstructionCopy (PCI(pcprev), 1));
4604                 pcprev = NULL;
4605                 pCodeInsertAfter((pCode*)pci, label);
4606                 pBlockMergeLabels(pci->pc.pb);
4607         }
4608 }
4609
4610 /*-----------------------------------------------------------------*/
4611 /*-----------------------------------------------------------------*/
4612 static void insertBankSel(pCodeInstruction  *pci, const char *name)
4613 {
4614         pCode *new_pc;
4615         
4616         pCodeOp *pcop;
4617
4618         // Never BANKSEL STATUS, this breaks all kinds of code (e.g., interrupt handlers).
4619         if (!strcmp("STATUS", name) || !strcmp("_STATUS", name)) return;
4620         
4621         pcop = popCopyReg(PCOR(pci->pcop));
4622         pcop->type = PO_GPR_REGISTER; // Sometimes the type is set to legacy 8051 - so override it
4623         if (pcop->name == 0)
4624                 pcop->name = strdup(name);
4625         new_pc = newpCode(POC_BANKSEL, pcop);
4626         
4627         insertPCodeInstruction(pci, PCI(new_pc));
4628 }
4629
4630 /*-----------------------------------------------------------------*/
4631 /*-----------------------------------------------------------------*/
4632 static int sameBank(regs *reg, regs *previous_reg, const char *new_bank, const char *cur_bank, unsigned max_mask)
4633 {
4634     if (!cur_bank) return 0;
4635
4636     // identify '(regname + X)' and 'regname'
4637     if (reg && reg->name && reg->name[0] == '(' && !strncmp(&reg->name[1], cur_bank, strlen(cur_bank))) return 1;
4638     if (new_bank && new_bank[0] == '(' && !strncmp(&new_bank[1], cur_bank, strlen(cur_bank))) return 1;
4639     if (cur_bank[0] == '(' && reg && reg->name && !strncmp(reg->name, &cur_bank[1], strlen(reg->name))) return 1;
4640     if (cur_bank[0] == '(' && new_bank && !strncmp(new_bank, &cur_bank[1], strlen(new_bank))) return 1;
4641     
4642     if (previous_reg && reg && previous_reg->isFixed && reg->isFixed && ((previous_reg->address & max_mask) == (reg->address & max_mask)))      // only if exists 
4643       return 1;  // if we have address info, we use it for banksel optimization
4644
4645     // XXX: identify '(regname + X)' and '(regname + Y)'
4646     
4647     return ((reg && reg->name && !strcmp(reg->name, cur_bank)) || (new_bank && !strcmp(new_bank, cur_bank)));
4648 }
4649     
4650 /*-----------------------------------------------------------------*/
4651 /*-----------------------------------------------------------------*/
4652 void FixRegisterBanking(pBlock *pb)
4653 {
4654     pCode *pc;
4655     pCodeInstruction *pci;
4656     regs *reg;
4657     regs *previous_reg;         // contains the previous variable access info
4658     const char *cur_bank, *new_bank;
4659     unsigned cur_mask, new_mask, max_mask;
4660     int allRAMmshared;
4661     
4662     if (!pb) return;
4663
4664     max_mask = pic14_getPIC()->bankMask;
4665     cur_mask = max_mask;
4666     cur_bank = NULL;
4667     previous_reg = NULL;
4668
4669     allRAMmshared = pic14_allRAMShared();
4670
4671     for (pc = pb->pcHead; pc; pc = pc->next)
4672     {
4673         // this one has a label---might check bank at all jumps here...
4674         if (isPCI(pc) && (PCI(pc)->label || PCI(pc)->op == POC_CALL)) {
4675             addpCodeComment(pc->prev, "BANKOPT3 drop assumptions: PCI with label or call found");
4676             previous_reg = NULL;
4677             cur_bank = NULL; // start new flow
4678             cur_mask = max_mask;
4679         }
4680         
4681         // this one is/might be a label or BANKSEL---assume nothing
4682         if (isPCL(pc) || isPCASMDIR(pc)) {
4683             addpCodeComment(pc->prev, "BANKOPT4 drop assumptions: label or ASMDIR found");
4684             previous_reg = NULL;
4685             cur_bank = NULL;
4686             cur_mask = max_mask;
4687         }
4688
4689         // this one modifies STATUS
4690         // XXX: this should be checked, but usually BANKSELs are not done this way in generated code
4691         
4692         if (isPCI(pc)) {
4693             pci = PCI(pc);
4694             if ((pci->inCond | pci->outCond) & PCC_REGISTER) {
4695                 // might need a BANKSEL
4696                 reg = getRegFromInstruction(pc);
4697
4698                 if (reg) {
4699                     new_bank = reg->name;
4700                     // reg->alias == 0: reg is in only one bank, we do not know which (may be any bank)
4701                     // reg->alias != 0: reg is in 2/4/8/2**N banks, we select one of them
4702                     new_mask = reg->alias;
4703                 } else if (pci->pcop && pci->pcop->name) {
4704                     new_bank = pci->pcop->name;
4705                     new_mask = 0; // unknown, assume worst case
4706                 } else {
4707                     assert(!"Could not get register from instruction.");
4708                 }
4709
4710                 // optimizations...
4711                 // XXX: add switch to disable these
4712                 if (1) {
4713                     // reg present in all banks possibly selected?
4714                     if (new_mask == max_mask || (cur_mask && ((new_mask & cur_mask) == cur_mask))) {
4715                         // no BANKSEL required
4716                         addpCodeComment(pc->prev, "BANKOPT1 BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4717                         continue;
4718                     }
4719
4720                     // only one bank of memory and no SFR accessed?
4721                     // XXX: We can do better with fixed registers.
4722                     if (allRAMmshared && reg && (reg->type != REG_SFR) && (!reg->isFixed)) {
4723                         // no BANKSEL required
4724                         addpCodeComment(pc->prev, "BANKOPT1b BANKSEL dropped; %s present in all of %s's banks", new_bank, cur_bank);
4725                         continue;
4726                     }
4727
4728                     // restrict cur_mask to cover only the banks this register
4729                     // is in (as well as the previous registers)
4730                     cur_mask &= new_mask;
4731
4732                     if (sameBank(reg, previous_reg, new_bank, cur_bank, max_mask)) {
4733                         // no BANKSEL required
4734                         addpCodeComment(pc->prev, "BANKOPT2 BANKSEL dropped; %s present in same bank as %s", new_bank, cur_bank);
4735                         continue;
4736                     }
4737                 } // if
4738
4739                 cur_mask = new_mask;
4740                 cur_bank = new_bank;
4741                 previous_reg = reg;
4742                 insertBankSel(pci, cur_bank);
4743             } // if
4744         } // if
4745     } // for
4746 }
4747
4748 /*-----------------------------------------------------------------*/
4749 /*-----------------------------------------------------------------*/
4750 int OptimizepBlock(pBlock *pb)
4751 {
4752         pCode *pc, *pcprev;
4753         int matches =0;
4754         
4755         if(!pb || options.nopeep)
4756                 return 0;
4757         
4758         DFPRINTF((stderr," Optimizing pBlock: %c\n",getpBlock_dbName(pb)));
4759         /*
4760         for(pc = pb->pcHead; pc; pc = pc->next)
4761         matches += pCodePeepMatchRule(pc);
4762         */
4763         
4764         pc = findNextInstruction(pb->pcHead);
4765         if(!pc)
4766                 return 0;
4767         
4768         pcprev = pc->prev;
4769         do {
4770                 
4771                 
4772                 if(pCodePeepMatchRule(pc)) {
4773                         
4774                         matches++;
4775                         
4776                         if(pcprev)
4777                                 pc = findNextInstruction(pcprev->next);
4778                         else 
4779                                 pc = findNextInstruction(pb->pcHead);
4780                 } else
4781                         pc = findNextInstruction(pc->next);
4782         } while(pc);
4783         
4784         if(matches)
4785                 DFPRINTF((stderr," Optimizing pBlock: %c - matches=%d\n",getpBlock_dbName(pb),matches));
4786         return matches;
4787         
4788 }
4789
4790 /*-----------------------------------------------------------------*/
4791 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
4792 /*-----------------------------------------------------------------*/
4793 pCode * findInstructionUsingLabel(pCodeLabel *pcl, pCode *pcs)
4794 {
4795   pCode *pc;
4796
4797   for(pc = pcs; pc; pc = pc->next) {
4798
4799     if(((pc->type == PC_OPCODE) || (pc->type == PC_INLINE) || (pc->type == PC_ASMDIR)) &&
4800       (PCI(pc)->pcop) && 
4801       (PCI(pc)->pcop->type == PO_LABEL) &&
4802       (PCOLAB(PCI(pc)->pcop)->key == pcl->key))
4803       return pc;
4804   }
4805
4806   return NULL;
4807 }
4808
4809 /*-----------------------------------------------------------------*/
4810 /*-----------------------------------------------------------------*/
4811 void exchangeLabels(pCodeLabel *pcl, pCode *pc)
4812 {
4813         
4814         char *s=NULL;
4815         
4816         if(isPCI(pc) && 
4817                 (PCI(pc)->pcop) && 
4818                 (PCI(pc)->pcop->type == PO_LABEL)) {
4819                 
4820                 pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop);
4821                 
4822                 //fprintf(stderr,"changing label key from %d to %d\n",pcol->key, pcl->key);
4823                 if(pcol->pcop.name)
4824                         free(pcol->pcop.name);
4825                 
4826                         /* If the key is negative, then we (probably) have a label to
4827                 * a function and the name is already defined */
4828                 
4829                 if(pcl->key>0)
4830                         sprintf(s=buffer,"_%05d_DS_",pcl->key);
4831                 else 
4832                         s = pcl->label;
4833                 
4834                 //sprintf(buffer,"_%05d_DS_",pcl->key);
4835                 if(!s) {
4836                         fprintf(stderr, "ERROR %s:%d function label is null\n",__FUNCTION__,__LINE__);
4837                 }
4838                 pcol->pcop.name = Safe_strdup(s);
4839                 pcol->key = pcl->key;
4840                 //pc->print(stderr,pc);
4841                 
4842         }
4843         
4844         
4845 }
4846
4847 /*-----------------------------------------------------------------*/
4848 /* pBlockRemoveUnusedLabels - remove the pCode labels from the     */
4849 /*                            pCode chain if they're not used.     */
4850 /*-----------------------------------------------------------------*/
4851 void pBlockRemoveUnusedLabels(pBlock *pb)
4852 {
4853         pCode *pc; pCodeLabel *pcl;
4854         
4855         if(!pb)
4856                 return;
4857         
4858         for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
4859                 
4860                 pBranch *pbr = PCI(pc)->label;
4861                 if(pbr && pbr->next) {
4862                         pCode *pcd = pb->pcHead;
4863                         
4864                         //fprintf(stderr, "multiple labels\n");
4865                         //pc->print(stderr,pc);
4866                         
4867                         pbr = pbr->next;
4868                         while(pbr) {
4869                                 
4870                                 while ( (pcd = findInstructionUsingLabel(PCL(PCI(pc)->label->pc), pcd)) != NULL) {
4871                                         //fprintf(stderr,"Used by:\n");
4872                                         //pcd->print(stderr,pcd);
4873                                         
4874                                         exchangeLabels(PCL(pbr->pc),pcd);
4875                                         
4876                                         pcd = pcd->next;
4877                                 }
4878                                 pbr = pbr->next;
4879                         }
4880                 }
4881         }
4882         
4883         for(pc = pb->pcHead; pc; pc = pc->next) {
4884                 
4885                 if(isPCL(pc)) // Label pcode
4886                         pcl = PCL(pc);
4887                 else if (isPCI(pc) && PCI(pc)->label) // pcode instruction with a label
4888                         pcl = PCL(PCI(pc)->label->pc);
4889                 else continue;
4890                 
4891                 //fprintf(stderr," found  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4892                 
4893                 /* This pCode is a label, so search the pBlock to see if anyone
4894                 * refers to it */
4895                 
4896                 if( (pcl->key>0) && (!findInstructionUsingLabel(pcl, pb->pcHead))) {
4897                         //if( !findInstructionUsingLabel(pcl, pb->pcHead)) {
4898                         /* Couldn't find an instruction that refers to this label
4899                         * So, unlink the pCode label from it's pCode chain
4900                         * and destroy the label */
4901                         //fprintf(stderr," removed  A LABEL !!! key = %d, %s\n", pcl->key,pcl->label);
4902                         
4903                         DFPRINTF((stderr," !!! REMOVED A LABEL !!! key = %d, %s\n", pcl->key,pcl->label));
4904                         if(pc->type == PC_LABEL) {
4905                                 unlinkpCode(pc);
4906                                 pCodeLabelDestruct(pc);
4907                         } else {
4908                                 unlinkpCodeFromBranch(pc, PCODE(pcl));
4909                                 /*if(pc->label->next == NULL && pc->label->pc == NULL) {
4910                                 free(pc->label);
4911                         }*/
4912                         }
4913                         
4914                 }
4915         }
4916         
4917 }
4918
4919
4920 /*-----------------------------------------------------------------*/
4921 /* pBlockMergeLabels - remove the pCode labels from the pCode      */
4922 /*                     chain and put them into pBranches that are  */
4923 /*                     associated with the appropriate pCode       */
4924 /*                     instructions.                               */
4925 /*-----------------------------------------------------------------*/
4926 void pBlockMergeLabels(pBlock *pb)
4927 {
4928         pBranch *pbr;
4929         pCode *pc, *pcnext=NULL;
4930         
4931         if(!pb)
4932                 return;
4933         
4934         /* First, Try to remove any unused labels */
4935         //pBlockRemoveUnusedLabels(pb);
4936         
4937         /* Now loop through the pBlock and merge the labels with the opcodes */
4938         
4939         pc = pb->pcHead;
4940         //  for(pc = pb->pcHead; pc; pc = pc->next) {
4941         
4942         while(pc) {
4943                 pCode *pcn = pc->next;
4944                 
4945                 if(pc->type == PC_LABEL) {
4946                         
4947                         //fprintf(stderr," checking merging label %s\n",PCL(pc)->label);
4948                         //fprintf(stderr,"Checking label key = %d\n",PCL(pc)->key);
4949                         if((pcnext = findNextInstruction(pc) )) {
4950                                 
4951                                 // Unlink the pCode label from it's pCode chain
4952                                 unlinkpCode(pc);
4953                                 
4954                                 //fprintf(stderr,"Merged label key = %d\n",PCL(pc)->key);
4955                                 // And link it into the instruction's pBranch labels. (Note, since
4956                                 // it's possible to have multiple labels associated with one instruction
4957                                 // we must provide a means to accomodate the additional labels. Thus
4958                                 // the labels are placed into the singly-linked list "label" as 
4959                                 // opposed to being a single member of the pCodeInstruction.)
4960                                 
4961                                 //_ALLOC(pbr,sizeof(pBranch));
4962                                 pbr = Safe_calloc(1,sizeof(pBranch));
4963                                 pbr->pc = pc;
4964                                 pbr->next = NULL;
4965                                 
4966                                 PCI(pcnext)->label = pBranchAppend(PCI(pcnext)->label,pbr);
4967                                 
4968                         } else {
4969                                 fprintf(stderr, "WARNING: couldn't associate label %s with an instruction\n",PCL(pc)->label);
4970                         }
4971                 } else if(pc->type == PC_CSOURCE) {
4972                         
4973                         /* merge the source line symbolic info into the next instruction */
4974                         if((pcnext = findNextInstruction(pc) )) {
4975                                 
4976                                 // Unlink the pCode label from it's pCode chain
4977                                 unlinkpCode(pc);
4978                                 PCI(pcnext)->cline = PCCS(pc);
4979                                 //fprintf(stderr, "merging CSRC\n");
4980                                 //genericPrint(stderr,pcnext);
4981                         }
4982                         
4983                 }
4984                 pc = pcn;
4985         }
4986         pBlockRemoveUnusedLabels(pb);
4987         
4988 }
4989
4990 /*-----------------------------------------------------------------*/
4991 /*-----------------------------------------------------------------*/
4992 int OptimizepCode(char dbName)
4993 {
4994 #define MAX_PASSES 4
4995         
4996         int matches = 0;
4997         int passes = 0;
4998         pBlock *pb;
4999         
5000         if(!the_pFile)
5001                 return 0;
5002         
5003         DFPRINTF((stderr," Optimizing pCode\n"));
5004         
5005         do {
5006                 matches = 0;
5007                 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5008                         if('*' == dbName || getpBlock_dbName(pb) == dbName)
5009                                 matches += OptimizepBlock(pb);
5010                 }
5011         }
5012         while(matches && ++passes < MAX_PASSES);
5013         
5014         return matches;
5015 }
5016
5017 /*-----------------------------------------------------------------*/
5018 /* popCopyGPR2Bit - copy a pcode operator                          */
5019 /*-----------------------------------------------------------------*/
5020
5021 pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval)
5022 {
5023         pCodeOp *pcop;
5024         
5025         pcop = newpCodeOpBit(pc->name, bitval, 0);
5026         
5027         if( !( (pcop->type == PO_LABEL) ||
5028                 (pcop->type == PO_LITERAL) ||
5029                 (pcop->type == PO_STR) ))
5030                 PCOR(pcop)->r = PCOR(pc)->r;  /* This is dangerous... */
5031         
5032         return pcop;
5033 }
5034
5035 /*-----------------------------------------------------------------*/
5036 /*-----------------------------------------------------------------*/
5037 void pBlockDestruct(pBlock *pb)
5038 {
5039         
5040         if(!pb)
5041                 return;
5042         
5043         
5044         free(pb);
5045         
5046 }
5047
5048 /*-----------------------------------------------------------------*/
5049 /* void mergepBlocks(char dbName) - Search for all pBlocks with the*/
5050 /*                                  name dbName and combine them   */
5051 /*                                  into one block                 */
5052 /*-----------------------------------------------------------------*/
5053 void mergepBlocks(char dbName)
5054 {
5055         
5056         pBlock *pb, *pbmerged = NULL,*pbn;
5057         
5058         pb = the_pFile->pbHead;
5059         
5060         //fprintf(stderr," merging blocks named %c\n",dbName);
5061         while(pb) {
5062                 
5063                 pbn = pb->next;
5064                 //fprintf(stderr,"looking at %c\n",getpBlock_dbName(pb));
5065                 if( getpBlock_dbName(pb) == dbName) {
5066                         
5067                         //fprintf(stderr," merged block %c\n",dbName);
5068                         
5069                         if(!pbmerged) {
5070                                 pbmerged = pb;
5071                         } else {
5072                                 addpCode2pBlock(pbmerged, pb->pcHead);
5073                                 /* addpCode2pBlock doesn't handle the tail: */
5074                                 pbmerged->pcTail = pb->pcTail;
5075                                 
5076                                 pb->prev->next = pbn;
5077                                 if(pbn) 
5078                                         pbn->prev = pb->prev;
5079                                 
5080                                 
5081                                 pBlockDestruct(pb);
5082                         }
5083                         //printpBlock(stderr, pbmerged);
5084                 } 
5085                 pb = pbn;
5086         }
5087         
5088 }
5089
5090 /*-----------------------------------------------------------------*/
5091 /* AnalyzeFlow - Examine the flow of the code and optimize         */
5092 /*                                                                 */
5093 /* level 0 == minimal optimization                                 */
5094 /*   optimize registers that are used only by two instructions     */
5095 /* level 1 == maximal optimization                                 */
5096 /*   optimize by looking at pairs of instructions that use the     */
5097 /*   register.                                                     */
5098 /*-----------------------------------------------------------------*/
5099
5100 void AnalyzeFlow(int level)
5101 {
5102         static int times_called=0;
5103         
5104         pBlock *pb;
5105         
5106         if(!the_pFile)
5107                 return;
5108         
5109         
5110                 /* if this is not the first time this function has been called,
5111         then clean up old flow information */
5112         if(times_called++) {
5113                 for(pb = the_pFile->pbHead; pb; pb = pb->next)
5114                         unBuildFlow(pb);
5115                 
5116                 RegsUnMapLiveRanges();
5117                 
5118         }
5119         
5120         GpcFlowSeq = 1;
5121         
5122         /* Phase 2 - Flow Analysis - Register Banking
5123         *
5124         * In this phase, the individual flow blocks are examined
5125         * and register banking is fixed.
5126         */
5127         
5128         //for(pb = the_pFile->pbHead; pb; pb = pb->next)
5129         //FixRegisterBanking(pb);
5130         
5131         /* Phase 2 - Flow Analysis
5132         *
5133         * In this phase, the pCode is partition into pCodeFlow 
5134         * blocks. The flow blocks mark the points where a continuous
5135         * stream of instructions changes flow (e.g. because of
5136         * a call or goto or whatever).
5137         */
5138         
5139         for(pb = the_pFile->pbHead; pb; pb = pb->next)
5140                 BuildFlow(pb);
5141         
5142         
5143                 /* Phase 2 - Flow Analysis - linking flow blocks
5144                 *
5145                 * In this phase, the individual flow blocks are examined
5146                 * to determine their order of excution.
5147         */
5148         
5149         for(pb = the_pFile->pbHead; pb; pb = pb->next)
5150                 LinkFlow(pb);
5151         
5152                 /* Phase 3 - Flow Analysis - Flow Tree
5153                 *
5154                 * In this phase, the individual flow blocks are examined
5155                 * to determine their order of excution.
5156         */
5157         
5158         for(pb = the_pFile->pbHead; pb; pb = pb->next)
5159                 BuildFlowTree(pb);
5160         
5161         
5162                 /* Phase x - Flow Analysis - Used Banks
5163                 *
5164                 * In this phase, the individual flow blocks are examined
5165                 * to determine the Register Banks they use
5166         */
5167         
5168         //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
5169         //    FixBankFlow(pb);
5170         
5171         
5172         for(pb = the_pFile->pbHead; pb; pb = pb->next)
5173                 pCodeRegMapLiveRanges(pb);
5174         
5175         RemoveUnusedRegisters();
5176         
5177         //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
5178         pCodeRegOptimizeRegUsage(level);
5179         
5180         OptimizepCode('*');
5181         
5182         /*      
5183         for(pb = the_pFile->pbHead; pb; pb = pb->next)
5184         DumpFlow(pb);
5185         */
5186         /* debug stuff */
5187         /*
5188         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5189     pCode *pcflow;
5190     for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
5191     (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5192     pcflow = pcflow->next) {
5193     
5194           FillFlow(PCFL(pcflow));
5195           }
5196           }
5197         */
5198         /*
5199         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5200     pCode *pcflow;
5201     for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); 
5202     (pcflow = findNextpCode(pcflow, PC_FLOW)) != NULL;
5203     pcflow = pcflow->next) {
5204         
5205           FlowStats(PCFL(pcflow));
5206           }
5207           }
5208         */
5209 }
5210
5211 /*-----------------------------------------------------------------*/
5212 /* AnalyzeBanking - Called after the memory addresses have been    */
5213 /*                  assigned to the registers.                     */
5214 /*                                                                 */
5215 /*-----------------------------------------------------------------*/
5216
5217 void AnalyzeBanking(void)
5218 {
5219         pBlock  *pb;
5220
5221         if(!picIsInitialized()) {
5222                 werror(E_FILE_OPEN_ERR, "no memory size is known for this processor");
5223                 exit(1);
5224         }
5225         
5226         if (!the_pFile) return;
5227         
5228         /* Phase x - Flow Analysis - Used Banks
5229         *
5230         * In this phase, the individual flow blocks are examined
5231         * to determine the Register Banks they use
5232         */
5233         
5234         AnalyzeFlow(0);
5235         AnalyzeFlow(1);
5236         
5237         //  for(pb = the_pFile->pbHead; pb; pb = pb->next)
5238         //    BanksUsedFlow(pb);
5239         for(pb = the_pFile->pbHead; pb; pb = pb->next)
5240                 FixRegisterBanking(pb);
5241
5242         AnalyzeFlow(0);
5243         AnalyzeFlow(1);
5244         
5245 }
5246
5247 /*-----------------------------------------------------------------*/
5248 /*-----------------------------------------------------------------*/
5249 DEFSETFUNC (resetrIdx)
5250 {
5251         regs *r = (regs *)item;
5252         if (!r->isFixed) {
5253                 r->rIdx = 0;
5254         }
5255         
5256         return 0;
5257 }
5258
5259 /*-----------------------------------------------------------------*/
5260 /* InitRegReuse - Initialises variables for code analyzer          */
5261 /*-----------------------------------------------------------------*/
5262 void InitReuseReg(void)
5263 {
5264         /* Find end of statically allocated variables for start idx */
5265         /* Start from begining of GPR. Note may not be 0x20 on some PICs */
5266         /* XXX: Avoid clashes with fixed registers, start late. */
5267         unsigned maxIdx = 0x1000;
5268         regs *r;
5269         for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) {
5270                 if (r->type != REG_SFR) {
5271                         maxIdx += r->size; /* Increment for all statically allocated variables */
5272                 }
5273         }
5274         peakIdx = maxIdx;
5275         applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */
5276 }
5277
5278 /*-----------------------------------------------------------------*/
5279 /*-----------------------------------------------------------------*/
5280 static unsigned register_reassign(pBlock *pb, unsigned idx, unsigned level)
5281 {
5282     pCode *pc;
5283
5284     /* check recursion */
5285     pc = setFirstItem(pb->function_entries);
5286     if(!pc)
5287         return idx;
5288
5289     if (pb->visited) {
5290         /* TODO: Recursion detection missing, should emit a warning as recursive code will fail. */
5291         return idx;
5292     }
5293
5294     pb->visited = 1;
5295
5296     DFPRINTF((stderr," (%u) reassigning registers for function \"%s\"\n",level,PCF(pc)->fname));
5297
5298     if (pb->tregisters) {
5299         regs *r;
5300         for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) {
5301             if (r->type == REG_GPR) {
5302                 if (!r->isFixed) {
5303                     if (r->rIdx < (int)idx) {
5304                         char s[20];
5305                         set *regset;
5306                         // make sure, idx is not yet used in this routine...
5307                         do {
5308                             regset = pb->tregisters;
5309                             // do not touch s->curr ==> outer loop!
5310                             while (regset && ((regs *)regset->item)->rIdx != idx) {
5311                                 regset = regset->next;
5312                             }
5313                             if (regset) idx++;
5314                         } while (regset);
5315                         r->rIdx = idx++;
5316                         if (peakIdx < idx) peakIdx = idx;
5317                         sprintf(s,"r0x%02X", r->rIdx);
5318                         DFPRINTF((stderr," (%u) reassigning register %p \"%s\" to \"%s\"\n",level,r,r->name,s));
5319                         free(r->name);
5320                         r->name = Safe_strdup(s);
5321                     }
5322                 }
5323             }
5324         }
5325     }
5326     for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) {
5327
5328         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5329             char *dest = get_op_from_instruction(PCI(pc));
5330
5331             pCode *pcn = findFunction(dest);
5332             if(pcn) {
5333                 /* This index increment from subroutines is not required, as all subroutines
5334                  * may share registers NOT used by this one (< idx).
5335                  * BUT if called functions A and B share a register, which gets assigned
5336                  * rIdx = idx + 4 while analyzing A, we must not assign idx + 4 again while
5337                  * analyzing B!
5338                  * As an alternative to this "solution" we could check above whether an
5339                  * to-be-assigned rIdx is already present in the register set of the
5340                  * current function. This would increase the reused registers and make this
5341                  * `idx =' irrelevant.
5342                  * UPDATE: Implemented above; not fast, but works.
5343                  * (Problem shown with regression test src/regression/sub2.c)
5344                  */
5345                 /*idx = */register_reassign(pcn->pb,idx,level+1);
5346             }
5347         }
5348     }
5349
5350     return idx;
5351 }
5352
5353 /*------------------------------------------------------------------*/
5354 /* ReuseReg were call tree permits                                  */
5355 /*                                                                  */
5356 /*  Re-allocate the GPR for optimum reuse for a given pblock        */ 
5357 /*  eg  if a function m() calls function f1() and f2(), where f1    */
5358 /*  allocates a local variable vf1 and f2 allocates a local         */
5359 /*  variable vf2. Then providing f1 and f2 do not call each other   */
5360 /*  they may share the same general purpose registers for vf1 and   */
5361 /*  vf2.                                                            */
5362 /*  This is done by first setting the the regs rIdx to start after  */
5363 /*  all the global variables, then walking through the call tree    */
5364 /*  renaming the registers to match their new idx and incrementng   */
5365 /*  it as it goes. If a function has already been called it will    */
5366 /*  only rename the registers if it has already used up those       */
5367 /*  registers ie rIdx of the function's registers is lower than the */
5368 /*  current rIdx. That way the register will not be reused while    */
5369 /*  still being used by an eariler function call.                   */
5370 /*                                                                  */
5371 /*  Note for this to work the functions need to be declared static. */
5372 /*                                                                  */
5373 /*------------------------------------------------------------------*/
5374 void ReuseReg(void)
5375 {
5376         pBlock  *pb;
5377         if (!the_pFile) return;
5378         InitReuseReg();
5379         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5380                 /* Non static functions can be called from other modules so their registers must reassign */
5381                 if (pb->function_entries && (PCF(setFirstItem(pb->function_entries))->isPublic || !pb->visited))
5382                         register_reassign(pb,peakIdx,0);
5383         }
5384 }
5385
5386 /*-----------------------------------------------------------------*/
5387 /* buildCallTree - look at the flow and extract all of the calls   */
5388 /*                                                                 */
5389 /*-----------------------------------------------------------------*/
5390
5391 void buildCallTree(void    )
5392 {
5393         pBranch *pbr;
5394         pBlock  *pb;
5395         pCode   *pc;
5396         
5397         if(!the_pFile)
5398                 return;
5399         
5400                 /* Now build the call tree.
5401                 First we examine all of the pCodes for functions.
5402                 Keep in mind that the function boundaries coincide
5403                 with pBlock boundaries. 
5404                 
5405                   The algorithm goes something like this:
5406                   We have two nested loops. The outer loop iterates
5407                   through all of the pBlocks/functions. The inner
5408                   loop iterates through all of the pCodes for
5409                   a given pBlock. When we begin iterating through
5410                   a pBlock, the variable pc_fstart, pCode of the start
5411                   of a function, is cleared. We then search for pCodes
5412                   of type PC_FUNCTION. When one is encountered, we
5413                   initialize pc_fstart to this and at the same time
5414                   associate a new pBranch object that signifies a 
5415                   branch entry. If a return is found, then this signifies
5416                   a function exit point. We'll link the pCodes of these
5417                   returns to the matching pc_fstart.
5418                   
5419                         When we're done, a doubly linked list of pBranches
5420                         will exist. The head of this list is stored in
5421                         `the_pFile', which is the meta structure for all
5422                         of the pCode. Look at the printCallTree function
5423                         on how the pBranches are linked together.
5424                         
5425         */
5426         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5427                 pCode *pc_fstart=NULL;
5428                 for(pc = pb->pcHead; pc; pc = pc->next) {
5429                         if(isPCF(pc)) {
5430                                 pCodeFunction *pcf = PCF(pc);
5431                                 if (pcf->fname) {
5432                                         
5433                                         if(STRCASECMP(pcf->fname, "_main") == 0) {
5434                                                 //fprintf(stderr," found main \n");
5435                                                 pb->cmemmap = NULL;  /* FIXME do we need to free ? */
5436                                                 pb->dbName = 'M';
5437                                         }
5438                                         
5439                                         pbr = Safe_calloc(1,sizeof(pBranch));
5440                                         pbr->pc = pc_fstart = pc;
5441                                         pbr->next = NULL;
5442                                         
5443                                         the_pFile->functions = pBranchAppend(the_pFile->functions,pbr);
5444                                         
5445                                         // Here's a better way of doing the same:
5446                                         addSet(&pb->function_entries, pc);
5447                                         
5448                                 } else {
5449                                         // Found an exit point in a function, e.g. return
5450                                         // (Note, there may be more than one return per function)
5451                                         if(pc_fstart)
5452                                                 pBranchLink(PCF(pc_fstart), pcf);
5453                                         
5454                                         addSet(&pb->function_exits, pc);
5455                                 }
5456                         } else if(isCALL(pc)) {
5457                                 addSet(&pb->function_calls,pc);
5458                         }
5459                 }
5460         }
5461 }
5462
5463 /*-----------------------------------------------------------------*/
5464 /* AnalyzepCode - parse the pCode that has been generated and form */
5465 /*                all of the logical connections.                  */
5466 /*                                                                 */
5467 /* Essentially what's done here is that the pCode flow is          */
5468 /* determined.                                                     */
5469 /*-----------------------------------------------------------------*/
5470
5471 void AnalyzepCode(char dbName)
5472 {
5473         pBlock *pb;
5474         int i,changes;
5475         
5476         if(!the_pFile)
5477                 return;
5478         
5479         mergepBlocks('D');
5480         
5481         
5482         /* Phase 1 - Register allocation and peep hole optimization
5483         *
5484         * The first part of the analysis is to determine the registers
5485         * that are used in the pCode. Once that is done, the peep rules
5486         * are applied to the code. We continue to loop until no more
5487         * peep rule optimizations are found (or until we exceed the
5488         * MAX_PASSES threshold). 
5489         *
5490         * When done, the required registers will be determined.
5491         *
5492         */
5493         i = 0;
5494         do {
5495                 
5496                 DFPRINTF((stderr," Analyzing pCode: PASS #%d\n",i+1));
5497                 
5498                 /* First, merge the labels with the instructions */
5499                 for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5500                         if('*' == dbName || getpBlock_dbName(pb) == dbName) {
5501                                 
5502                                 DFPRINTF((stderr," analyze and merging block %c\n",dbName));
5503                                 pBlockMergeLabels(pb);
5504                                 AnalyzepBlock(pb);
5505                         } else {
5506                                 DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName(pb)));
5507                         }
5508                 }
5509                 
5510                 changes = OptimizepCode(dbName);
5511                 
5512         } while(changes && (i++ < MAX_PASSES));
5513         
5514         buildCallTree();
5515 }
5516
5517 /*-----------------------------------------------------------------*/
5518 /* ispCodeFunction - returns true if *pc is the pCode of a         */
5519 /*                   function                                      */
5520 /*-----------------------------------------------------------------*/
5521 bool ispCodeFunction(pCode *pc)
5522 {
5523         
5524         if(pc && pc->type == PC_FUNCTION && PCF(pc)->fname)
5525                 return 1;
5526         
5527         return 0;
5528 }
5529
5530 /*-----------------------------------------------------------------*/
5531 /* findFunction - Search for a function by name (given the name)   */
5532 /*                in the set of all functions that are in a pBlock */
5533 /* (note - I expect this to change because I'm planning to limit   */
5534 /*  pBlock's to just one function declaration                      */
5535 /*-----------------------------------------------------------------*/
5536 pCode *findFunction(char *fname)
5537 {
5538         pBlock *pb;
5539         pCode *pc;
5540         if(!fname)
5541                 return NULL;
5542         
5543         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5544                 
5545                 pc = setFirstItem(pb->function_entries);
5546                 while(pc) {
5547                         
5548                         if((pc->type == PC_FUNCTION) &&
5549                                 (PCF(pc)->fname) && 
5550                                 (strcmp(fname, PCF(pc)->fname)==0))
5551                                 return pc;
5552                         
5553                         pc = setNextItem(pb->function_entries);
5554                         
5555                 }
5556                 
5557         }
5558         return NULL;
5559 }
5560
5561 void MarkUsedRegisters(set *regset)
5562 {
5563         
5564         regs *r1,*r2;
5565         
5566         for(r1=setFirstItem(regset); r1; r1=setNextItem(regset)) {
5567                 r2 = pic14_regWithIdx(r1->rIdx);
5568                 if (r2) {
5569                         r2->isFree = 0;
5570                         r2->wasUsed = 1;
5571                 }
5572         }
5573 }
5574
5575 void pBlockStats(FILE *of, pBlock *pb)
5576 {
5577         
5578         pCode *pc;
5579         regs  *r;
5580         
5581         fprintf(of,";***\n;  pBlock Stats: dbName = %c\n;***\n",getpBlock_dbName(pb));
5582         
5583         // for now just print the first element of each set
5584         pc = setFirstItem(pb->function_entries);
5585         if(pc) {
5586                 fprintf(of,";entry:  ");
5587                 pc->print(of,pc);
5588         }
5589         pc = setFirstItem(pb->function_exits);
5590         if(pc) {
5591                 fprintf(of,";has an exit\n");
5592                 //pc->print(of,pc);
5593         }
5594         
5595         pc = setFirstItem(pb->function_calls);
5596         if(pc) {
5597                 fprintf(of,";functions called:\n");
5598                 
5599                 while(pc) {
5600                         if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5601                                 fprintf(of,";   %s\n",get_op_from_instruction(PCI(pc)));
5602                         }
5603                         pc = setNextItem(pb->function_calls);
5604                 }
5605         }
5606         
5607         r = setFirstItem(pb->tregisters);
5608         if(r) {
5609                 int n = elementsInSet(pb->tregisters);
5610                 
5611                 fprintf(of,";%d compiler assigned register%c:\n",n, ( (n!=1) ? 's' : ' '));
5612                 
5613                 while (r) {
5614                         fprintf(of,";   %s\n",r->name);
5615                         r = setNextItem(pb->tregisters);
5616                 }
5617         }
5618 }
5619
5620 /*-----------------------------------------------------------------*/
5621 /*-----------------------------------------------------------------*/
5622 #if 0
5623 static void sequencepCode(void)
5624 {
5625         pBlock *pb;
5626         pCode *pc;
5627         
5628         
5629         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5630                 
5631                 pb->seq = GpCodeSequenceNumber+1;
5632                 
5633                 for( pc = pb->pcHead; pc; pc = pc->next)
5634                         pc->seq = ++GpCodeSequenceNumber;
5635         }
5636         
5637 }
5638 #endif
5639
5640 /*-----------------------------------------------------------------*/
5641 /*-----------------------------------------------------------------*/
5642 /*
5643 set *register_usage(pBlock *pb)
5644 {
5645         pCode *pc,*pcn;
5646         set *registers=NULL;
5647         set *registersInCallPath = NULL;
5648         
5649         / * check recursion * /
5650                 
5651                 pc = setFirstItem(pb->function_entries);
5652         
5653         if(!pc)
5654                 return registers;
5655         
5656         pb->visited = 1;
5657         
5658         if(pc->type != PC_FUNCTION)
5659                 fprintf(stderr,"%s, first pc is not a function???\n",__FUNCTION__);
5660         
5661         pc = setFirstItem(pb->function_calls);
5662         for( ; pc; pc = setNextItem(pb->function_calls)) {
5663                 
5664                 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5665                         char *dest = get_op_from_instruction(PCI(pc));
5666                         
5667                         pcn = findFunction(dest);
5668                         if(pcn) 
5669                                 registersInCallPath = register_usage(pcn->pb);
5670                 } else
5671                         fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5672                 
5673         }
5674         
5675 #ifdef PCODE_DEBUG
5676         pBlockStats(stderr,pb);  // debug
5677 #endif
5678         
5679         // Mark the registers in this block as used.
5680         
5681         MarkUsedRegisters(pb->tregisters);
5682         if(registersInCallPath) {
5683                 / * registers were used in the functions this pBlock has called * /
5684                 / * so now, we need to see if these collide with the ones we are * /
5685                 / * using here * /
5686                 
5687                         regs *r1,*r2, *newreg;
5688                 
5689                 DFPRINTF((stderr,"comparing registers\n"));
5690                 
5691                 r1 = setFirstItem(registersInCallPath);
5692                 while(r1) {
5693                         if (r1->type != REG_STK) {
5694                                 r2 = setFirstItem(pb->tregisters);
5695                                 
5696                                 while(r2 && (r2->type != REG_STK)) {
5697                                         
5698                                         if(r2->rIdx == r1->rIdx) {
5699                                                 newreg = pic14_findFreeReg(REG_GPR);
5700                                                 
5701                                                 
5702                                                 if(!newreg) {
5703                                                         DFPRINTF((stderr,"Bummer, no more registers.\n"));
5704                                                         exit(1);
5705                                                 }
5706                                                 
5707                                                 DFPRINTF((stderr,"Cool found register collision nIdx=%d moving to %d\n",
5708                                                         r1->rIdx, newreg->rIdx));
5709                                                 r2->rIdx = newreg->rIdx;
5710                                                 if(newreg->name)
5711                                                         r2->name = Safe_strdup(newreg->name);
5712                                                 else
5713                                                         r2->name = NULL;
5714                                                 newreg->isFree = 0;
5715                                                 newreg->wasUsed = 1;
5716                                         }
5717                                         r2 = setNextItem(pb->tregisters);
5718                                 }
5719                         }
5720                         
5721                         r1 = setNextItem(registersInCallPath);
5722                 }
5723                 
5724                 / * Collisions have been resolved. Now free the registers in the call path * /
5725                 r1 = setFirstItem(registersInCallPath);
5726                 while(r1) {
5727                         newreg = pic14_regWithIdx(r1->rIdx);
5728                         if (newreg) newreg->isFree = 1;
5729                         r1 = setNextItem(registersInCallPath);
5730                 }
5731                 
5732         }// else
5733         //      MarkUsedRegisters(pb->registers);
5734         
5735         registers = unionSets(pb->tregisters, registersInCallPath, THROW_NONE);
5736 #ifdef PCODE_DEBUG
5737         if(registers) 
5738                 DFPRINTF((stderr,"returning regs\n"));
5739         else
5740                 DFPRINTF((stderr,"not returning regs\n"));
5741         
5742         DFPRINTF((stderr,"pBlock after register optim.\n"));
5743         pBlockStats(stderr,pb);  // debug
5744 #endif
5745         
5746         return registers;
5747 }
5748 */
5749
5750 /*-----------------------------------------------------------------*/
5751 /* printCallTree - writes the call tree to a file                  */
5752 /*                                                                 */
5753 /*-----------------------------------------------------------------*/
5754 void pct2(FILE *of,pBlock *pb,int indent)
5755 {
5756         pCode *pc,*pcn;
5757         int i;
5758         //  set *registersInCallPath = NULL;
5759         
5760         if(!of)
5761                 return;
5762         
5763         if(indent > 10)
5764                 return; //recursion ?
5765         
5766         pc = setFirstItem(pb->function_entries);
5767         
5768         if(!pc)
5769                 return;
5770         
5771         pb->visited = 0;
5772         
5773         for(i=0;i<indent;i++)   // Indentation
5774                 fputc(' ',of);
5775         
5776         if(pc->type == PC_FUNCTION)
5777                 fprintf(of,"%s\n",PCF(pc)->fname);
5778         else
5779                 return;  // ???
5780         
5781         
5782         pc = setFirstItem(pb->function_calls);
5783         for( ; pc; pc = setNextItem(pb->function_calls)) {
5784                 
5785                 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) {
5786                         char *dest = get_op_from_instruction(PCI(pc));
5787                         
5788                         pcn = findFunction(dest);
5789                         if(pcn) 
5790                                 pct2(of,pcn->pb,indent+1);
5791                 } else
5792                         fprintf(of,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5793                 
5794         }
5795         
5796         
5797 }
5798
5799
5800 /*-----------------------------------------------------------------*/
5801 /* printCallTree - writes the call tree to a file                  */
5802 /*                                                                 */
5803 /*-----------------------------------------------------------------*/
5804
5805 void printCallTree(FILE *of)
5806 {
5807         pBranch *pbr;
5808         pBlock  *pb;
5809         pCode   *pc;
5810         
5811         if(!the_pFile)
5812                 return;
5813         
5814         if(!of)
5815                 of = stderr;
5816         
5817         fprintf(of, "\npBlock statistics\n");
5818         for(pb = the_pFile->pbHead; pb;  pb = pb->next )
5819                 pBlockStats(of,pb);
5820         
5821         
5822         
5823         fprintf(of,"Call Tree\n");
5824         pbr = the_pFile->functions;
5825         while(pbr) {
5826                 if(pbr->pc) {
5827                         pc = pbr->pc;
5828                         if(!ispCodeFunction(pc))
5829                                 fprintf(of,"bug in call tree");
5830                         
5831                         
5832                         fprintf(of,"Function: %s\n", PCF(pc)->fname);
5833                         
5834                         while(pc->next && !ispCodeFunction(pc->next)) {
5835                                 pc = pc->next;
5836                                 if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL)
5837                                         fprintf(of,"\t%s\n",get_op_from_instruction(PCI(pc)));
5838                         }
5839                 }
5840                 
5841                 pbr = pbr->next;
5842         }
5843         
5844         
5845         fprintf(of,"\n**************\n\na better call tree\n");
5846         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5847                 if(pb->visited)
5848                         pct2(of,pb,0);
5849         }
5850         
5851         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5852                 fprintf(of,"block dbname: %c\n", getpBlock_dbName(pb));
5853         }
5854 }
5855
5856
5857
5858 /*-----------------------------------------------------------------*/
5859 /*                                                                 */
5860 /*-----------------------------------------------------------------*/
5861
5862 void InlineFunction(pBlock *pb)
5863 {
5864         pCode *pc;
5865         pCode *pc_call;
5866         
5867         if(!pb)
5868                 return;
5869         
5870         pc = setFirstItem(pb->function_calls);
5871         
5872         for( ; pc; pc = setNextItem(pb->function_calls)) {
5873                 
5874                 if(isCALL(pc)) {
5875                         pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5876                         pCode *pcp = pc->prev;
5877                         pCode *pct;
5878                         pCode *pce;
5879                         
5880                         pBranch *pbr;
5881                         
5882                         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 */
5883                                 
5884                                 InlineFunction(pcn->pb);
5885                                 
5886                                 /*
5887                                 At this point, *pc points to a CALL mnemonic, and
5888                                 *pcn points to the function that is being called.
5889                                 
5890                                   To in-line this call, we need to remove the CALL
5891                                   and RETURN(s), and link the function pCode in with
5892                                   the CALLee pCode.
5893                                   
5894                                 */
5895                                 
5896                                 pc_call = pc;
5897                                 
5898                                 /* Check if previous instruction was a bit skip */
5899                                 if (isPCI_BITSKIP(pcp)) {
5900                                         pCodeLabel *pcl;
5901                                         /* Invert skip instruction and add a goto */
5902                                         PCI(pcp)->op = (PCI(pcp)->op == POC_BTFSS) ? POC_BTFSC : POC_BTFSS;
5903                                         
5904                                         if(isPCL(pc_call->next)) { // Label pcode
5905                                                 pcl = PCL(pc_call->next);
5906                                         } else if (isPCI(pc_call->next) && PCI(pc_call->next)->label) { // pcode instruction with a label
5907                                                 pcl = PCL(PCI(pc_call->next)->label->pc);
5908                                         } else {
5909                                                 pcl = PCL(newpCodeLabel(NULL, newiTempLabel(NULL)->key+100));
5910                                                 PCI(pc_call->next)->label->pc = (struct pCode*)pcl;
5911                                         }
5912                                         pCodeInsertAfter(pcp, newpCode(POC_GOTO, newpCodeOp(pcl->label,PO_STR)));
5913                                 }
5914                                 
5915                                 /* remove callee pBlock from the pBlock linked list */
5916                                 removepBlock(pcn->pb);
5917                                 
5918                                 pce = pcn;
5919                                 while(pce) {
5920                                         pce->pb = pb;
5921                                         pce = pce->next;
5922                                 }
5923                                 
5924                                 /* Remove the Function pCode */
5925                                 pct = findNextInstruction(pcn->next);
5926                                 
5927                                 /* Link the function with the callee */
5928                                 if (pcp) pcp->next = pcn->next;
5929                                 pcn->next->prev = pcp;
5930                                 
5931                                 /* Convert the function name into a label */
5932                                 
5933                                 pbr = Safe_calloc(1,sizeof(pBranch));
5934                                 pbr->pc = newpCodeLabel(PCF(pcn)->fname, -1);
5935                                 pbr->next = NULL;
5936                                 PCI(pct)->label = pBranchAppend(PCI(pct)->label,pbr);
5937                                 PCI(pct)->label = pBranchAppend(PCI(pct)->label,PCI(pc_call)->label);
5938                                 
5939                                 /* turn all of the return's except the last into goto's */
5940                                 /* check case for 2 instruction pBlocks */
5941                                 pce = findNextInstruction(pcn->next);
5942                                 while(pce) {
5943                                         pCode *pce_next = findNextInstruction(pce->next);
5944                                         
5945                                         if(pce_next == NULL) {
5946                                                 /* found the last return */
5947                                                 pCode *pc_call_next =  findNextInstruction(pc_call->next);
5948                                                 
5949                                                 //fprintf(stderr,"found last return\n");
5950                                                 //pce->print(stderr,pce);
5951                                                 pce->prev->next = pc_call->next;
5952                                                 pc_call->next->prev = pce->prev;
5953                                                 PCI(pc_call_next)->label = pBranchAppend(PCI(pc_call_next)->label,
5954                                                         PCI(pce)->label);
5955                                         }
5956                                         
5957                                         pce = pce_next;
5958                                 }
5959                                 
5960                         }
5961                 } else
5962                         fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
5963                 
5964         }
5965         
5966 }
5967
5968 /*-----------------------------------------------------------------*/
5969 /*                                                                 */
5970 /*-----------------------------------------------------------------*/
5971
5972 void InlinepCode(void)
5973 {
5974         
5975         pBlock  *pb;
5976         pCode   *pc;
5977         
5978         if(!the_pFile)
5979                 return;
5980         
5981         if(!functionInlining)
5982                 return;
5983         
5984                 /* Loop through all of the function definitions and count the
5985         * number of times each one is called */
5986         //fprintf(stderr,"inlining %d\n",__LINE__);
5987         
5988         for(pb = the_pFile->pbHead; pb; pb = pb->next) {
5989                 
5990                 pc = setFirstItem(pb->function_calls);
5991                 
5992                 for( ; pc; pc = setNextItem(pb->function_calls)) {
5993                         
5994                         if(isCALL(pc)) {
5995                                 pCode *pcn = findFunction(get_op_from_instruction(PCI(pc)));
5996                                 if(pcn && isPCF(pcn)) {
5997                                         PCF(pcn)->ncalled++;
5998                                 }
5999                         } else
6000                                 fprintf(stderr,"BUG? pCode isn't a POC_CALL %d\n",__LINE__);
6001                         
6002                 }
6003         }
6004         
6005         //fprintf(stderr,"inlining %d\n",__LINE__);
6006         
6007         /* Now, Loop through the function definitions again, but this
6008         * time inline those functions that have only been called once. */
6009         
6010         InlineFunction(the_pFile->pbHead);
6011         //fprintf(stderr,"inlining %d\n",__LINE__);
6012         
6013         for(pb = the_pFile->pbHead; pb; pb = pb->next)
6014                 unBuildFlow(pb);
6015         
6016 }