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