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