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