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