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