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