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