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