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