1 /*------------------------------------------------------------------------
2
3 ralloc.c - source file for register allocation. PIC16 specific
4
5 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
6 Added Pic Port T.scott Dattalo scott@dattalo.com (2000)
7 Added Pic16 Port Martin Dubuc m.dubuc@rogers.com (2002)
8
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
12 later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
27
28 #include "common.h"
29 #include "ralloc.h"
30 #include "pcode.h"
31 #include "gen.h"
32 #include "device.h"
33
34 #ifndef debugf
35 #define debugf(frm, rest) _debugf(__FILE__, __LINE__, frm, rest)
36 #endif
37 void _debugf(char *f, int l, char *frm, ...);
38
39 #define NEWREG_DEBUG 0
40 //#define USE_ONSTACK
41
42
43 /*-----------------------------------------------------------------*/
44 /* At this point we start getting processor specific although */
45 /* some routines are non-processor specific & can be reused when */
46 /* targetting other processors. The decision for this will have */
47 /* to be made on a routine by routine basis */
48 /* routines used to pack registers are most definitely not reusable */
49 /* since the pack the registers depending strictly on the MCU */
50 /*-----------------------------------------------------------------*/
51
52 reg_info *pic16_typeRegWithIdx (int idx, int type, int fixed);
53 extern void genpic16Code (iCode *);
54
55 /* Global data */
56 static struct
57 {
58 bitVect *spiltSet;
59 set *stackSpil;
60 bitVect *regAssigned;
61 short blockSpil;
62 int slocNum;
63 bitVect *funcrUsed; /* registers used in a function */
64 int stackExtend;
65 int dataExtend;
66 }
67 _G;
68
69 /* Shared with gen.c */
70 int pic16_ptrRegReq; /* one byte pointer register required */
71
72
73 set *pic16_dynAllocRegs=NULL;
74 set *pic16_dynStackRegs=NULL;
75 set *pic16_dynProcessorRegs=NULL;
76 set *pic16_dynDirectRegs=NULL;
77 set *pic16_dynDirectBitRegs=NULL;
78 set *pic16_dynInternalRegs=NULL;
79 set *pic16_dynAccessRegs=NULL;
80
81 static hTab *dynDirectRegNames=NULL;
82 static hTab *dynAllocRegNames=NULL;
83 static hTab *dynProcRegNames=NULL;
84 static hTab *dynAccessRegNames=NULL;
85 //static hTab *regHash = NULL; /* a hash table containing ALL registers */
86
87 extern set *sectNames;
88
89 set *pic16_rel_udata=NULL; /* relocatable uninitialized registers */
90 set *pic16_fix_udata=NULL; /* absolute uninitialized registers */
91 set *pic16_equ_data=NULL; /* registers used by equates */
92 set *pic16_int_regs=NULL; /* internal registers placed in access bank 0 to 0x7f */
93 set *pic16_acs_udata=NULL; /* access bank variables */
94
95 set *pic16_builtin_functions=NULL;
96
97 static int dynrIdx=0x00; //0x20; // starting temporary register rIdx
98 static int rDirectIdx=0;
99
100 int pic16_nRegs = 128; // = sizeof (regspic16) / sizeof (regs);
101
102 int pic16_Gstack_base_addr=0; /* The starting address of registers that
103 * are used to pass and return parameters */
104
105
106 int _inRegAllocator=0; /* flag that marks whther allocReg happens while
107 * inside the register allocator function */
108
109
110 static void spillThis (symbol *);
111 int pic16_ralloc_debug = 0;
112 static FILE *debugF = NULL;
113 /*-----------------------------------------------------------------*/
114 /* debugLog - open a file for debugging information */
115 /*-----------------------------------------------------------------*/
116 //static void debugLog(char *inst,char *fmt, ...)
117 static void
debugLog(const char * fmt,...)118 debugLog (const char *fmt,...)
119 {
120 static int append = 0; // First time through, open the file without append.
121
122 char buffer[256];
123 //char *bufferP=buffer;
124 va_list ap;
125
126 if (!pic16_ralloc_debug || !dstFileName)
127 return;
128
129
130 if (!debugF)
131 {
132 /* create the file name */
133 SNPRINTF(buffer, sizeof(buffer), "%s.d", dstFileName);
134
135 if (!(debugF = fopen (buffer, (append ? "a+" : "w"))))
136 {
137 werror (E_FILE_OPEN_ERR, buffer);
138 exit (1);
139 }
140 append = 1; // Next time debubLog is called, we'll append the debug info
141 }
142
143 va_start (ap, fmt);
144
145 vsprintf (buffer, fmt, ap);
146
147 fprintf (debugF, "%s", buffer);
148 //fprintf (stderr, "%s", buffer);
149 /*
150 while (isspace((unsigned char)*bufferP)) bufferP++;
151
152 if (bufferP && *bufferP)
153 lineCurr = (lineCurr ?
154 connectLine(lineCurr,newLineNode(lb)) :
155 (lineHead = newLineNode(lb)));
156 lineCurr->isInline = _G.inLine;
157 lineCurr->isDebug = _G.debugLine;
158 */
159 va_end (ap);
160
161 }
162
163 static void
debugNewLine(void)164 debugNewLine (void)
165 {
166 if(!pic16_ralloc_debug)return;
167
168 if (debugF)
169 fputc ('\n', debugF);
170 }
171 /*-----------------------------------------------------------------*/
172 /* debugLogClose - closes the debug log file (if opened) */
173 /*-----------------------------------------------------------------*/
174 static void
debugLogClose(void)175 debugLogClose (void)
176 {
177 if (debugF) {
178 fclose (debugF);
179 debugF = NULL;
180 }
181 }
182
183 #define AOP(op) op->aop
184
185 static char *
debugAopGet(char * str,operand * op)186 debugAopGet (char *str, operand * op)
187 {
188 if(!pic16_ralloc_debug)return NULL;
189
190 if (str)
191 debugLog (str);
192
193 printOperand (op, debugF);
194 debugNewLine ();
195
196 return NULL;
197 }
198
199 char *
pic16_decodeOp(unsigned int op)200 pic16_decodeOp (unsigned int op)
201 {
202 if (op < 128 && op > ' ') {
203 buffer[0] = op & 0xff;
204 buffer[1] = '\0';
205 return buffer;
206 }
207
208 switch (op) {
209 case IDENTIFIER: return "IDENTIFIER";
210 case TYPE_NAME: return "TYPE_NAME";
211 case CONSTANT: return "CONSTANT";
212 case STRING_LITERAL: return "STRING_LITERAL";
213 case SIZEOF: return "SIZEOF";
214 case PTR_OP: return "PTR_OP";
215 case INC_OP: return "INC_OP";
216 case DEC_OP: return "DEC_OP";
217 case LEFT_OP: return "LEFT_OP";
218 case RIGHT_OP: return "RIGHT_OP";
219 case LE_OP: return "LE_OP";
220 case GE_OP: return "GE_OP";
221 case EQ_OP: return "EQ_OP";
222 case NE_OP: return "NE_OP";
223 case AND_OP: return "AND_OP";
224 case OR_OP: return "OR_OP";
225 case MUL_ASSIGN: return "MUL_ASSIGN";
226 case DIV_ASSIGN: return "DIV_ASSIGN";
227 case MOD_ASSIGN: return "MOD_ASSIGN";
228 case ADD_ASSIGN: return "ADD_ASSIGN";
229 case SUB_ASSIGN: return "SUB_ASSIGN";
230 case LEFT_ASSIGN: return "LEFT_ASSIGN";
231 case RIGHT_ASSIGN: return "RIGHT_ASSIGN";
232 case AND_ASSIGN: return "AND_ASSIGN";
233 case XOR_ASSIGN: return "XOR_ASSIGN";
234 case OR_ASSIGN: return "OR_ASSIGN";
235 case TYPEDEF: return "TYPEDEF";
236 case EXTERN: return "EXTERN";
237 case STATIC: return "STATIC";
238 case AUTO: return "AUTO";
239 case REGISTER: return "REGISTER";
240 case CODE: return "CODE";
241 case EEPROM: return "EEPROM";
242 case INTERRUPT: return "INTERRUPT";
243 case SFR: return "SFR";
244 case AT: return "AT";
245 case SBIT: return "SBIT";
246 case REENTRANT: return "REENTRANT";
247 case USING: return "USING";
248 case XDATA: return "XDATA";
249 case DATA: return "DATA";
250 case IDATA: return "IDATA";
251 case PDATA: return "PDATA";
252 case VAR_ARGS: return "VAR_ARGS";
253 case CRITICAL: return "CRITICAL";
254 case NONBANKED: return "NONBANKED";
255 case BANKED: return "BANKED";
256 case SD_CHAR: return "CHAR";
257 case SD_SHORT: return "SHORT";
258 case SD_INT: return "INT";
259 case SD_LONG: return "LONG";
260 case SIGNED: return "SIGNED";
261 case UNSIGNED: return "UNSIGNED";
262 case SD_FLOAT: return "FLOAT";
263 case DOUBLE: return "DOUBLE";
264 case SD_CONST: return "CONST";
265 case VOLATILE: return "VOLATILE";
266 case SD_VOID: return "VOID";
267 case BIT: return "BIT";
268 case STRUCT: return "STRUCT";
269 case UNION: return "UNION";
270 case ENUM: return "ENUM";
271 case RANGE: return "RANGE";
272 case SD_FAR: return "FAR";
273 case CASE: return "CASE";
274 case DEFAULT: return "DEFAULT";
275 case IF: return "IF";
276 case ELSE: return "ELSE";
277 case SWITCH: return "SWITCH";
278 case WHILE: return "WHILE";
279 case DO: return "DO";
280 case FOR: return "FOR";
281 case GOTO: return "GOTO";
282 case CONTINUE: return "CONTINUE";
283 case BREAK: return "BREAK";
284 case RETURN: return "RETURN";
285 case INLINEASM: return "INLINEASM";
286 case IFX: return "IFX";
287 case ADDRESS_OF: return "ADDRESS_OF";
288 case GET_VALUE_AT_ADDRESS: return "GET_VALUE_AT_ADDRESS";
289 case SPIL: return "SPIL";
290 case UNSPIL: return "UNSPIL";
291 case GETHBIT: return "GETHBIT";
292 case BITWISEAND: return "BITWISEAND";
293 case UNARYMINUS: return "UNARYMINUS";
294 case IPUSH: return "IPUSH";
295 case IPOP: return "IPOP";
296 case PCALL: return "PCALL";
297 case FUNCTION: return "FUNCTION";
298 case ENDFUNCTION: return "ENDFUNCTION";
299 case JUMPTABLE: return "JUMPTABLE";
300 case RRC: return "RRC";
301 case RLC: return "RLC";
302 case CAST: return "CAST";
303 case CALL: return "CALL";
304 case PARAM: return "PARAM ";
305 case NULLOP: return "NULLOP";
306 case BLOCK: return "BLOCK";
307 case LABEL: return "LABEL";
308 case RECEIVE: return "RECEIVE";
309 case SEND: return "SEND";
310 case DUMMY_READ_VOLATILE: return "DUMMY_READ_VOLATILE";
311 }
312 SNPRINTF(buffer, sizeof(buffer), "unknown op %d %c", op, op & 0xff);
313
314 return buffer;
315 }
316
317 #if 0
318 static const char *decodeRegType(short type)
319 {
320 switch(type) {
321 case REG_GPR: return "REG_GPR";
322 case REG_PTR: return "REG_PTR";
323 case REG_CND: return "REG_CNT";
324
325 default:
326 return "<unknown>";
327 }
328 }
329 #endif
330
331 /*-----------------------------------------------------------------*/
332 /*-----------------------------------------------------------------*/
333 static const char *
debugLogRegType(short type)334 debugLogRegType (short type)
335 {
336 if(!pic16_ralloc_debug)return NULL;
337 switch (type) {
338 case REG_GPR: return "REG_GPR";
339 case REG_PTR: return "REG_PTR";
340 case REG_CND: return "REG_CND";
341 }
342 SNPRINTF(buffer, sizeof(buffer), "unknown reg type %d", type);
343
344 return buffer;
345 }
346
347 /*-----------------------------------------------------------------*/
348 /*-----------------------------------------------------------------*/
regname2key(char const * name)349 static int regname2key(char const *name)
350 {
351 int key = 0;
352
353 if(!name)
354 return 0;
355
356 while(*name) {
357 key += (*name++) + 1;
358 }
359
360 return ((key + (key >> 4) + (key>>8)) & 0x3f);
361 }
362
363 /*-----------------------------------------------------------------*/
364 /* newReg - allocate and init memory for a new register */
365 /*-----------------------------------------------------------------*/
newReg(int type,short pc_type,int rIdx,const char * name,unsigned size,int alias,operand * refop)366 reg_info* newReg(int type, short pc_type, int rIdx, const char *name, unsigned size, int alias, operand *refop)
367 {
368
369 reg_info *dReg;
370
371 dReg = Safe_alloc(sizeof(reg_info));
372 dReg->type = type;
373 dReg->pc_type = pc_type;
374 dReg->rIdx = rIdx;
375 if(name)
376 dReg->name = Safe_strdup(name);
377 else {
378 if(pic16_options.xinst && pc_type == PO_GPR_TEMP) {
379 SNPRINTF(buffer, sizeof(buffer), "0x%02x", dReg->rIdx);
380 } else {
381 SNPRINTF(buffer, sizeof(buffer), "r0x%02x", dReg->rIdx);
382 }
383
384 if(type == REG_STK) {
385 *buffer = 's';
386 }
387 dReg->name = Safe_strdup(buffer);
388 }
389
390
391 dReg->isFree = 0;
392 dReg->wasUsed = 1;
393 dReg->isEmitted = 0;
394
395 if(type == REG_SFR) {
396 dReg->isFixed = 1;
397 dReg->address = rIdx;
398 dReg->accessBank = 1;
399 } else {
400 dReg->isFixed = 0;
401 dReg->address = 0;
402 dReg->accessBank = 0;
403 }
404
405 #if NEWREG_DEBUG
406 fprintf(stderr,"newReg @ %p: %s, rIdx = 0x%02x\taccess= %d\tregop= %p\n",dReg, dReg->name,rIdx, dReg->accessBank, refop);
407 #endif
408 dReg->size = size;
409 dReg->alias = alias;
410 dReg->reg_alias = NULL;
411 dReg->reglives.usedpFlows = newSet();
412 dReg->reglives.assignedpFlows = newSet();
413 dReg->regop = refop;
414
415 if(!(type == REG_SFR && alias == 0x80))
416 hTabAddItem(&dynDirectRegNames, regname2key(dReg->name), dReg);
417
418 return dReg;
419 }
420
421 /*-----------------------------------------------------------------*/
422 /* regWithIdx - Search through a set of registers that matches idx */
423 /*-----------------------------------------------------------------*/
424 static reg_info *
regWithIdx(set * dRegs,int idx,unsigned fixed)425 regWithIdx (set *dRegs, int idx, unsigned fixed)
426 {
427 reg_info *dReg;
428
429 //#define D(text) text
430 #define D(text)
431
432 for (dReg = setFirstItem(dRegs) ; dReg ;
433 dReg = setNextItem(dRegs)) {
434
435 D(fprintf(stderr, "%s:%d testing reg w/rIdx = %d (%d f:%d)\t", __FUNCTION__, __LINE__, dReg->rIdx, idx, fixed));
436 if(idx == dReg->rIdx && (fixed == dReg->isFixed)) {
437 D(fprintf(stderr, "found!\n"));
438 return dReg;
439 } else
440 D(fprintf(stderr, "not found!\n"));
441 }
442
443 return NULL;
444 }
445
446 /*-----------------------------------------------------------------*/
447 /* regFindFree - Search for a free register in a set of registers */
448 /*-----------------------------------------------------------------*/
449 static reg_info *
regFindFree(set * dRegs)450 regFindFree (set *dRegs)
451 {
452 reg_info *dReg;
453
454 for (dReg = setFirstItem(dRegs) ; dReg ;
455 dReg = setNextItem(dRegs)) {
456
457 // fprintf(stderr, "%s:%d checking register %s (%p) [rIdx: 0x%02x] if free= %d\n",
458 // __FILE__, __LINE__, dReg->name, dReg, dReg->rIdx, dReg->isFree);
459
460 if(dReg->isFree) {
461 // fprintf(stderr, "%s:%d free register found, rIdx = %d\n", __FILE__, __LINE__, dReg->rIdx);
462
463 return dReg;
464 }
465 }
466
467 return NULL;
468 }
469
470 static reg_info *
regFindFreeNext(set * dRegs,reg_info * creg)471 regFindFreeNext(set *dRegs, reg_info *creg)
472 {
473 reg_info *dReg;
474
475 if(creg) {
476 /* position at current register */
477 for(dReg = setFirstItem(dRegs); dReg != creg; dReg = setNextItem(dRegs));
478 }
479
480 for(dReg = setNextItem(dRegs); dReg; dReg = setNextItem(dRegs)) {
481 if(dReg->isFree) {
482 return dReg;
483 }
484 }
485
486 return NULL;
487 }
488
489 /*-----------------------------------------------------------------*
490 *-----------------------------------------------------------------*/
491 reg_info *
pic16_allocProcessorRegister(int rIdx,const char * name,short po_type,int alias)492 pic16_allocProcessorRegister(int rIdx, const char * name, short po_type, int alias)
493 {
494 reg_info *reg = newReg(REG_SFR, po_type, rIdx, name, 1, alias, NULL);
495
496 // fprintf(stderr,"%s: %s addr =0x%x\n",__FUNCTION__, name,rIdx);
497
498 reg->wasUsed = 0; // we do not know if they are going to be used at all
499 reg->accessBank = 1; // implicit add access Bank
500
501 hTabAddItem(&dynProcRegNames, regname2key(reg->name), reg);
502
503 return addSet(&pic16_dynProcessorRegs, reg);
504 }
505
506 /*-----------------------------------------------------------------*
507 *-----------------------------------------------------------------*/
508
509 reg_info *
pic16_allocInternalRegister(int rIdx,const char * name,short po_type,int alias)510 pic16_allocInternalRegister(int rIdx, const char *name, short po_type, int alias)
511 {
512 reg_info * reg = newReg(REG_GPR, po_type, rIdx, name, 1, alias, NULL);
513
514 // fprintf(stderr,"%s:%d: %s %s addr =0x%x\n",__FILE__, __LINE__, __FUNCTION__, name, rIdx);
515
516 if(reg) {
517 reg->wasUsed = 0;
518 return addSet(&pic16_dynInternalRegs, reg);
519 }
520
521 return NULL;
522 }
523
524
525 /*-----------------------------------------------------------------*/
526 /* allocReg - allocates register of given type */
527 /*-----------------------------------------------------------------*/
528 static reg_info *
allocReg(short type)529 allocReg (short type)
530 {
531 reg_info * reg=NULL;
532
533 #define MAX_P16_NREGS 16
534
535
536 #if 0
537 if(dynrIdx > pic16_nRegs)
538 werror(W_POSSBUG2, __FILE__, __LINE__);
539 return NULL;
540 #endif
541
542 /* try to reuse some unused registers */
543 reg = regFindFree( pic16_dynAllocRegs );
544
545 if(reg) {
546 // fprintf(stderr, "%s: [%s][cf:%p] found FREE register %s, rIdx: %d\n", __FILE__, (_inRegAllocator)?"ralloc":"", currFunc, reg->name, reg->rIdx);
547 }
548
549 if(!reg) {
550 reg = newReg(REG_GPR, PO_GPR_TEMP, dynrIdx++, NULL, 1, 0, NULL);
551 // fprintf(stderr, "%s [%s][cf:%p] allocating NEW register %s, rIdx: %d\n", __FILE__,
552 // (_inRegAllocator)?"ralloc":"", currFunc, reg->name, reg->rIdx);
553
554 #if 1
555 if(_inRegAllocator && (dynrIdx > MAX_P16_NREGS)) {
556 // debugf("allocating more registers than available\n", 0);
557 // return (NULL);
558 }
559
560 addSet(&pic16_dynAllocRegs, reg);
561 hTabAddItem(&dynAllocRegNames, regname2key(reg->name), reg);
562 // fprintf(stderr, "%s:%d added reg to pic16_dynAllocRegs = %p\n", __FUNCTION__, __LINE__, pic16_dynAllocRegs);
563 #endif
564 }
565
566 debugLog ("%s of type %s for register rIdx: %d (0x%x)\n", __FUNCTION__, debugLogRegType (type), dynrIdx-1, dynrIdx-1);
567
568 #if 0
569 fprintf(stderr,"%s:%d: %s\t%s addr= 0x%x\trIdx= 0x%02x isFree: %d\n",
570 __FILE__, __LINE__, __FUNCTION__, reg->name, reg->address, reg->rIdx, reg->isFree);
571 #endif
572 if(reg) {
573 reg->isFree=0;
574 reg->accessBank = 1; /* this is a temporary register alloc in accessBank */
575 reg->isLocal = 1; /* this is a local frame register */
576 // reg->wasUsed = 1;
577 }
578
579 if (currFunc) {
580 // fprintf(stderr, "%s:%d adding %s into function %s regsUsed\n", __FUNCTION__, __LINE__, reg->name, currFunc->name);
581 currFunc->regsUsed = bitVectSetBit (currFunc->regsUsed, reg->rIdx);
582 }
583
584 return (reg); // addSet(&pic16_dynAllocRegs,reg);
585
586 }
587
588
589 /*-----------------------------------------------------------------*/
590 /* pic16_dirregWithName - search for register by name */
591 /*-----------------------------------------------------------------*/
592 reg_info *
pic16_dirregWithName(const char * name)593 pic16_dirregWithName(const char *name)
594 {
595 int hkey;
596 reg_info *reg;
597
598 if(!name)
599 return NULL;
600
601 /* hash the name to get a key */
602
603 hkey = regname2key(name);
604
605 // fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
606
607 reg = hTabFirstItemWK(dynDirectRegNames, hkey);
608
609 while(reg) {
610
611 if(STRCASECMP(reg->name, name) == 0) {
612 // fprintf(stderr, "%s:%d: FOUND name = %s\thash = %d\n", __FUNCTION__, __LINE__, reg->name, hkey);
613 return(reg);
614 }
615
616 reg = hTabNextItemWK (dynDirectRegNames);
617
618 }
619
620 return NULL; // name wasn't found in the hash table
621 }
622
623 /*-----------------------------------------------------------------*/
624 /* pic16_allocregWithName - search for register by name */
625 /*-----------------------------------------------------------------*/
626 reg_info *
pic16_allocregWithName(const char * name)627 pic16_allocregWithName(const char *name)
628 {
629 int hkey;
630 reg_info *reg;
631
632 if(!name)
633 return NULL;
634
635 /* hash the name to get a key */
636
637 hkey = regname2key(name);
638
639 //fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
640
641 reg = hTabFirstItemWK(dynAllocRegNames, hkey);
642
643 while(reg) {
644
645 if(STRCASECMP(reg->name, name) == 0) {
646 return(reg);
647 }
648
649 reg = hTabNextItemWK (dynAllocRegNames);
650
651 }
652
653 return NULL; // name wasn't found in the hash table
654
655 }
656
657
658 /*-----------------------------------------------------------------*/
659 /* pic16_procregWithName - search for register by name */
660 /*-----------------------------------------------------------------*/
661 reg_info *
pic16_procregWithName(const char * name)662 pic16_procregWithName(const char *name)
663 {
664 int hkey;
665 reg_info *reg;
666
667 if(!name)
668 return NULL;
669
670 /* hash the name to get a key */
671
672 hkey = regname2key(name);
673
674 // fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
675
676 reg = hTabFirstItemWK(dynProcRegNames, hkey);
677
678 while(reg) {
679
680 if(STRCASECMP(reg->name, name) == 0) {
681 return(reg);
682 }
683
684 reg = hTabNextItemWK (dynProcRegNames);
685
686 }
687
688 return NULL; // name wasn't found in the hash table
689
690 }
691
692 /*-----------------------------------------------------------------*/
693 /* pic16_accessregWithName - search for register by name */
694 /*-----------------------------------------------------------------*/
695 reg_info *
pic16_accessregWithName(const char * name)696 pic16_accessregWithName(const char *name)
697 {
698 int hkey;
699 reg_info *reg;
700
701 if(!name)
702 return NULL;
703
704 /* hash the name to get a key */
705
706 hkey = regname2key(name);
707
708 // fprintf(stderr, "%s:%d: name = %s\thash = %d\n", __FUNCTION__, __LINE__, name, hkey);
709
710 reg = hTabFirstItemWK(dynAccessRegNames, hkey);
711
712 while(reg) {
713
714 if(STRCASECMP(reg->name, name) == 0) {
715 return(reg);
716 }
717
718 reg = hTabNextItemWK (dynAccessRegNames);
719
720 }
721
722 return NULL; // name wasn't found in the hash table
723
724 }
725
pic16_regWithName(const char * name)726 reg_info *pic16_regWithName(const char *name)
727 {
728 reg_info *reg;
729
730 reg = pic16_dirregWithName( name );
731 if(reg)return reg;
732
733 reg = pic16_procregWithName( name );
734 if(reg)return reg;
735
736 reg = pic16_allocregWithName( name );
737 if(reg)return reg;
738
739 reg = pic16_accessregWithName( name );
740 if(reg)return reg;
741
742 return NULL;
743 }
744
745
746 /*-----------------------------------------------------------------*/
747 /* pic16_allocDirReg - allocates register of given type */
748 /*-----------------------------------------------------------------*/
749 reg_info *
pic16_allocDirReg(operand * op)750 pic16_allocDirReg (operand *op )
751 {
752 reg_info *reg;
753 char *name;
754
755 if(!IS_SYMOP(op)) {
756 debugLog ("%s BAD, op is NULL\n", __FUNCTION__);
757 // fprintf(stderr, "%s BAD, op is NULL\n", __FUNCTION__);
758 return NULL;
759 }
760
761 name = OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name;
762
763
764 if(!SPEC_OCLS( OP_SYM_ETYPE(op))) {
765 #if 0
766 if(pic16_debug_verbose)
767 {
768 fprintf(stderr, "%s:%d symbol %s(r:%s) is not assigned to a memmap\n", __FILE__, __LINE__,
769 OP_SYMBOL(op)->name, OP_SYMBOL(op)->rname);
770 }
771 #endif
772 return NULL;
773 }
774
775 if(!IN_DIRSPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
776 || !IN_FARSPACE(SPEC_OCLS( OP_SYM_ETYPE(op))) ) {
777
778 #if 0
779 if(pic16_debug_verbose) {
780 fprintf(stderr, "dispace:%d farspace:%d codespace:%d regspace:%d stack:%d eeprom: %d regparm: %d isparm: %d\n",
781 IN_DIRSPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
782 IN_FARSPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
783 IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
784 IN_REGSP( SPEC_OCLS( OP_SYM_ETYPE(op))),
785 IN_STACK( OP_SYM_ETYPE(op)),
786 SPEC_OCLS(OP_SYM_ETYPE(op)) == eeprom,
787 IS_REGPARM(OP_SYM_ETYPE(op)),
788 IS_PARM(op));
789
790 fprintf(stderr, "%s:%d symbol %s NOT in dirspace\n", __FILE__, __LINE__,
791 OP_SYMBOL(op)->name);
792 }
793 #endif
794
795 }
796
797
798
799 if (IS_CODE ( OP_SYM_ETYPE(op)) ) {
800 // fprintf(stderr, "%s:%d sym: %s in codespace\n", __FUNCTION__, __LINE__, OP_SYMBOL(op)->name);
801 return NULL;
802 }
803
804 if(IS_ITEMP(op))return NULL;
805
806 // if(IS_STATIC(OP_SYM_ETYPE(op)))return NULL;
807
808 if(IN_STACK(OP_SYM_ETYPE(op)))return NULL;
809
810 debugLog ("%s:%d symbol name %s\n", __FUNCTION__, __LINE__, name);
811 // fprintf(stderr, "%s symbol name %s\tSTATIC:%d\n", __FUNCTION__,name, IS_STATIC(OP_SYM_ETYPE(op)));
812
813 {
814 if(SPEC_CONST ( OP_SYM_ETYPE(op)) && (IS_CHAR ( OP_SYM_ETYPE(op)) )) {
815 debugLog(" %d const char\n",__LINE__);
816 debugLog(" value = %s \n",SPEC_CVAL( OP_SYM_ETYPE(op)));
817 // fprintf(stderr, " %d const char\n",__LINE__);
818 // fprintf(stderr, " value = %s \n",SPEC_CVAL( OP_SYM_ETYPE(op)));
819 }
820
821
822 debugLog(" %d storage class %d \n",__LINE__,SPEC_SCLS( OP_SYM_ETYPE(op)));
823 if (IS_CODE ( OP_SYM_ETYPE(op)) )
824 debugLog(" %d code space\n",__LINE__);
825
826 if (IS_INTEGRAL ( OP_SYM_ETYPE(op)) )
827 debugLog(" %d integral\n",__LINE__);
828
829 if (IS_LITERAL ( OP_SYM_ETYPE(op)) )
830 debugLog(" %d literal\n",__LINE__);
831
832 if (IS_SPEC ( OP_SYM_ETYPE(op)) )
833 debugLog(" %d specifier\n",__LINE__);
834
835 debugAopGet(NULL, op);
836 }
837
838
839 reg = pic16_dirregWithName(name);
840
841 if(!reg) {
842 int regtype = REG_GPR;
843
844 /* if this is at an absolute address, then get the address. */
845 if (0 && SPEC_ABSA ( OP_SYM_ETYPE(op)) )
846 {
847 int address = 0;
848 address = SPEC_ADDR ( OP_SYM_ETYPE(op));
849 fprintf(stderr,"reg %s is at an absolute address: 0x%03x\n",name,address);
850 }
851
852 /* Register wasn't found in hash, so let's create
853 * a new one and put it in the hash table AND in the
854 * dynDirectRegNames set */
855 if(IS_CODE(OP_SYM_ETYPE(op)) || IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))) {
856 debugLog("%s:%d sym: %s in codespace\n", __FUNCTION__, __LINE__, OP_SYMBOL(op)->name);
857 return NULL;
858 }
859
860
861 #if 0
862 if(OP_SYMBOL(op)->onStack) {
863 fprintf(stderr, "%s:%d onStack %s offset: %d\n", __FILE__, __LINE__,
864 OP_SYMBOL(op)->name, OP_SYMBOL(op)->stack);
865 }
866 #endif
867
868 if(!IN_DIRSPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
869 || !IN_FARSPACE(SPEC_OCLS( OP_SYM_ETYPE(op))) ) {
870
871 #if 0
872 if(pic16_debug_verbose)
873 {
874 fprintf(stderr, "dispace:%d farspace:%d codespace:%d regspace:%d stack:%d eeprom: %d\n",
875 IN_DIRSPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
876 IN_FARSPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
877 IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op))),
878 IN_REGSP( SPEC_OCLS( OP_SYM_ETYPE(op))),
879 IN_STACK( OP_SYM_ETYPE(op)),
880 SPEC_OCLS(OP_SYM_ETYPE(op)) == eeprom);
881
882 fprintf(stderr, "%s:%d symbol %s NOT in dirspace\n", __FILE__, __LINE__,
883 OP_SYMBOL(op)->name);
884 }
885 #endif
886 }
887
888 reg = newReg(regtype, PO_DIR, rDirectIdx++, name,getSize (OP_SYMBOL (op)->type),0, op);
889 debugLog ("%d -- added %s to hash, size = %d\n", __LINE__, name,reg->size);
890
891 if( SPEC_SCLS( OP_SYM_ETYPE( op ) ) == S_REGISTER ) {
892 fprintf(stderr, "%s:%d symbol %s is declared as register\n", __FILE__, __LINE__,
893 name);
894
895 reg->accessBank = 1;
896 checkAddReg(&pic16_dynAccessRegs, reg);
897 hTabAddItem(&dynAccessRegNames, regname2key(name), reg);
898
899 return (reg);
900 }
901
902
903 // if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
904 // fprintf(stderr, " ralloc.c at fixed address: %s - changing to REG_SFR\n",name);
905 // reg->type = REG_SFR;
906 // }
907
908 if (IS_BITVAR (OP_SYM_ETYPE(op))) {
909 // fprintf(stderr, "%s:%d adding %s in bit registers\n", __FILE__, __LINE__, reg->name);
910 addSet(&pic16_dynDirectBitRegs, reg);
911 reg->isBitField = 1;
912 } else {
913 // fprintf(stderr, "%s:%d adding %s in direct registers\n", __FILE__, __LINE__, reg->name);
914 // addSet(&pic16_dynDirectRegs, reg);
915
916 #if 1
917 if(!(IS_STATIC(OP_SYM_ETYPE(op))
918 && OP_SYMBOL(op)->ival
919 ))
920 #endif
921 checkAddReg(&pic16_dynDirectRegs, reg);
922 }
923
924 } else {
925 // debugLog (" -- %s is declared at address 0x30000x\n",name);
926 return (reg); /* This was NULL before, but since we found it
927 * why not just return it?! */
928 }
929
930 if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
931 reg->isFixed = 1;
932 reg->address = SPEC_ADDR ( OP_SYM_ETYPE(op));
933
934 /* work around for user defined registers in access bank */
935 if((reg->address>= 0x00 && reg->address < pic16->acsSplitOfs)
936 || (reg->address >= (0xf00 + pic16->acsSplitOfs) && reg->address <= 0xfff))
937 reg->accessBank = 1;
938
939 debugLog (" -- and it is at a fixed address 0x%02x\n",reg->address);
940 }
941
942 return reg;
943 }
944
945 /*-----------------------------------------------------------------*/
946 /* pic16_allocRegByName - allocates register of given type */
947 /*-----------------------------------------------------------------*/
948 reg_info *
pic16_allocRegByName(const char * name,int size,operand * op)949 pic16_allocRegByName(const char *name, int size, operand *op)
950 {
951
952 reg_info *reg;
953
954 if(!name) {
955 fprintf(stderr, "%s - allocating a NULL register\n",__FUNCTION__);
956 exit(1);
957 }
958
959 /* First, search the hash table to see if there is a register with this name */
960 reg = pic16_dirregWithName(name);
961
962 if(!reg) {
963
964 /* Register wasn't found in hash, so let's create
965 * a new one and put it in the hash table AND in the
966 * dynDirectRegNames set */
967
968 //fprintf (stderr,"%s:%d symbol name %s\tregop= %p\n", __FUNCTION__, __LINE__, name, op);
969
970 reg = newReg(REG_GPR, PO_DIR, rDirectIdx++, name,size,0, op);
971
972 debugLog ("%d -- added %s to hash, size = %d\n", __LINE__, name,reg->size);
973 //fprintf(stderr, " -- added %s to hash, size = %d\n", name,reg->size);
974
975 //hTabAddItem(&dynDirectRegNames, regname2key(name), reg); /* initially commented out */
976 addSet(&pic16_dynDirectRegs, reg);
977 }
978
979 return reg;
980 }
981
982 /*-----------------------------------------------------------------*/
983 /* RegWithIdx - returns pointer to register with index number */
984 /*-----------------------------------------------------------------*/
pic16_typeRegWithIdx(int idx,int type,int fixed)985 reg_info *pic16_typeRegWithIdx (int idx, int type, int fixed)
986 {
987
988 reg_info *dReg;
989
990 debugLog ("%s - requesting index = 0x%x\n", __FUNCTION__,idx);
991 // fprintf(stderr, "%s - requesting index = 0x%x (type = %d [%s])\n", __FUNCTION__, idx, type, decodeRegType(type));
992
993 switch (type) {
994
995 case REG_GPR:
996 if( (dReg = regWithIdx ( pic16_dynAllocRegs, idx, fixed)) != NULL) {
997
998 debugLog ("Found a Dynamic Register!\n");
999 return dReg;
1000 }
1001 if( (dReg = regWithIdx ( pic16_dynDirectRegs, idx, fixed)) != NULL ) {
1002 debugLog ("Found a Direct Register!\n");
1003 return dReg;
1004 }
1005
1006 if( (dReg = regWithIdx ( pic16_dynInternalRegs, idx, fixed)) != NULL ) {
1007 debugLog ("Found an Internal Register!\n");
1008 return dReg;
1009 }
1010
1011 break;
1012 case REG_STK:
1013 if( (dReg = regWithIdx ( pic16_dynStackRegs, idx, fixed)) != NULL ) {
1014 debugLog ("Found a Stack Register!\n");
1015 return dReg;
1016 }
1017 break;
1018 case REG_SFR:
1019 if( (dReg = regWithIdx ( pic16_dynProcessorRegs, idx, 1)) != NULL ) {
1020 debugLog ("Found a Processor Register!\n");
1021 return dReg;
1022 }
1023
1024 case REG_CND:
1025 case REG_PTR:
1026 default:
1027 break;
1028 }
1029
1030
1031 return NULL;
1032 }
1033
1034 /*-----------------------------------------------------------------*/
1035 /* pic16_regWithIdx - returns pointer to register with index number*/
1036 /*-----------------------------------------------------------------*/
1037 reg_info *
pic16_regWithIdx(int idx)1038 pic16_regWithIdx (int idx)
1039 {
1040 reg_info *dReg;
1041
1042 if( (dReg = pic16_typeRegWithIdx(idx,REG_GPR,0)) != NULL)
1043 return dReg;
1044
1045 if( (dReg = pic16_typeRegWithIdx(idx,REG_SFR,0)) != NULL)
1046 return dReg;
1047
1048 #if 0
1049 if( (dReg = pic16_typeRegWithIdx(idx,REG_STK,0)) != NULL)
1050 return dReg;
1051 #endif
1052
1053 return NULL;
1054 }
1055
1056 /*-----------------------------------------------------------------*/
1057 /* pic16_regWithIdx - returns pointer to register with index number */
1058 /*-----------------------------------------------------------------*/
1059 reg_info *
pic16_allocWithIdx(int idx)1060 pic16_allocWithIdx (int idx)
1061 {
1062
1063 reg_info *dReg=NULL;
1064
1065 debugLog ("%s - allocating with index = 0x%x\n", __FUNCTION__,idx);
1066 // fprintf(stderr, "%s - allocating with index = 0x%x\n", __FUNCTION__,idx);
1067
1068 if( (dReg = regWithIdx ( pic16_dynAllocRegs, idx,0)) != NULL) {
1069
1070 debugLog ("Found a Dynamic Register!\n");
1071 } else if( (dReg = regWithIdx ( pic16_dynStackRegs, idx,0)) != NULL ) {
1072 debugLog ("Found a Stack Register!\n");
1073 } else if( (dReg = regWithIdx ( pic16_dynProcessorRegs, idx,1)) != NULL ) {
1074 debugLog ("Found a Processor Register!\n");
1075 fprintf(stderr, "Found a processor register! %s\n", dReg->name);
1076 } else if( (dReg = regWithIdx ( pic16_dynInternalRegs, idx,0)) != NULL ) {
1077 debugLog ("Found an Internal Register!\n");
1078 } else {
1079
1080 debugLog ("Dynamic Register not found\n");
1081
1082 #if 1
1083 dReg = newReg(REG_GPR, PO_GPR_TEMP, idx, NULL, 1, 0, NULL);
1084 addSet(&pic16_dynAllocRegs, dReg);
1085 hTabAddItem(&dynAllocRegNames, regname2key(dReg->name), dReg);
1086 #endif
1087
1088 if(!dReg) {
1089 // return (NULL);
1090 //fprintf(stderr,"%s %d - requested register: 0x%x\n",__FUNCTION__,__LINE__,idx);
1091 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1092 "allocWithIdx not found");
1093 exit (1);
1094 }
1095 }
1096
1097 dReg->wasUsed = 1;
1098 dReg->isFree = 0;
1099
1100 return dReg;
1101 }
1102 /*-----------------------------------------------------------------*/
1103 /*-----------------------------------------------------------------*/
1104 reg_info *
pic16_findFreeReg(short type)1105 pic16_findFreeReg(short type)
1106 {
1107 // int i;
1108 reg_info* dReg;
1109
1110 switch (type) {
1111 case REG_GPR:
1112 if((dReg = regFindFree(pic16_dynAllocRegs)) != NULL)
1113 return dReg;
1114 // return (addSet(&pic16_dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0, NULL)));
1115 return allocReg( REG_GPR );
1116
1117 case REG_STK:
1118
1119 if((dReg = regFindFree(pic16_dynStackRegs)) != NULL)
1120 return dReg;
1121
1122 return NULL;
1123
1124 case REG_PTR:
1125 case REG_CND:
1126 case REG_SFR:
1127 default:
1128 return NULL;
1129 }
1130 }
1131
1132 reg_info *
pic16_findFreeRegNext(short type,reg_info * creg)1133 pic16_findFreeRegNext(short type, reg_info *creg)
1134 {
1135 // int i;
1136 reg_info* dReg;
1137
1138 switch (type) {
1139 case REG_GPR:
1140 if((dReg = regFindFreeNext(pic16_dynAllocRegs, creg)) != NULL)
1141 return dReg;
1142 // return (addSet(&pic16_dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0, NULL)));
1143 return (allocReg( REG_GPR ) );
1144
1145 case REG_STK:
1146
1147 if((dReg = regFindFreeNext(pic16_dynStackRegs, creg)) != NULL)
1148 return dReg;
1149
1150 return NULL;
1151
1152 case REG_PTR:
1153 case REG_CND:
1154 case REG_SFR:
1155 default:
1156 return NULL;
1157 }
1158 }
1159 /*-----------------------------------------------------------------*/
1160 /* freeReg - frees a register */
1161 /*-----------------------------------------------------------------*/
1162 static void
freeReg(reg_info * reg)1163 freeReg (reg_info * reg)
1164 {
1165 debugLog ("%s\n", __FUNCTION__);
1166 // fprintf(stderr, "%s:%d register %s (%p) is freed\n", __FILE__, __LINE__, reg->name, reg);
1167 reg->isFree = 1;
1168 }
1169
1170
1171 /*-----------------------------------------------------------------*/
1172 /* nFreeRegs - returns number of free registers */
1173 /*-----------------------------------------------------------------*/
1174 static int
nFreeRegs(int type)1175 nFreeRegs (int type)
1176 {
1177 reg_info *reg;
1178 int nfr=0;
1179
1180
1181 /* although I fixed the register allocation/freeing scheme
1182 * the for loop below doesn't give valid results. I do not
1183 * know why yet. -- VR 10-Jan-2003 */
1184
1185 return 100;
1186
1187
1188 /* dynamically allocate as many as we need and worry about
1189 * fitting them into a PIC later */
1190
1191 debugLog ("%s\n", __FUNCTION__);
1192
1193 for(reg = setFirstItem(pic16_dynAllocRegs); reg; reg=setNextItem(pic16_dynAllocRegs))
1194 if((reg->type == type) && reg->isFree)nfr++;
1195
1196 fprintf(stderr, "%s:%d # of free registers= %d\n", __FILE__, __LINE__, nfr);
1197 return nfr;
1198 }
1199
1200 /*-----------------------------------------------------------------*/
1201 /* nfreeRegsType - free registers with type */
1202 /*-----------------------------------------------------------------*/
1203 static int
nfreeRegsType(int type)1204 nfreeRegsType (int type)
1205 {
1206 int nfr;
1207 debugLog ("%s\n", __FUNCTION__);
1208 if (type == REG_PTR)
1209 {
1210 if ((nfr = nFreeRegs (type)) == 0)
1211 return nFreeRegs (REG_GPR);
1212 }
1213
1214 return nFreeRegs (type);
1215 }
1216 #if 0
1217 static void writeSetUsedRegs(FILE *of, set *dRegs)
1218 {
1219
1220 reg_info *dReg;
1221
1222 for (dReg = setFirstItem(dRegs) ; dReg ;
1223 dReg = setNextItem(dRegs)) {
1224
1225 if(dReg->wasUsed)
1226 fprintf (of, "\t%s\n",dReg->name);
1227 }
1228
1229 }
1230 #endif
1231
1232 extern void pic16_groupRegistersInSection(set *regset);
1233
1234 extern void pic16_dump_equates(FILE *of, set *equs);
1235 extern void pic16_dump_access(FILE *of, set *section);
1236 //extern void pic16_dump_map(void);
1237 extern void pic16_dump_usection(FILE *of, set *section, int fix);
1238 extern void pic16_dump_isection(FILE *of, set *section, int fix);
1239 extern void pic16_dump_int_registers(FILE *of, set *section);
1240 extern void pic16_dump_idata(FILE *of, set *idataSymSet);
1241
1242 extern void pic16_dump_gsection(FILE *of, set *sections);
1243
packBits(set * bregs)1244 static void packBits(set *bregs)
1245 {
1246 set *regset;
1247 reg_info *breg;
1248 reg_info *bitfield=NULL;
1249 reg_info *relocbitfield=NULL;
1250 int bit_no=0;
1251 int byte_no=-1;
1252 char buffer[20];
1253
1254
1255 for (regset = bregs ; regset ;
1256 regset = regset->next) {
1257
1258 breg = regset->item;
1259 breg->isBitField = 1;
1260 //fprintf(stderr,"bit reg: %s\n",breg->name);
1261
1262 if(breg->isFixed) {
1263 //fprintf(stderr,"packing bit at fixed address = 0x%03x\n",breg->address);
1264
1265 bitfield = pic16_typeRegWithIdx (breg->address >> 3, -1 , 1);
1266 breg->rIdx = breg->address & 7;
1267 breg->address >>= 3;
1268
1269 if(!bitfield) {
1270 SNPRINTF(buffer, sizeof(buffer), "fbitfield%02x", breg->address);
1271 //fprintf(stderr,"new bit field\n");
1272 bitfield = newReg(REG_SFR, PO_GPR_BIT,breg->address,buffer,1,0, NULL);
1273 bitfield->isBitField = 1;
1274 bitfield->isFixed = 1;
1275 bitfield->address = breg->address;
1276 addSet(&pic16_dynDirectRegs,bitfield);
1277 //hTabAddItem(&dynDirectRegNames, regname2key(buffer), bitfield);
1278 } else {
1279 //fprintf(stderr," which is occupied by %s (addr = %d)\n",bitfield->name,bitfield->address);
1280 ;
1281 }
1282 breg->reg_alias = bitfield;
1283 bitfield = NULL;
1284
1285 } else {
1286 if(!relocbitfield || bit_no >7) {
1287 byte_no++;
1288 bit_no=0;
1289 SNPRINTF(buffer, sizeof(buffer), "bitfield%d", byte_no);
1290 //fprintf(stderr,"new relocatable bit field\n");
1291 relocbitfield = newReg(REG_GPR, PO_GPR_BIT,rDirectIdx++,buffer,1,0, NULL);
1292 relocbitfield->isBitField = 1;
1293 addSet(&pic16_dynDirectRegs,relocbitfield);
1294 //hTabAddItem(&dynDirectRegNames, regname2key(buffer), relocbitfield);
1295
1296 }
1297
1298 breg->reg_alias = relocbitfield;
1299 breg->address = rDirectIdx; /* byte_no; */
1300 breg->rIdx = bit_no++;
1301 }
1302 }
1303
1304 }
1305
pic16_writeUsedRegs(FILE * of)1306 void pic16_writeUsedRegs(FILE *of)
1307 {
1308 packBits(pic16_dynDirectBitRegs);
1309
1310 pic16_groupRegistersInSection(pic16_dynAllocRegs);
1311 pic16_groupRegistersInSection(pic16_dynInternalRegs);
1312 pic16_groupRegistersInSection(pic16_dynStackRegs);
1313 pic16_groupRegistersInSection(pic16_dynDirectRegs);
1314 pic16_groupRegistersInSection(pic16_dynDirectBitRegs);
1315 pic16_groupRegistersInSection(pic16_dynProcessorRegs);
1316 pic16_groupRegistersInSection(pic16_dynAccessRegs);
1317
1318 /* dump equates */
1319 pic16_dump_equates(of, pic16_equ_data);
1320
1321 // pic16_dump_esection(of, pic16_rel_eedata, 0);
1322 // pic16_dump_esection(of, pic16_fix_eedata, 0);
1323
1324 /* dump access bank symbols */
1325 pic16_dump_access(of, pic16_acs_udata);
1326
1327 /* dump initialised data */
1328 pic16_dump_isection(of, rel_idataSymSet, 0);
1329 pic16_dump_isection(of, fix_idataSymSet, 1);
1330
1331 if(!pic16_options.xinst) {
1332 /* dump internal registers */
1333 pic16_dump_int_registers(of, pic16_int_regs);
1334 }
1335
1336 /* dump generic section variables */
1337 pic16_dump_gsection(of, sectNames);
1338
1339 /* dump other variables */
1340 pic16_dump_usection(of, pic16_rel_udata, 0);
1341 pic16_dump_usection(of, pic16_fix_udata, 1);
1342 }
1343
1344
1345 /*-----------------------------------------------------------------*/
1346 /* computeSpillable - given a point find the spillable live ranges */
1347 /*-----------------------------------------------------------------*/
1348 static bitVect *
computeSpillable(iCode * ic)1349 computeSpillable (iCode * ic)
1350 {
1351 bitVect *spillable;
1352
1353 debugLog ("%s\n", __FUNCTION__);
1354 /* spillable live ranges are those that are live at this
1355 point . the following categories need to be subtracted
1356 from this set.
1357 a) - those that are already spilt
1358 b) - if being used by this one
1359 c) - defined by this one */
1360
1361 spillable = bitVectCopy (ic->rlive);
1362 spillable =
1363 bitVectCplAnd (spillable, _G.spiltSet); /* those already spilt */
1364 spillable =
1365 bitVectCplAnd (spillable, ic->uses); /* used in this one */
1366 bitVectUnSetBit (spillable, ic->defKey);
1367 spillable = bitVectIntersect (spillable, _G.regAssigned);
1368 return spillable;
1369
1370 }
1371
1372 /*-----------------------------------------------------------------*/
1373 /* noSpilLoc - return true if a variable has no spil location */
1374 /*-----------------------------------------------------------------*/
1375 static int
noSpilLoc(symbol * sym,eBBlock * ebp,iCode * ic)1376 noSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
1377 {
1378 debugLog ("%s\n", __FUNCTION__);
1379 return (SYM_SPIL_LOC (sym) ? 0 : 1);
1380 }
1381
1382 /*-----------------------------------------------------------------*/
1383 /* hasSpilLoc - will return 1 if the symbol has spil location */
1384 /*-----------------------------------------------------------------*/
1385 static int
hasSpilLoc(symbol * sym,eBBlock * ebp,iCode * ic)1386 hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
1387 {
1388 debugLog ("%s\n", __FUNCTION__);
1389 return (SYM_SPIL_LOC (sym) ? 1 : 0);
1390 }
1391
1392 /*-----------------------------------------------------------------*/
1393 /* directSpilLoc - will return 1 if the splilocation is in direct */
1394 /*-----------------------------------------------------------------*/
1395 static int
directSpilLoc(symbol * sym,eBBlock * ebp,iCode * ic)1396 directSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
1397 {
1398 debugLog ("%s\n", __FUNCTION__);
1399 if (SYM_SPIL_LOC (sym) &&
1400 (IN_DIRSPACE (SPEC_OCLS (SYM_SPIL_LOC (sym)->etype))))
1401 return 1;
1402 else
1403 return 0;
1404 }
1405
1406 /*-----------------------------------------------------------------*/
1407 /* hasSpilLocnoUptr - will return 1 if the symbol has spil location */
1408 /* but is not used as a pointer */
1409 /*-----------------------------------------------------------------*/
1410 static int
hasSpilLocnoUptr(symbol * sym,eBBlock * ebp,iCode * ic)1411 hasSpilLocnoUptr (symbol * sym, eBBlock * ebp, iCode * ic)
1412 {
1413 debugLog ("%s\n", __FUNCTION__);
1414 return ((SYM_SPIL_LOC (sym) && !sym->uptr) ? 1 : 0);
1415 }
1416
1417 /*-----------------------------------------------------------------*/
1418 /* rematable - will return 1 if the remat flag is set */
1419 /*-----------------------------------------------------------------*/
1420 static int
rematable(symbol * sym,eBBlock * ebp,iCode * ic)1421 rematable (symbol * sym, eBBlock * ebp, iCode * ic)
1422 {
1423 debugLog ("%s\n", __FUNCTION__);
1424 return sym->remat;
1425 }
1426
1427 /*-----------------------------------------------------------------*/
1428 /* notUsedInRemaining - not used or defined in remain of the block */
1429 /*-----------------------------------------------------------------*/
1430 static int
notUsedInRemaining(symbol * sym,eBBlock * ebp,iCode * ic)1431 notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
1432 {
1433 debugLog ("%s\n", __FUNCTION__);
1434 return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
1435 allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
1436 }
1437
1438 /*-----------------------------------------------------------------*/
1439 /* allLRs - return true for all */
1440 /*-----------------------------------------------------------------*/
1441 static int
allLRs(symbol * sym,eBBlock * ebp,iCode * ic)1442 allLRs (symbol * sym, eBBlock * ebp, iCode * ic)
1443 {
1444 debugLog ("%s\n", __FUNCTION__);
1445 return 1;
1446 }
1447
1448 /*-----------------------------------------------------------------*/
1449 /* liveRangesWith - applies function to a given set of live range */
1450 /*-----------------------------------------------------------------*/
1451 static set *
liveRangesWith(bitVect * lrs,int (func)(symbol *,eBBlock *,iCode *),eBBlock * ebp,iCode * ic)1452 liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
1453 eBBlock * ebp, iCode * ic)
1454 {
1455 set *rset = NULL;
1456 int i;
1457
1458 debugLog ("%s\n", __FUNCTION__);
1459 if (!lrs || !lrs->size)
1460 return NULL;
1461
1462 for (i = 1; i < lrs->size; i++)
1463 {
1464 symbol *sym;
1465 if (!bitVectBitValue (lrs, i))
1466 continue;
1467
1468 /* if we don't find it in the live range
1469 hash table we are in serious trouble */
1470 if (!(sym = hTabItemWithKey (liveRanges, i)))
1471 {
1472 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1473 "liveRangesWith could not find liveRange");
1474 exit (1);
1475 }
1476
1477 if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
1478 addSetHead (&rset, sym);
1479 }
1480
1481 return rset;
1482 }
1483
1484
1485 /*-----------------------------------------------------------------*/
1486 /* leastUsedLR - given a set determines which is the least used */
1487 /*-----------------------------------------------------------------*/
1488 static symbol *
leastUsedLR(set * sset)1489 leastUsedLR (set * sset)
1490 {
1491 symbol *sym = NULL, *lsym = NULL;
1492
1493 debugLog ("%s\n", __FUNCTION__);
1494 sym = lsym = setFirstItem (sset);
1495
1496 if (!lsym)
1497 return NULL;
1498
1499 for (; lsym; lsym = setNextItem (sset))
1500 {
1501
1502 /* if usage is the same then prefer
1503 the spill the smaller of the two */
1504 if (lsym->used == sym->used)
1505 if (getSize (lsym->type) < getSize (sym->type))
1506 sym = lsym;
1507
1508 /* if less usage */
1509 if (lsym->used < sym->used)
1510 sym = lsym;
1511
1512 }
1513
1514 setToNull ((void *) &sset);
1515 sym->blockSpil = 0;
1516 return sym;
1517 }
1518
1519 /*-----------------------------------------------------------------*/
1520 /* noOverLap - will iterate through the list looking for over lap */
1521 /*-----------------------------------------------------------------*/
1522 static int
noOverLap(set * itmpStack,symbol * fsym)1523 noOverLap (set * itmpStack, symbol * fsym)
1524 {
1525 symbol *sym;
1526 debugLog ("%s\n", __FUNCTION__);
1527
1528
1529 for (sym = setFirstItem (itmpStack); sym;
1530 sym = setNextItem (itmpStack))
1531 {
1532 if (sym->liveTo > fsym->liveFrom)
1533 return 0;
1534
1535 }
1536
1537 return 1;
1538 }
1539
1540 /*-----------------------------------------------------------------*/
1541 /* isFree - will return 1 if the a free spil location is found */
1542 /*-----------------------------------------------------------------*/
1543 static
DEFSETFUNC(isFree)1544 DEFSETFUNC (isFree)
1545 {
1546 symbol *sym = item;
1547 V_ARG (symbol **, sloc);
1548 V_ARG (symbol *, fsym);
1549
1550 debugLog ("%s\n", __FUNCTION__);
1551 /* if already found */
1552 if (*sloc)
1553 return 0;
1554
1555 /* if it is free && and the itmp assigned to
1556 this does not have any overlapping live ranges
1557 with the one currently being assigned and
1558 the size can be accomodated */
1559 if (sym->isFree &&
1560 noOverLap (sym->usl.itmpStack, fsym) &&
1561 getSize (sym->type) >= getSize (fsym->type))
1562 {
1563 *sloc = sym;
1564 return 1;
1565 }
1566
1567 return 0;
1568 }
1569
1570 /*-----------------------------------------------------------------*/
1571 /* spillLRWithPtrReg :- will spil those live ranges which use PTR */
1572 /*-----------------------------------------------------------------*/
1573 static void
spillLRWithPtrReg(symbol * forSym)1574 spillLRWithPtrReg (symbol * forSym)
1575 {
1576 symbol *lrsym;
1577 reg_info *r0, *r1;
1578 int k;
1579
1580 debugLog ("%s\n", __FUNCTION__);
1581 if (!_G.regAssigned ||
1582 bitVectIsZero (_G.regAssigned))
1583 return;
1584
1585 r0 = pic16_regWithIdx (R0_IDX);
1586 r1 = pic16_regWithIdx (R1_IDX);
1587
1588 /* for all live ranges */
1589 for (lrsym = hTabFirstItem (liveRanges, &k); lrsym;
1590 lrsym = hTabNextItem (liveRanges, &k))
1591 {
1592 int j;
1593
1594 /* if no registers assigned to it or
1595 spilt */
1596 /* if it does not overlap with this then
1597 not need to spill it */
1598
1599 if (lrsym->isspilt || !lrsym->nRegs ||
1600 (lrsym->liveTo < forSym->liveFrom))
1601 continue;
1602
1603 /* go thru the registers : if it is either
1604 r0 or r1 then spil it */
1605 for (j = 0; j < lrsym->nRegs; j++)
1606 if (lrsym->regs[j] == r0 ||
1607 lrsym->regs[j] == r1)
1608 {
1609 spillThis (lrsym);
1610 break;
1611 }
1612 }
1613
1614 }
1615
1616 /*-----------------------------------------------------------------*/
1617 /* createStackSpil - create a location on the stack to spil */
1618 /*-----------------------------------------------------------------*/
1619 static symbol *
createStackSpil(symbol * sym)1620 createStackSpil (symbol * sym)
1621 {
1622 symbol *sloc = NULL;
1623 int useXstack, model, noOverlay;
1624 char slocBuffer[120];
1625
1626 debugLog ("%s\n", __FUNCTION__);
1627
1628 /* first go try and find a free one that is already
1629 existing on the stack */
1630 if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
1631 {
1632 /* found a free one : just update & return */
1633 SYM_SPIL_LOC (sym) = sloc;
1634 sym->stackSpil = 1;
1635 sloc->isFree = 0;
1636 addSetHead (&sloc->usl.itmpStack, sym);
1637 return sym;
1638 }
1639
1640 SNPRINTF(slocBuffer, sizeof(slocBuffer), "sloc%d", _G.slocNum++);
1641 sloc = newiTemp(slocBuffer);
1642
1643 /* set the type to the spilling symbol */
1644 sloc->type = copyLinkChain (sym->type);
1645 sloc->etype = getSpec (sloc->type);
1646 SPEC_SCLS (sloc->etype) = S_DATA;
1647 SPEC_EXTR (sloc->etype) = 0;
1648 SPEC_STAT (sloc->etype) = 0;
1649
1650 /* we don't allow it to be allocated`
1651 onto the external stack since : so we
1652 temporarily turn it off ; we also
1653 turn off memory model to prevent
1654 the spil from going to the external storage
1655 and turn off overlaying
1656 */
1657
1658 useXstack = options.useXstack;
1659 model = options.model;
1660 noOverlay = options.noOverlay;
1661 options.noOverlay = 1;
1662 options.model = options.useXstack = 0;
1663
1664 allocLocal (sloc);
1665
1666 options.useXstack = useXstack;
1667 options.model = model;
1668 options.noOverlay = noOverlay;
1669 sloc->isref = 1; /* to prevent compiler warning */
1670
1671 /* if it is on the stack then update the stack */
1672 if (IN_STACK (sloc->etype))
1673 {
1674 currFunc->stack += getSize (sloc->type);
1675 _G.stackExtend += getSize (sloc->type);
1676 }
1677 else
1678 _G.dataExtend += getSize (sloc->type);
1679
1680 /* add it to the _G.stackSpil set */
1681 addSetHead (&_G.stackSpil, sloc);
1682 SYM_SPIL_LOC (sym) = sloc;
1683 sym->stackSpil = 1;
1684
1685 /* add it to the set of itempStack set
1686 of the spill location */
1687 addSetHead (&sloc->usl.itmpStack, sym);
1688 return sym;
1689 }
1690
1691 /*-----------------------------------------------------------------*/
1692 /* isSpiltOnStack - returns true if the spil location is on stack */
1693 /*-----------------------------------------------------------------*/
1694 static bool
isSpiltOnStack(symbol * sym)1695 isSpiltOnStack (symbol * sym)
1696 {
1697 sym_link *etype;
1698
1699 debugLog ("%s\n", __FUNCTION__);
1700 if (!sym)
1701 return FALSE;
1702
1703 if (!sym->isspilt)
1704 return FALSE;
1705
1706 /* if (sym->_G.stackSpil) */
1707 /* return TRUE; */
1708
1709 if (!SYM_SPIL_LOC (sym))
1710 return FALSE;
1711
1712 etype = getSpec (SYM_SPIL_LOC (sym)->type);
1713 if (IN_STACK (etype))
1714 return TRUE;
1715
1716 return FALSE;
1717 }
1718
1719 /*-----------------------------------------------------------------*/
1720 /* spillThis - spils a specific operand */
1721 /*-----------------------------------------------------------------*/
1722 static void
spillThis(symbol * sym)1723 spillThis (symbol * sym)
1724 {
1725 int i;
1726 debugLog ("%s : %s\n", __FUNCTION__, sym->rname);
1727
1728 /* if this is rematerializable or has a spillLocation
1729 we are okay, else we need to create a spillLocation
1730 for it */
1731 if (!(sym->remat || SYM_SPIL_LOC (sym)))
1732 createStackSpil (sym);
1733
1734
1735 /* mark it has spilt & put it in the spilt set */
1736 sym->isspilt = 1;
1737 _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
1738
1739 bitVectUnSetBit (_G.regAssigned, sym->key);
1740
1741 for (i = 0; i < sym->nRegs; i++)
1742
1743 if (sym->regs[i])
1744 {
1745 freeReg (sym->regs[i]);
1746 sym->regs[i] = NULL;
1747 }
1748
1749 /* if spilt on stack then free up r0 & r1
1750 if they could have been assigned to some
1751 LIVE ranges */
1752 if (!pic16_ptrRegReq && isSpiltOnStack (sym))
1753 {
1754 pic16_ptrRegReq++;
1755 spillLRWithPtrReg (sym);
1756 }
1757
1758 if (SYM_SPIL_LOC (sym) && !sym->remat)
1759 SYM_SPIL_LOC (sym)->allocreq = 1;
1760 return;
1761 }
1762
1763 /*-----------------------------------------------------------------*/
1764 /* selectSpil - select a iTemp to spil : rather a simple procedure */
1765 /*-----------------------------------------------------------------*/
1766 static symbol *
selectSpil(iCode * ic,eBBlock * ebp,symbol * forSym)1767 selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
1768 {
1769 bitVect *lrcs = NULL;
1770 set *selectS;
1771 symbol *sym;
1772
1773 debugLog ("%s\n", __FUNCTION__);
1774 /* get the spillable live ranges */
1775 lrcs = computeSpillable (ic);
1776
1777 /* get all live ranges that are rematerizable */
1778 if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
1779 {
1780
1781 /* return the least used of these */
1782 return leastUsedLR (selectS);
1783 }
1784
1785 /* get live ranges with spillLocations in direct space */
1786 if ((selectS = liveRangesWith (lrcs, directSpilLoc, ebp, ic)))
1787 {
1788 sym = leastUsedLR (selectS);
1789 strcpy (sym->rname, (SYM_SPIL_LOC (sym)->rname[0] ?
1790 SYM_SPIL_LOC (sym)->rname :
1791 SYM_SPIL_LOC (sym)->name));
1792 sym->spildir = 1;
1793 /* mark it as allocation required */
1794 SYM_SPIL_LOC (sym)->allocreq = 1;
1795 return sym;
1796 }
1797
1798 /* if the symbol is local to the block then */
1799 if (forSym->liveTo < ebp->lSeq)
1800 {
1801
1802 /* check if there are any live ranges allocated
1803 to registers that are not used in this block */
1804 if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
1805 {
1806 sym = leastUsedLR (selectS);
1807 /* if this is not rematerializable */
1808 if (!sym->remat)
1809 {
1810 _G.blockSpil++;
1811 sym->blockSpil = 1;
1812 }
1813 return sym;
1814 }
1815
1816 /* check if there are any live ranges that not
1817 used in the remainder of the block */
1818 if (!_G.blockSpil &&
1819 !isiCodeInFunctionCall (ic) &&
1820 (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
1821 {
1822 sym = leastUsedLR (selectS);
1823 if (!sym->remat)
1824 {
1825 sym->remainSpil = 1;
1826 _G.blockSpil++;
1827 }
1828 return sym;
1829 }
1830 }
1831
1832 /* find live ranges with spillocation && not used as pointers */
1833 if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
1834 {
1835
1836 sym = leastUsedLR (selectS);
1837 /* mark this as allocation required */
1838 SYM_SPIL_LOC (sym)->allocreq = 1;
1839 return sym;
1840 }
1841
1842 /* find live ranges with spillocation */
1843 if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
1844 {
1845
1846 sym = leastUsedLR (selectS);
1847 SYM_SPIL_LOC (sym)->allocreq = 1;
1848 return sym;
1849 }
1850
1851 /* couldn't find then we need to create a spil
1852 location on the stack , for which one? the least
1853 used ofcourse */
1854 if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
1855 {
1856
1857 /* return a created spil location */
1858 sym = createStackSpil (leastUsedLR (selectS));
1859 SYM_SPIL_LOC (sym)->allocreq = 1;
1860 return sym;
1861 }
1862
1863 /* this is an extreme situation we will spill
1864 this one : happens very rarely but it does happen */
1865 spillThis (forSym);
1866 return forSym;
1867
1868 }
1869
1870 /*-----------------------------------------------------------------*/
1871 /* spilSomething - spil some variable & mark registers as free */
1872 /*-----------------------------------------------------------------*/
1873 static bool
spilSomething(iCode * ic,eBBlock * ebp,symbol * forSym)1874 spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
1875 {
1876 symbol *ssym;
1877 int i;
1878
1879 debugLog ("%s\n", __FUNCTION__);
1880 /* get something we can spil */
1881 ssym = selectSpil (ic, ebp, forSym);
1882
1883 /* mark it as spilt */
1884 ssym->isspilt = 1;
1885 _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
1886
1887 /* mark it as not register assigned &
1888 take it away from the set */
1889 bitVectUnSetBit (_G.regAssigned, ssym->key);
1890
1891 /* mark the registers as free */
1892 for (i = 0; i < ssym->nRegs; i++)
1893 if (ssym->regs[i])
1894 freeReg (ssym->regs[i]);
1895
1896 /* if spilt on stack then free up r0 & r1
1897 if they could have been assigned to as gprs */
1898 if (!pic16_ptrRegReq && isSpiltOnStack (ssym))
1899 {
1900 pic16_ptrRegReq++;
1901 spillLRWithPtrReg (ssym);
1902 }
1903
1904 /* if this was a block level spil then insert push & pop
1905 at the start & end of block respectively */
1906 if (ssym->blockSpil)
1907 {
1908 iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
1909 /* add push to the start of the block */
1910 addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ?
1911 ebp->sch->next : ebp->sch));
1912 nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
1913 /* add pop to the end of the block */
1914 addiCodeToeBBlock (ebp, nic, NULL);
1915 }
1916
1917 /* if spilt because not used in the remainder of the
1918 block then add a push before this instruction and
1919 a pop at the end of the block */
1920 if (ssym->remainSpil)
1921 {
1922
1923 iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
1924 /* add push just before this instruction */
1925 addiCodeToeBBlock (ebp, nic, ic);
1926
1927 nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
1928 /* add pop to the end of the block */
1929 addiCodeToeBBlock (ebp, nic, NULL);
1930 }
1931
1932 if (ssym == forSym)
1933 return FALSE;
1934 else
1935 return TRUE;
1936 }
1937
1938 /*-----------------------------------------------------------------*/
1939 /* getRegPtr - will try for PTR if not a GPR type if not spil */
1940 /*-----------------------------------------------------------------*/
1941 static reg_info *
getRegPtr(iCode * ic,eBBlock * ebp,symbol * sym)1942 getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym)
1943 {
1944 reg_info *reg;
1945 int j;
1946
1947 debugLog ("%s\n", __FUNCTION__);
1948 tryAgain:
1949 /* try for a ptr type */
1950 if ((reg = allocReg (REG_PTR)))
1951 return reg;
1952
1953 /* try for gpr type */
1954 if ((reg = allocReg (REG_GPR)))
1955 return reg;
1956
1957 /* we have to spil */
1958 if (!spilSomething (ic, ebp, sym))
1959 return NULL;
1960
1961 /* make sure partially assigned registers aren't reused */
1962 for (j=0; j<=sym->nRegs; j++)
1963 if (sym->regs[j])
1964 sym->regs[j]->isFree = 0;
1965
1966 /* this looks like an infinite loop but
1967 in really selectSpil will abort */
1968 goto tryAgain;
1969 }
1970
1971 /*-----------------------------------------------------------------*/
1972 /* getRegGpr - will try for GPR if not spil */
1973 /*-----------------------------------------------------------------*/
1974 static reg_info *
getRegGpr(iCode * ic,eBBlock * ebp,symbol * sym)1975 getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
1976 {
1977 reg_info *reg;
1978 int j;
1979
1980 debugLog ("%s\n", __FUNCTION__);
1981 tryAgain:
1982 /* try for gpr type */
1983 if ((reg = allocReg (REG_GPR)))
1984 return reg;
1985
1986 if (!pic16_ptrRegReq)
1987 if ((reg = allocReg (REG_PTR)))
1988 return reg;
1989
1990 /* we have to spil */
1991 if (!spilSomething (ic, ebp, sym))
1992 return NULL;
1993
1994 /* make sure partially assigned registers aren't reused */
1995 for (j=0; j<=sym->nRegs; j++)
1996 if (sym->regs[j])
1997 sym->regs[j]->isFree = 0;
1998
1999 /* this looks like an infinite loop but
2000 in really selectSpil will abort */
2001 goto tryAgain;
2002 }
2003
2004 /*-----------------------------------------------------------------*/
2005 /* symHasReg - symbol has a given register */
2006 /*-----------------------------------------------------------------*/
2007 static bool
symHasReg(symbol * sym,reg_info * reg)2008 symHasReg (symbol *sym, reg_info *reg)
2009 {
2010 int i;
2011
2012 debugLog ("%s\n", __FUNCTION__);
2013 for (i = 0; i < sym->nRegs; i++)
2014 if (sym->regs[i] == reg)
2015 return TRUE;
2016
2017 return FALSE;
2018 }
2019
2020 /*-----------------------------------------------------------------*/
2021 /* deassignLRs - check the live to and if they have registers & are */
2022 /* not spilt then free up the registers */
2023 /*-----------------------------------------------------------------*/
2024 static void
deassignLRs(iCode * ic,eBBlock * ebp)2025 deassignLRs (iCode * ic, eBBlock * ebp)
2026 {
2027 symbol *sym;
2028 int k;
2029 symbol *result;
2030
2031 debugLog ("%s\n", __FUNCTION__);
2032 for (sym = hTabFirstItem (liveRanges, &k); sym;
2033 sym = hTabNextItem (liveRanges, &k))
2034 {
2035
2036 symbol *psym = NULL;
2037 /* if it does not end here */
2038 if (sym->liveTo > ic->seq)
2039 continue;
2040
2041 /* if it was spilt on stack then we can
2042 mark the stack spil location as free */
2043 if (sym->isspilt)
2044 {
2045 if (sym->stackSpil)
2046 {
2047 SYM_SPIL_LOC (sym)->isFree = 1;
2048 sym->stackSpil = 0;
2049 }
2050 continue;
2051 }
2052
2053 if (!bitVectBitValue (_G.regAssigned, sym->key))
2054 continue;
2055
2056 /* special case for shifting: there is a case where shift count
2057 * can be allocated in the same register as the result, so do not
2058 * free right registers if same as result registers, cause genShiftLeft
2059 * will fail -- VR */
2060 if(ic->op == LEFT_OP)
2061 continue;
2062
2063 /* special case check if this is an IFX &
2064 the privious one was a pop and the
2065 previous one was not spilt then keep track
2066 of the symbol */
2067 if (ic->op == IFX && ic->prev &&
2068 ic->prev->op == IPOP &&
2069 !ic->prev->parmPush &&
2070 !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt)
2071 psym = OP_SYMBOL (IC_LEFT (ic->prev));
2072
2073 if (sym->nRegs)
2074 {
2075 int i = 0;
2076
2077 bitVectUnSetBit (_G.regAssigned, sym->key);
2078
2079 /* if the result of this one needs registers
2080 and does not have it then assign it right
2081 away */
2082 if (IC_RESULT (ic) &&
2083 !(SKIP_IC2 (ic) || /* not a special icode */
2084 ic->op == JUMPTABLE ||
2085 ic->op == IFX ||
2086 ic->op == IPUSH ||
2087 ic->op == IPOP ||
2088 ic->op == RETURN ||
2089 POINTER_SET (ic)) &&
2090 (result = OP_SYMBOL (IC_RESULT (ic))) && /* has a result */
2091 result->liveTo > ic->seq && /* and will live beyond this */
2092 result->liveTo <= ebp->lSeq && /* does not go beyond this block */
2093 result->liveFrom == ic->seq && /* does not start before here */
2094 result->regType == sym->regType && /* same register types */
2095 result->nRegs && /* which needs registers */
2096 !result->isspilt && /* and does not already have them */
2097 !result->remat &&
2098 !bitVectBitValue (_G.regAssigned, result->key) &&
2099 /* the number of free regs + number of regs in this LR
2100 can accomodate the what result Needs */
2101 ((nfreeRegsType (result->regType) +
2102 sym->nRegs) >= result->nRegs)
2103 )
2104 {
2105
2106 for (i = 0; i < result->nRegs; i++)
2107 if (i < sym->nRegs)
2108 result->regs[i] = sym->regs[i];
2109 else
2110 result->regs[i] = getRegGpr (ic, ebp, result);
2111
2112 _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
2113
2114 }
2115
2116 /* free the remaining */
2117 for (; i < sym->nRegs; i++)
2118 {
2119 if (psym)
2120 {
2121 if (!symHasReg (psym, sym->regs[i]))
2122 freeReg (sym->regs[i]);
2123 }
2124 else
2125 freeReg (sym->regs[i]);
2126 }
2127 }
2128 }
2129 }
2130
2131
2132 /*-----------------------------------------------------------------*/
2133 /* reassignLR - reassign this to registers */
2134 /*-----------------------------------------------------------------*/
2135 static void
reassignLR(operand * op)2136 reassignLR (operand * op)
2137 {
2138 symbol *sym = OP_SYMBOL (op);
2139 int i;
2140
2141 debugLog ("%s\n", __FUNCTION__);
2142 /* not spilt any more */
2143 sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
2144 bitVectUnSetBit (_G.spiltSet, sym->key);
2145
2146 _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
2147
2148 _G.blockSpil--;
2149
2150 for (i = 0; i < sym->nRegs; i++)
2151 sym->regs[i]->isFree = 0;
2152 }
2153
2154 /*-----------------------------------------------------------------*/
2155 /* willCauseSpill - determines if allocating will cause a spill */
2156 /*-----------------------------------------------------------------*/
2157 static int
willCauseSpill(int nr,int rt)2158 willCauseSpill (int nr, int rt)
2159 {
2160 debugLog ("%s\n", __FUNCTION__);
2161 /* first check if there are any avlb registers
2162 of te type required */
2163 if (rt == REG_PTR)
2164 {
2165 /* special case for pointer type
2166 if pointer type not avlb then
2167 check for type gpr */
2168 if (nFreeRegs (rt) >= nr)
2169 return 0;
2170 if (nFreeRegs (REG_GPR) >= nr)
2171 return 0;
2172 }
2173 else
2174 {
2175 if (pic16_ptrRegReq)
2176 {
2177 if (nFreeRegs (rt) >= nr)
2178 return 0;
2179 }
2180 else
2181 {
2182 if (nFreeRegs (REG_PTR) +
2183 nFreeRegs (REG_GPR) >= nr)
2184 return 0;
2185 }
2186 }
2187
2188 debugLog (" ... yep it will (cause a spill)\n");
2189 /* it will cause a spil */
2190 return 1;
2191 }
2192
2193 /*-----------------------------------------------------------------*/
2194 /* positionRegs - the allocator can allocate same registers to res- */
2195 /* ult and operand, if this happens make sure they are in the same */
2196 /* position as the operand otherwise chaos results */
2197 /*-----------------------------------------------------------------*/
2198 static void
positionRegs(symbol * result,symbol * opsym,int lineno)2199 positionRegs (symbol * result, symbol * opsym, int lineno)
2200 {
2201 int count = min (result->nRegs, opsym->nRegs);
2202 int i, j = 0, shared = 0;
2203
2204 debugLog ("%s\n", __FUNCTION__);
2205 /* if the result has been spilt then cannot share */
2206 if (opsym->isspilt)
2207 return;
2208 again:
2209 shared = 0;
2210 /* first make sure that they actually share */
2211 for (i = 0; i < count; i++)
2212 {
2213 for (j = 0; j < count; j++)
2214 {
2215 if (result->regs[i] == opsym->regs[j] && i != j)
2216 {
2217 shared = 1;
2218 goto xchgPositions;
2219 }
2220 }
2221 }
2222 xchgPositions:
2223 if (shared)
2224 {
2225 reg_info *tmp = result->regs[i];
2226 result->regs[i] = result->regs[j];
2227 result->regs[j] = tmp;
2228 goto again;
2229 }
2230 }
2231
2232 /*------------------------------------------------------------------*/
2233 /* verifyRegsAssigned - make sure an iTemp is properly initialized; */
2234 /* it should either have registers or have beed spilled. Otherwise, */
2235 /* there was an uninitialized variable, so just spill this to get */
2236 /* the operand in a valid state. */
2237 /*------------------------------------------------------------------*/
2238 static void
verifyRegsAssigned(operand * op,iCode * ic)2239 verifyRegsAssigned (operand *op, iCode * ic)
2240 {
2241 symbol * sym;
2242
2243 if (!op) return;
2244 if (!IS_ITEMP (op)) return;
2245
2246 sym = OP_SYMBOL (op);
2247 if (sym->isspilt) return;
2248 if (!sym->nRegs) return;
2249 if (sym->regs[0]) return;
2250
2251 werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT,
2252 sym->prereqv ? sym->prereqv->name : sym->name);
2253 spillThis (sym);
2254 }
2255
2256
2257 /*-----------------------------------------------------------------*/
2258 /* serialRegAssign - serially allocate registers to the variables */
2259 /*-----------------------------------------------------------------*/
2260 static void
serialRegAssign(eBBlock ** ebbs,int count)2261 serialRegAssign (eBBlock ** ebbs, int count)
2262 {
2263 int i;
2264 iCode *ic;
2265
2266 debugLog ("%s\n", __FUNCTION__);
2267 /* for all blocks */
2268 for (i = 0; i < count; i++)
2269 {
2270 if (ebbs[i]->noPath &&
2271 (ebbs[i]->entryLabel != entryLabel &&
2272 ebbs[i]->entryLabel != returnLabel))
2273 continue;
2274
2275 /* of all instructions do */
2276 for (ic = ebbs[i]->sch; ic; ic = ic->next)
2277 {
2278
2279 debugLog (" op: %s\n", pic16_decodeOp (ic->op));
2280
2281 if(IC_RESULT(ic) && !IS_ITEMP( IC_RESULT(ic)))
2282 pic16_allocDirReg(IC_RESULT(ic));
2283
2284 if(IC_LEFT(ic) && !IS_ITEMP( IC_LEFT(ic)))
2285 pic16_allocDirReg(IC_LEFT(ic));
2286
2287 if(IC_RIGHT(ic) && !IS_ITEMP( IC_RIGHT(ic)))
2288 pic16_allocDirReg(IC_RIGHT(ic));
2289
2290 /* if this is an ipop that means some live
2291 range will have to be assigned again */
2292 if (ic->op == IPOP)
2293 reassignLR (IC_LEFT (ic));
2294
2295 /* if result is present && is a true symbol */
2296 if (IC_RESULT (ic) && ic->op != IFX &&
2297 IS_TRUE_SYMOP (IC_RESULT (ic)))
2298 OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
2299
2300 /* take away registers from live
2301 ranges that end at this instruction */
2302 deassignLRs (ic, ebbs[i]);
2303
2304 /* some don't need registers */
2305 if (SKIP_IC2 (ic) ||
2306 ic->op == JUMPTABLE ||
2307 ic->op == IFX ||
2308 ic->op == IPUSH ||
2309 ic->op == IPOP ||
2310 (IC_RESULT (ic) && POINTER_SET (ic)))
2311 continue;
2312
2313 /* now we need to allocate registers
2314 only for the result */
2315 if (IC_RESULT (ic))
2316 {
2317 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2318 bitVect *spillable;
2319 int willCS;
2320 int j;
2321 int ptrRegSet = 0;
2322
2323 /* Make sure any spill location is definately allocated */
2324 if (sym->isspilt && !sym->remat && SYM_SPIL_LOC (sym) &&
2325 !SYM_SPIL_LOC (sym)->allocreq)
2326 {
2327 SYM_SPIL_LOC (sym)->allocreq++;
2328 }
2329
2330 /* if it does not need or is spilt
2331 or is already assigned to registers
2332 or will not live beyond this instructions */
2333 if (!sym->nRegs ||
2334 sym->isspilt ||
2335 bitVectBitValue (_G.regAssigned, sym->key) ||
2336 sym->liveTo <= ic->seq)
2337 continue;
2338
2339 /* if some liverange has been spilt at the block level
2340 and this one live beyond this block then spil this
2341 to be safe */
2342 if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
2343 {
2344 spillThis (sym);
2345 continue;
2346 }
2347 /* if trying to allocate this will cause
2348 a spill and there is nothing to spill
2349 or this one is rematerializable then
2350 spill this one */
2351 willCS = willCauseSpill (sym->nRegs, sym->regType);
2352
2353 /* explicit turn off register spilling */
2354 willCS = 0;
2355
2356 spillable = computeSpillable (ic);
2357 if (sym->remat ||
2358 (willCS && bitVectIsZero (spillable)))
2359 {
2360
2361 spillThis (sym);
2362 continue;
2363
2364 }
2365
2366 /* If the live range preceeds the point of definition
2367 then ideally we must take into account registers that
2368 have been allocated after sym->liveFrom but freed
2369 before ic->seq. This is complicated, so spill this
2370 symbol instead and let fillGaps handle the allocation. */
2371 if (sym->liveFrom < ic->seq)
2372 {
2373 spillThis (sym);
2374 continue;
2375 }
2376
2377 /* if it has a spillocation & is used less than
2378 all other live ranges then spill this */
2379 if (willCS) {
2380 if (SYM_SPIL_LOC (sym)) {
2381 symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
2382 allLRs, ebbs[i], ic));
2383 if (leastUsed && leastUsed->used > sym->used) {
2384 spillThis (sym);
2385 continue;
2386 }
2387 } else {
2388 /* if none of the liveRanges have a spillLocation then better
2389 to spill this one than anything else already assigned to registers */
2390 if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
2391 /* if this is local to this block then we might find a block spil */
2392 if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
2393 spillThis (sym);
2394 continue;
2395 }
2396 }
2397 }
2398 }
2399
2400 if (ic->op == RECEIVE)
2401 debugLog ("When I get clever, I'll optimize the receive logic\n");
2402
2403 if(POINTER_GET(ic) && IS_BITFIELD(getSpec(operandType(IC_RESULT(ic))))
2404 && (SPEC_BLEN(getSpec(operandType(IC_RESULT(ic))))==1)
2405 && (ic->next->op == IFX)
2406 && (OP_LIVETO(IC_RESULT(ic)) == ic->next->seq)) {
2407
2408 /* skip register allocation since none will be used */
2409 for(j=0;j<sym->nRegs;j++)
2410 sym->regs[j] = newReg(REG_TMP, PO_GPR_TEMP, 0, "bad", 1, 0, NULL);
2411 // OP_SYMBOL(IC_RESULT(ic))->nRegs = 0;
2412
2413 continue;
2414 }
2415
2416 /* if we need ptr regs for the right side
2417 then mark it */
2418 if (POINTER_GET (ic) && IS_SYMOP( IC_LEFT(ic) ) && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
2419 <= (unsigned) NEARPTRSIZE)
2420 {
2421 pic16_ptrRegReq++;
2422 ptrRegSet = 1;
2423 }
2424 /* else we assign registers to it */
2425 _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
2426
2427 if(debugF)
2428 bitVectDebugOn(_G.regAssigned, debugF);
2429
2430 for (j = 0; j < sym->nRegs; j++)
2431 {
2432 if (sym->regType == REG_PTR)
2433 sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
2434 else
2435 sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
2436
2437 /* if the allocation falied which means
2438 this was spilt then break */
2439 if (!sym->regs[j])
2440 break;
2441 }
2442 debugLog (" %d - \n", __LINE__);
2443
2444 /* if it shares registers with operands make sure
2445 that they are in the same position */
2446 if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
2447 OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=')
2448 positionRegs (OP_SYMBOL (IC_RESULT (ic)),
2449 OP_SYMBOL (IC_LEFT (ic)), ic->lineno);
2450 /* do the same for the right operand */
2451 if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
2452 OP_SYMBOL (IC_RIGHT (ic))->nRegs && ic->op != '=')
2453 positionRegs (OP_SYMBOL (IC_RESULT (ic)),
2454 OP_SYMBOL (IC_RIGHT (ic)), ic->lineno);
2455
2456 debugLog (" %d - \n", __LINE__);
2457 if (ptrRegSet)
2458 {
2459 debugLog (" %d - \n", __LINE__);
2460 pic16_ptrRegReq--;
2461 ptrRegSet = 0;
2462 }
2463
2464 }
2465 }
2466 }
2467
2468 /* Check for and fix any problems with uninitialized operands */
2469 for (i = 0; i < count; i++)
2470 {
2471 iCode *ic;
2472
2473 if (ebbs[i]->noPath &&
2474 (ebbs[i]->entryLabel != entryLabel &&
2475 ebbs[i]->entryLabel != returnLabel))
2476 continue;
2477
2478 for (ic = ebbs[i]->sch; ic; ic = ic->next)
2479 {
2480 if (SKIP_IC2 (ic))
2481 continue;
2482
2483 if (ic->op == IFX)
2484 {
2485 verifyRegsAssigned (IC_COND (ic), ic);
2486 continue;
2487 }
2488
2489 if (ic->op == JUMPTABLE)
2490 {
2491 verifyRegsAssigned (IC_JTCOND (ic), ic);
2492 continue;
2493 }
2494
2495 verifyRegsAssigned (IC_RESULT (ic), ic);
2496 verifyRegsAssigned (IC_LEFT (ic), ic);
2497 verifyRegsAssigned (IC_RIGHT (ic), ic);
2498 }
2499 }
2500
2501 }
2502
2503 /*-----------------------------------------------------------------*/
2504 /* rUmaskForOp :- returns register mask for an operand */
2505 /*-----------------------------------------------------------------*/
2506 static bitVect *
rUmaskForOp(operand * op)2507 rUmaskForOp (operand * op)
2508 {
2509 bitVect *rumask;
2510 symbol *sym;
2511 int j;
2512
2513 debugLog ("%s\n", __FUNCTION__);
2514 /* only temporaries are assigned registers */
2515 if (!IS_ITEMP (op))
2516 return NULL;
2517
2518 sym = OP_SYMBOL (op);
2519
2520 /* if spilt or no registers assigned to it
2521 then nothing */
2522 if (sym->isspilt || !sym->nRegs)
2523 return NULL;
2524
2525 rumask = newBitVect (pic16_nRegs);
2526
2527 for (j = 0; j < sym->nRegs; j++)
2528 {
2529 rumask = bitVectSetBit (rumask,
2530 sym->regs[j]->rIdx);
2531 }
2532
2533 return rumask;
2534 }
2535
2536 /*-----------------------------------------------------------------*/
2537 /* regsUsedIniCode :- returns bit vector of registers used in iCode */
2538 /*-----------------------------------------------------------------*/
2539 static bitVect *
regsUsedIniCode(iCode * ic)2540 regsUsedIniCode (iCode * ic)
2541 {
2542 bitVect *rmask = newBitVect (pic16_nRegs);
2543
2544 debugLog ("%s\n", __FUNCTION__);
2545 /* do the special cases first */
2546 if (ic->op == IFX)
2547 {
2548 rmask = bitVectUnion (rmask,
2549 rUmaskForOp (IC_COND (ic)));
2550 goto ret;
2551 }
2552
2553 /* for the jumptable */
2554 if (ic->op == JUMPTABLE)
2555 {
2556 rmask = bitVectUnion (rmask,
2557 rUmaskForOp (IC_JTCOND (ic)));
2558
2559 goto ret;
2560 }
2561
2562 /* of all other cases */
2563 if (IC_LEFT (ic))
2564 rmask = bitVectUnion (rmask,
2565 rUmaskForOp (IC_LEFT (ic)));
2566
2567
2568 if (IC_RIGHT (ic))
2569 rmask = bitVectUnion (rmask,
2570 rUmaskForOp (IC_RIGHT (ic)));
2571
2572 if (IC_RESULT (ic))
2573 rmask = bitVectUnion (rmask,
2574 rUmaskForOp (IC_RESULT (ic)));
2575
2576 ret:
2577 return rmask;
2578 }
2579
2580 /*-----------------------------------------------------------------*/
2581 /* createRegMask - for each instruction will determine the regsUsed */
2582 /*-----------------------------------------------------------------*/
2583 static void
createRegMask(eBBlock ** ebbs,int count)2584 createRegMask (eBBlock ** ebbs, int count)
2585 {
2586 int i;
2587
2588 debugLog ("%s\n", __FUNCTION__);
2589 /* for all blocks */
2590 for (i = 0; i < count; i++)
2591 {
2592 iCode *ic;
2593
2594 if (ebbs[i]->noPath &&
2595 (ebbs[i]->entryLabel != entryLabel &&
2596 ebbs[i]->entryLabel != returnLabel))
2597 continue;
2598
2599 /* for all instructions */
2600 for (ic = ebbs[i]->sch; ic; ic = ic->next)
2601 {
2602
2603 int j;
2604
2605 if (SKIP_IC2 (ic) || !ic->rlive)
2606 continue;
2607
2608 /* first mark the registers used in this
2609 instruction */
2610 ic->rUsed = regsUsedIniCode (ic);
2611 _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
2612
2613 /* now create the register mask for those
2614 registers that are in use : this is a
2615 super set of ic->rUsed */
2616 ic->rMask = newBitVect (pic16_nRegs + 1);
2617
2618 /* for all live Ranges alive at this point */
2619 for (j = 1; j < ic->rlive->size; j++)
2620 {
2621 symbol *sym;
2622 int k;
2623
2624 /* if not alive then continue */
2625 if (!bitVectBitValue (ic->rlive, j))
2626 continue;
2627
2628 /* find the live range we are interested in */
2629 if (!(sym = hTabItemWithKey (liveRanges, j)))
2630 {
2631 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2632 "createRegMask cannot find live range");
2633 exit (0);
2634 }
2635
2636 /* if no register assigned to it */
2637 if (!sym->nRegs || sym->isspilt)
2638 continue;
2639
2640 /* for all the registers allocated to it */
2641 for (k = 0; k < sym->nRegs; k++)
2642 if (sym->regs[k])
2643 ic->rMask =
2644 bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
2645 }
2646 }
2647 }
2648 }
2649
2650 /*-----------------------------------------------------------------*/
2651 /* rematStr - returns the rematerialized string for a remat var */
2652 /*-----------------------------------------------------------------*/
2653 static symbol *
rematStr(symbol * sym)2654 rematStr (symbol * sym)
2655 {
2656 iCode *ic = sym->rematiCode;
2657 symbol *psym = NULL;
2658 int offset = 0;
2659
2660 debugLog ("%s\n", __FUNCTION__);
2661
2662 while (ic->op == '+' || ic->op == '-') {
2663 /* if plus or minus print the right hand side */
2664
2665 offset += (int) operandLitValue (IC_RIGHT (ic));
2666 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
2667 } // while
2668
2669 psym = newSymbol (OP_SYMBOL (IC_LEFT (ic))->rname, 1);
2670 psym->offset = offset;
2671 return psym;
2672 }
2673
2674 #if 0
2675 /*-----------------------------------------------------------------*/
2676 /* rematStr - returns the rematerialized string for a remat var */
2677 /*-----------------------------------------------------------------*/
2678 static char *
2679 rematStr (symbol * sym)
2680 {
2681 char *s = buffer;
2682 iCode *ic = sym->rematiCode;
2683
2684 debugLog ("%s\n", __FUNCTION__);
2685 while (1)
2686 {
2687
2688 printf ("%s\n", s);
2689 /* if plus or minus print the right hand side */
2690 /*
2691 if (ic->op == '+' || ic->op == '-') {
2692 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
2693 ic->op );
2694 s += strlen(s);
2695 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
2696 continue ;
2697 }
2698 */
2699 if (ic->op == '+' || ic->op == '-')
2700 {
2701 iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
2702 sprintf (s, "(%s %c 0x%04x)",
2703 OP_SYMBOL (IC_LEFT (ric))->rname,
2704 ic->op,
2705 (int) operandLitValue (IC_RIGHT (ic)));
2706
2707 //s += strlen(s);
2708 //ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
2709 //continue ;
2710 //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
2711 return buffer;
2712 }
2713
2714 /* we reached the end */
2715 sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
2716 break;
2717 }
2718
2719 printf ("%s\n", buffer);
2720 return buffer;
2721 }
2722 #endif
2723
2724 /*-----------------------------------------------------------------*/
2725 /* regTypeNum - computes the type & number of registers required */
2726 /*-----------------------------------------------------------------*/
2727 static void
regTypeNum()2728 regTypeNum ()
2729 {
2730 symbol *sym;
2731 int k;
2732 iCode *ic;
2733
2734 debugLog ("%s\n", __FUNCTION__);
2735 /* for each live range do */
2736 for (sym = hTabFirstItem (liveRanges, &k); sym; sym = hTabNextItem (liveRanges, &k)) {
2737
2738 debugLog (" %d - %s\n", __LINE__, sym->rname);
2739 //fprintf(stderr," %d - %s\n", __LINE__, sym->rname);
2740
2741 /* if used zero times then no registers needed */
2742 if ((sym->liveTo - sym->liveFrom) == 0)
2743 continue;
2744
2745 /* if the live range is a temporary */
2746 if (sym->isitmp) {
2747
2748 debugLog (" %d - itemp register\n", __LINE__);
2749
2750 /* if the type is marked as a conditional */
2751 if (sym->regType == REG_CND)
2752 continue;
2753
2754 /* if used in return only then we don't
2755 need registers */
2756 if (sym->ruonly || sym->accuse) {
2757 if (IS_AGGREGATE (sym->type) || sym->isptr)
2758 sym->type = aggrToPtr (sym->type, FALSE);
2759 debugLog (" %d - no reg needed - used as a return\n", __LINE__);
2760 continue;
2761 }
2762
2763 /* if the symbol has only one definition &
2764 that definition is a get_pointer and the
2765 pointer we are getting is rematerializable and
2766 in "data" space */
2767
2768 if (bitVectnBitsOn (sym->defs) == 1 &&
2769 (ic = hTabItemWithKey (iCodehTab,
2770 bitVectFirstBit (sym->defs))) &&
2771 POINTER_GET (ic) &&
2772 !IS_BITVAR (sym->etype) &&
2773 (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER)) {
2774
2775 // continue; /* FIXME -- VR */
2776 if (ptrPseudoSymSafe (sym, ic)) {
2777
2778 symbol *psym;
2779
2780 debugLog (" %d - \n", __LINE__);
2781
2782 /* create a psuedo symbol & force a spil */
2783 //X symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
2784 psym = rematStr (OP_SYMBOL (IC_LEFT (ic)));
2785 psym->type = sym->type;
2786 psym->etype = sym->etype;
2787 psym->psbase = ptrBaseRematSym (OP_SYMBOL (IC_LEFT (ic)));
2788 strcpy (psym->rname, psym->name);
2789 sym->isspilt = 1;
2790 SYM_SPIL_LOC (sym) = psym;
2791 continue;
2792 }
2793
2794 /* if in data space or idata space then try to
2795 allocate pointer register */
2796
2797 }
2798
2799 /* if not then we require registers */
2800 sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
2801 getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
2802 getSize (sym->type));
2803
2804
2805 #if 0
2806 if(IS_PTR_CONST (sym->type)) {
2807 #else
2808 if(IS_CODEPTR (sym->type)) {
2809 #endif
2810 // what IS this ???? (HJD)
2811 debugLog (" %d const pointer type requires %d registers, changing to 3\n",__LINE__,sym->nRegs); // patch 14
2812 sym->nRegs = 3; // patch 14
2813 }
2814
2815 if (sym->nRegs > 4) {
2816 fprintf (stderr, "allocated more than 4 or 0 registers for type ");
2817 printTypeChain (sym->type, stderr);
2818 fprintf (stderr, "\n");
2819 }
2820
2821 /* determine the type of register required */
2822 if (sym->nRegs == 1 &&
2823 IS_PTR (sym->type) &&
2824 sym->uptr)
2825 sym->regType = REG_PTR;
2826 else
2827 sym->regType = REG_GPR;
2828
2829
2830 debugLog (" reg name %s, reg type %s\n", sym->rname, debugLogRegType (sym->regType));
2831
2832 }
2833 else
2834 /* for the first run we don't provide */
2835 /* registers for true symbols we will */
2836 /* see how things go */
2837 sym->nRegs = 0;
2838
2839 }
2840
2841 }
2842 static DEFSETFUNC (markRegFree)
2843 {
2844 ((reg_info *)item)->isFree = 1;
2845 // ((regs *)item)->wasUsed = 0;
2846
2847 return 0;
2848 }
2849
2850 DEFSETFUNC (pic16_deallocReg)
2851 {
2852 fprintf(stderr,"deallocting register %s\n",((reg_info *)item)->name);
2853 ((reg_info *)item)->isFree = 1;
2854 ((reg_info *)item)->wasUsed = 0;
2855
2856 return 0;
2857 }
2858 /*-----------------------------------------------------------------*/
2859 /* freeAllRegs - mark all registers as free */
2860 /*-----------------------------------------------------------------*/
2861 void
2862 pic16_freeAllRegs ()
2863 {
2864 debugLog ("%s\n", __FUNCTION__);
2865
2866 applyToSet(pic16_dynAllocRegs,markRegFree);
2867 applyToSet(pic16_dynStackRegs,markRegFree);
2868 }
2869
2870 /*-----------------------------------------------------------------*/
2871 /*-----------------------------------------------------------------*/
2872 void
2873 pic16_deallocateAllRegs ()
2874 {
2875 debugLog ("%s\n", __FUNCTION__);
2876
2877 applyToSet(pic16_dynAllocRegs,pic16_deallocReg);
2878 }
2879
2880
2881 /*-----------------------------------------------------------------*/
2882 /* deallocStackSpil - this will set the stack pointer back */
2883 /*-----------------------------------------------------------------*/
2884 static
2885 DEFSETFUNC (deallocStackSpil)
2886 {
2887 symbol *sym = item;
2888
2889 debugLog ("%s\n", __FUNCTION__);
2890 deallocLocal (sym);
2891 return 0;
2892 }
2893
2894 /*-----------------------------------------------------------------*/
2895 /* farSpacePackable - returns the packable icode for far variables */
2896 /*-----------------------------------------------------------------*/
2897 static iCode *
2898 farSpacePackable (iCode * ic)
2899 {
2900 iCode *dic;
2901
2902 debugLog ("%s\n", __FUNCTION__);
2903 /* go thru till we find a definition for the
2904 symbol on the right */
2905 for (dic = ic->prev; dic; dic = dic->prev)
2906 {
2907
2908 /* if the definition is a call then no */
2909 if ((dic->op == CALL || dic->op == PCALL) &&
2910 IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
2911 {
2912 return NULL;
2913 }
2914
2915 /* if shift by unknown amount then not */
2916 if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) &&
2917 IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
2918 return NULL;
2919
2920 /* if pointer get and size > 1 */
2921 if (POINTER_GET (dic) &&
2922 getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1)
2923 return NULL;
2924
2925 if (POINTER_SET (dic) &&
2926 getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
2927 return NULL;
2928
2929 /* if any three is a true symbol in far space */
2930 if (IC_RESULT (dic) &&
2931 IS_TRUE_SYMOP (IC_RESULT (dic)) &&
2932 isOperandInFarSpace (IC_RESULT (dic)))
2933 return NULL;
2934
2935 if (IC_RIGHT (dic) &&
2936 IS_TRUE_SYMOP (IC_RIGHT (dic)) &&
2937 isOperandInFarSpace (IC_RIGHT (dic)) &&
2938 !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic)))
2939 return NULL;
2940
2941 if (IC_LEFT (dic) &&
2942 IS_TRUE_SYMOP (IC_LEFT (dic)) &&
2943 isOperandInFarSpace (IC_LEFT (dic)) &&
2944 !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic)))
2945 return NULL;
2946
2947 if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic)))
2948 {
2949 if ((dic->op == LEFT_OP ||
2950 dic->op == RIGHT_OP ||
2951 dic->op == '-') &&
2952 IS_OP_LITERAL (IC_RIGHT (dic)))
2953 return NULL;
2954 else
2955 return dic;
2956 }
2957 }
2958
2959 return NULL;
2960 }
2961
2962 #if 0
2963 static int packRegsForPointerGet(iCode *ic, eBBlock *ebp)
2964 {
2965 iCode *dic, *sic;
2966
2967 debugLog ("%d\t%s\n", __LINE__, __FUNCTION__);
2968 debugLog ("ic->op = %s\n", pic16_decodeOp( ic->op ) );
2969 debugAopGet (" result:", IC_RESULT (ic));
2970 debugAopGet (" left:", IC_LEFT (ic));
2971 debugAopGet (" right:", IC_RIGHT (ic));
2972
2973 dic = ic->prev;
2974 if((dic->op == '=')
2975 && (
2976 }
2977 #endif
2978
2979
2980 void replaceOperandWithOperand(eBBlock *ebp, iCode *ic, operand *src, iCode *dic, operand *dst);
2981
2982 /*-----------------------------------------------------------------*/
2983 /* packRegsForAssign - register reduction for assignment */
2984 /*-----------------------------------------------------------------*/
2985 static int
2986 packRegsForAssign (iCode * ic, eBBlock * ebp)
2987 {
2988 iCode *dic, *sic;
2989
2990 debugLog ("%d\t%s\n", __LINE__, __FUNCTION__);
2991 debugLog ("ic->op = %s\n", pic16_decodeOp( ic->op ) );
2992 debugAopGet (" result:", IC_RESULT (ic));
2993 debugAopGet (" left:", IC_LEFT (ic));
2994 debugAopGet (" right:", IC_RIGHT (ic));
2995
2996 // fprintf(stderr, "%s:%d symbol = %s\n", __FILE__, __LINE__, OP_SYMBOL( IC_RESULT(ic))->name);
2997
2998 debugLog(" %d - actuall processing\n", __LINE__ );
2999
3000 if (!IS_ITEMP (IC_RESULT (ic))) {
3001 pic16_allocDirReg(IC_RESULT (ic));
3002 debugLog (" %d - result is not temp\n", __LINE__);
3003 }
3004
3005 // if(IS_VALOP(IC_RIGHT(ic)))return 0;
3006
3007 /* See BUGLOG0001 - VR */
3008 #if 1
3009 if (!IS_ITEMP (IC_RIGHT (ic)) /*&& (!IS_PARM(IC_RESULT(ic)))*/) {
3010 debugLog (" %d - not packing - right is not temp\n", __LINE__);
3011 pic16_allocDirReg(IC_RIGHT (ic));
3012 return 0;
3013 }
3014 #endif
3015
3016 if (OP_SYMBOL (IC_RIGHT (ic))->isind ||
3017 OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
3018 {
3019 debugLog (" %d - not packing - right side fails \n", __LINE__);
3020 return 0;
3021 }
3022
3023 /* if the true symbol is defined in far space or on stack
3024 then we should not since this will increase register pressure */
3025 if (isOperandInFarSpace (IC_RESULT (ic)))
3026 {
3027 if ((dic = farSpacePackable (ic)))
3028 goto pack;
3029 else
3030 return 0;
3031
3032 }
3033
3034 /* find the definition of iTempNN scanning backwards if we find a
3035 a use of the true symbol before we find the definition then
3036 we cannot pack */
3037 for (dic = ic->prev; dic; dic = dic->prev)
3038 {
3039
3040 /* if there is a function call and this is
3041 a parameter & not my parameter then don't pack it */
3042 if ((dic->op == CALL || dic->op == PCALL) &&
3043 (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
3044 !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
3045 {
3046 debugLog (" %d - \n", __LINE__);
3047 dic = NULL;
3048 break;
3049 }
3050
3051
3052 if (SKIP_IC2 (dic))
3053 continue;
3054
3055 debugLog("%d\tSearching for iTempNN\n", __LINE__);
3056
3057 if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
3058 IS_OP_VOLATILE (IC_RESULT (dic)))
3059 {
3060 debugLog (" %d - dic is VOLATILE \n", __LINE__);
3061 dic = NULL;
3062 break;
3063 }
3064
3065 #if 1
3066 if( IS_SYMOP( IC_RESULT(dic)) &&
3067 IS_BITFIELD( OP_SYMBOL(IC_RESULT(dic))->etype ) ) {
3068
3069 debugLog (" %d - result is bitfield\n", __LINE__);
3070 dic = NULL;
3071 break;
3072 }
3073 #endif
3074
3075 if (IS_SYMOP (IC_RESULT (dic)) &&
3076 IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
3077 {
3078 /* A previous result was assigned to the same register - we'll our definition */
3079 debugLog (" %d - dic result key == ic right key -- pointer set=%c\n",
3080 __LINE__, ((POINTER_SET (dic)) ? 'Y' : 'N'));
3081 if (POINTER_SET (dic))
3082 dic = NULL;
3083
3084 break;
3085 }
3086
3087 if (IS_SYMOP (IC_RIGHT (dic)) &&
3088 (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
3089 IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
3090 {
3091 debugLog (" %d - dic right key == ic rightor result key\n", __LINE__);
3092 dic = NULL;
3093 break;
3094 }
3095
3096 if (IS_SYMOP (IC_LEFT (dic)) &&
3097 (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
3098 IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
3099 {
3100 debugLog (" %d - dic left key == ic rightor result key\n", __LINE__);
3101 dic = NULL;
3102 break;
3103 }
3104
3105 if (POINTER_SET (dic) &&
3106 IC_RESULT (dic)->key == IC_RESULT (ic)->key)
3107 {
3108 debugLog (" %d - dic result key == ic result key -- pointer set=Y\n",
3109 __LINE__);
3110 dic = NULL;
3111 break;
3112 }
3113 }
3114
3115 if (!dic)
3116 return 0; /* did not find */
3117
3118 #if 1
3119 /* This code is taken from the hc08 port. Do not know
3120 * if it fits for pic16, but I leave it here just in case */
3121
3122 /* if assignment then check that right is not a bit */
3123 if (ASSIGNMENT (ic) && !POINTER_SET (ic)) {
3124 sym_link *etype = operandType (IC_RESULT (dic));
3125
3126 if (IS_BITFIELD (etype)) {
3127 /* if result is a bit too then it's ok */
3128 etype = operandType (IC_RESULT (ic));
3129 if (!IS_BITFIELD (etype)) {
3130 debugLog(" %d bitfields\n");
3131 return 0;
3132 }
3133 }
3134 }
3135 #endif
3136
3137 /* if the result is on stack or iaccess then it must be
3138 the same atleast one of the operands */
3139 if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
3140 OP_SYMBOL (IC_RESULT (ic))->iaccess)
3141 {
3142 /* the operation has only one symbol
3143 operator then we can pack */
3144 if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) ||
3145 (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
3146 goto pack;
3147
3148 if (!((IC_LEFT (dic) &&
3149 IC_RESULT (ic)->key == IC_LEFT (dic)->key) ||
3150 (IC_RIGHT (dic) &&
3151 IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
3152 return 0;
3153 }
3154 pack:
3155 debugLog (" packing. removing %s\n", OP_SYMBOL (IC_RIGHT (ic))->rname);
3156 debugLog (" replacing with %s\n", OP_SYMBOL (IC_RESULT (dic))->rname);
3157 /* found the definition */
3158
3159 /* delete from liverange table also
3160 delete from all the points inbetween and the new
3161 one */
3162 for (sic = dic; sic != ic; sic = sic->next)
3163 {
3164 bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
3165 if (IS_ITEMP (IC_RESULT (dic)))
3166 bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
3167 }
3168
3169 /* replace the result with the result of */
3170 /* this assignment and remove this assignment */
3171
3172
3173 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3174 IC_RESULT (dic) = IC_RESULT (ic);
3175
3176 if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
3177 {
3178 OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
3179 }
3180
3181 remiCodeFromeBBlock (ebp, ic);
3182 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
3183
3184 debugLog(" %d\n", __LINE__ );
3185 hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
3186 OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
3187 return 1;
3188 }
3189
3190
3191 #if 1
3192
3193 #define NO_packRegsForAccUse
3194 #define NO_packRegsForSupport
3195 #define NO_packRegsForOneuse
3196 #define NO_cast_peep
3197
3198 #endif
3199
3200
3201 #ifndef NO_packRegsForSupport
3202 /*-----------------------------------------------------------------*/
3203 /* findAssignToSym : scanning backwards looks for first assig found */
3204 /*-----------------------------------------------------------------*/
3205 static iCode *
3206 findAssignToSym (operand * op, iCode * ic)
3207 {
3208 iCode *dic;
3209
3210 debugLog ("%s\n", __FUNCTION__);
3211 for (dic = ic->prev; dic; dic = dic->prev)
3212 {
3213
3214 /* if definition by assignment */
3215 if (dic->op == '=' &&
3216 !POINTER_SET (dic) &&
3217 IC_RESULT (dic)->key == op->key
3218 /* && IS_TRUE_SYMOP(IC_RIGHT(dic)) */
3219 )
3220 {
3221
3222 /* we are interested only if defined in far space */
3223 /* or in stack space in case of + & - */
3224
3225 /* if assigned to a non-symbol then return
3226 true */
3227 if (!IS_SYMOP (IC_RIGHT (dic)))
3228 break;
3229
3230 /* if the symbol is in far space then
3231 we should not */
3232 if (isOperandInFarSpace (IC_RIGHT (dic)))
3233 return NULL;
3234
3235 /* for + & - operations make sure that
3236 if it is on the stack it is the same
3237 as one of the three operands */
3238 if ((ic->op == '+' || ic->op == '-') &&
3239 OP_SYMBOL (IC_RIGHT (dic))->onStack)
3240 {
3241 if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
3242 IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
3243 IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
3244 return NULL;
3245 }
3246
3247 break;
3248
3249 }
3250
3251 /* if we find an usage then we cannot delete it */
3252 if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
3253 return NULL;
3254
3255 if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
3256 return NULL;
3257
3258 if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
3259 return NULL;
3260 }
3261
3262 /* now make sure that the right side of dic
3263 is not defined between ic & dic */
3264 if (dic)
3265 {
3266 iCode *sic = dic->next;
3267
3268 for (; sic != ic; sic = sic->next)
3269 if (IC_RESULT (sic) &&
3270 IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
3271 return NULL;
3272 }
3273
3274 return dic;
3275
3276
3277 }
3278 #endif
3279
3280
3281 #ifndef NO_packRegsForSupport
3282 /*-----------------------------------------------------------------*/
3283 /* packRegsForSupport :- reduce some registers for support calls */
3284 /*-----------------------------------------------------------------*/
3285 static int
3286 packRegsForSupport (iCode * ic, eBBlock * ebp)
3287 {
3288 int change = 0;
3289
3290 debugLog ("%s\n", __FUNCTION__);
3291 /* for the left & right operand :- look to see if the
3292 left was assigned a true symbol in far space in that
3293 case replace them */
3294 if (IS_ITEMP (IC_LEFT (ic)) &&
3295 OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
3296 {
3297 iCode *dic = findAssignToSym (IC_LEFT (ic), ic);
3298 iCode *sic;
3299
3300 if (!dic)
3301 goto right;
3302
3303 debugAopGet ("removing left:", IC_LEFT (ic));
3304
3305 /* found it we need to remove it from the
3306 block */
3307 for (sic = dic; sic != ic; sic = sic->next)
3308 bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
3309
3310 IC_LEFT (ic)->operand.symOperand =
3311 IC_RIGHT (dic)->operand.symOperand;
3312 IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
3313 remiCodeFromeBBlock (ebp, dic);
3314 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3315 hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3316 change++;
3317 }
3318
3319 /* do the same for the right operand */
3320 right:
3321 if (!change &&
3322 IS_ITEMP (IC_RIGHT (ic)) &&
3323 OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
3324 {
3325 iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
3326 iCode *sic;
3327
3328 if (!dic)
3329 return change;
3330
3331 /* if this is a subtraction & the result
3332 is a true symbol in far space then don't pack */
3333 if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
3334 {
3335 sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
3336 if (IN_FARSPACE (SPEC_OCLS (etype)))
3337 return change;
3338 }
3339
3340 debugAopGet ("removing right:", IC_RIGHT (ic));
3341
3342 /* found it we need to remove it from the
3343 block */
3344 for (sic = dic; sic != ic; sic = sic->next)
3345 bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
3346
3347 IC_RIGHT (ic)->operand.symOperand =
3348 IC_RIGHT (dic)->operand.symOperand;
3349 IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
3350
3351 remiCodeFromeBBlock (ebp, dic);
3352 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3353 hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3354 change++;
3355 }
3356
3357 return change;
3358 }
3359 #endif
3360
3361
3362 #ifndef NO_packRegsForOneuse
3363 /*-----------------------------------------------------------------*/
3364 /* packRegsForOneuse : - will reduce some registers for single Use */
3365 /*-----------------------------------------------------------------*/
3366 static iCode *
3367 packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
3368 {
3369 bitVect *uses;
3370 iCode *dic, *sic;
3371
3372 return NULL;
3373
3374 debugLog ("%s\n", __FUNCTION__);
3375 /* if returning a literal then do nothing */
3376 if (!IS_SYMOP (op))
3377 return NULL;
3378
3379 if(OP_SYMBOL(op)->remat || OP_SYMBOL(op)->ruonly)
3380 return NULL;
3381
3382 /* only upto 2 bytes since we cannot predict
3383 the usage of b, & acc */
3384 if (getSize (operandType (op)) > (pic16_fReturnSizePic - 1)
3385 && ic->op != RETURN
3386 && ic->op != SEND
3387 && !POINTER_SET(ic)
3388 && !POINTER_GET(ic)
3389 )
3390 return NULL;
3391
3392 /* this routine will mark the a symbol as used in one
3393 instruction use only && if the definition is local
3394 (ie. within the basic block) && has only one definition &&
3395 that definition is either a return value from a
3396 function or does not contain any variables in
3397 far space */
3398
3399 #if 0
3400 uses = bitVectCopy (OP_USES (op));
3401 bitVectUnSetBit (uses, ic->key); /* take away this iCode */
3402 if (!bitVectIsZero (uses)) /* has other uses */
3403 return NULL;
3404 #endif
3405
3406 #if 1
3407 if (bitVectnBitsOn (OP_USES (op)) > 1)
3408 return NULL;
3409 #endif
3410
3411 /* if it has only one defintion */
3412 if (bitVectnBitsOn (OP_DEFS (op)) > 1)
3413 return NULL; /* has more than one definition */
3414
3415 /* get that definition */
3416 if (!(dic =
3417 hTabItemWithKey (iCodehTab,
3418 bitVectFirstBit (OP_DEFS (op)))))
3419 return NULL;
3420
3421 /* found the definition now check if it is local */
3422 if (dic->seq < ebp->fSeq ||
3423 dic->seq > ebp->lSeq)
3424 return NULL; /* non-local */
3425
3426 /* now check if it is the return from
3427 a function call */
3428 if (dic->op == CALL || dic->op == PCALL)
3429 {
3430 if (ic->op != SEND && ic->op != RETURN &&
3431 !POINTER_SET(ic) && !POINTER_GET(ic))
3432 {
3433 OP_SYMBOL (op)->ruonly = 1;
3434 return dic;
3435 }
3436 dic = dic->next;
3437 }
3438 else
3439 {
3440
3441
3442 /* otherwise check that the definition does
3443 not contain any symbols in far space */
3444 if (isOperandInFarSpace (IC_LEFT (dic)) ||
3445 isOperandInFarSpace (IC_RIGHT (dic)) ||
3446 IS_OP_RUONLY (IC_LEFT (ic)) ||
3447 IS_OP_RUONLY (IC_RIGHT (ic)))
3448 {
3449 return NULL;
3450 }
3451
3452 /* if pointer set then make sure the pointer
3453 is one byte */
3454 if (POINTER_SET (dic) &&
3455 !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
3456 return NULL;
3457
3458 if (POINTER_GET (dic) &&
3459 !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
3460 return NULL;
3461 }
3462
3463 sic = dic;
3464
3465 /* also make sure the intervenening instructions
3466 don't have any thing in far space */
3467 for (dic = dic->next; dic && dic != ic; dic = dic->next)
3468 {
3469
3470 /* if there is an intervening function call then no */
3471 if (dic->op == CALL || dic->op == PCALL)
3472 return NULL;
3473 /* if pointer set then make sure the pointer
3474 is one byte */
3475 if (POINTER_SET (dic) &&
3476 !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
3477 return NULL;
3478
3479 if (POINTER_GET (dic) &&
3480 !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
3481 return NULL;
3482
3483 /* if address of & the result is remat then okay */
3484 if (dic->op == ADDRESS_OF &&
3485 OP_SYMBOL (IC_RESULT (dic))->remat)
3486 continue;
3487
3488 /* if operand has size of three or more & this
3489 operation is a '*','/' or '%' then 'b' may
3490 cause a problem */
3491 if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
3492 getSize (operandType (op)) >= 2)
3493 return NULL;
3494
3495 /* if left or right or result is in far space */
3496 if (isOperandInFarSpace (IC_LEFT (dic)) ||
3497 isOperandInFarSpace (IC_RIGHT (dic)) ||
3498 isOperandInFarSpace (IC_RESULT (dic)) ||
3499 IS_OP_RUONLY (IC_LEFT (dic)) ||
3500 IS_OP_RUONLY (IC_RIGHT (dic)) ||
3501 IS_OP_RUONLY (IC_RESULT (dic)))
3502 {
3503 return NULL;
3504 }
3505 }
3506
3507 OP_SYMBOL (op)->ruonly = 1;
3508 return sic;
3509
3510 }
3511 #endif
3512
3513
3514 /*-----------------------------------------------------------------*/
3515 /* isBitwiseOptimizable - requirements of JEAN LOUIS VERN */
3516 /*-----------------------------------------------------------------*/
3517 static bool
3518 isBitwiseOptimizable (iCode * ic)
3519 {
3520 sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
3521 sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
3522
3523 debugLog ("%s\n", __FUNCTION__);
3524 /* bitwise operations are considered optimizable
3525 under the following conditions (Jean-Louis VERN)
3526
3527 x & lit
3528 bit & bit
3529 bit & x
3530 bit ^ bit
3531 bit ^ x
3532 x ^ lit
3533 x | lit
3534 bit | bit
3535 bit | x
3536 */
3537 if (IS_LITERAL (rtype) ||
3538 (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
3539 return TRUE;
3540 else
3541 return FALSE;
3542 }
3543
3544
3545 #ifndef NO_packRegsForAccUse
3546
3547 /*-----------------------------------------------------------------*/
3548 /* packRegsForAccUse - pack registers for acc use */
3549 /*-----------------------------------------------------------------*/
3550 static void
3551 packRegsForAccUse (iCode * ic)
3552 {
3553 iCode *uic;
3554
3555 debugLog ("%s\n", __FUNCTION__);
3556
3557 /* if this is an aggregate, e.g. a one byte char array */
3558 if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
3559 return;
3560 }
3561 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3562
3563 /* if + or - then it has to be one byte result */
3564 if ((ic->op == '+' || ic->op == '-')
3565 && getSize (operandType (IC_RESULT (ic))) > 1)
3566 return;
3567
3568 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3569 /* if shift operation make sure right side is not a literal */
3570 if (ic->op == RIGHT_OP &&
3571 (isOperandLiteral (IC_RIGHT (ic)) ||
3572 getSize (operandType (IC_RESULT (ic))) > 1))
3573 return;
3574
3575 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3576 if (ic->op == LEFT_OP &&
3577 (isOperandLiteral (IC_RIGHT (ic)) ||
3578 getSize (operandType (IC_RESULT (ic))) > 1))
3579 return;
3580
3581 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3582 if (IS_BITWISE_OP (ic) &&
3583 getSize (operandType (IC_RESULT (ic))) > 1)
3584 return;
3585
3586
3587 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3588 /* has only one definition */
3589 if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
3590 return;
3591
3592 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3593 /* has only one use */
3594 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
3595 return;
3596
3597 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3598 /* and the usage immediately follows this iCode */
3599 if (!(uic = hTabItemWithKey (iCodehTab,
3600 bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
3601 return;
3602
3603 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3604 if (ic->next != uic)
3605 return;
3606
3607 /* if it is a conditional branch then we definitely can */
3608 if (uic->op == IFX)
3609 goto accuse;
3610
3611 if (uic->op == JUMPTABLE)
3612 return;
3613
3614 /* if the usage is not is an assignment
3615 or an arithmetic / bitwise / shift operation then not */
3616 if (POINTER_SET (uic) &&
3617 getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
3618 return;
3619
3620 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3621 if (uic->op != '=' &&
3622 !IS_ARITHMETIC_OP (uic) &&
3623 !IS_BITWISE_OP (uic) &&
3624 uic->op != LEFT_OP &&
3625 uic->op != RIGHT_OP)
3626 return;
3627
3628 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3629 /* if used in ^ operation then make sure right is not a
3630 literl */
3631 if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
3632 return;
3633
3634 /* if shift operation make sure right side is not a literal */
3635 if (uic->op == RIGHT_OP &&
3636 (isOperandLiteral (IC_RIGHT (uic)) ||
3637 getSize (operandType (IC_RESULT (uic))) > 1))
3638 return;
3639
3640 if (uic->op == LEFT_OP &&
3641 (isOperandLiteral (IC_RIGHT (uic)) ||
3642 getSize (operandType (IC_RESULT (uic))) > 1))
3643 return;
3644
3645 /* make sure that the result of this icode is not on the
3646 stack, since acc is used to compute stack offset */
3647 if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
3648 OP_SYMBOL (IC_RESULT (uic))->onStack)
3649 return;
3650
3651 /* if either one of them in far space then we cannot */
3652 if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
3653 isOperandInFarSpace (IC_LEFT (uic))) ||
3654 (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
3655 isOperandInFarSpace (IC_RIGHT (uic))))
3656 return;
3657
3658 /* if the usage has only one operand then we can */
3659 if (IC_LEFT (uic) == NULL ||
3660 IC_RIGHT (uic) == NULL)
3661 goto accuse;
3662
3663 /* make sure this is on the left side if not
3664 a '+' since '+' is commutative */
3665 if (ic->op != '+' &&
3666 IC_LEFT (uic)->key != IC_RESULT (ic)->key)
3667 return;
3668
3669 #if 1
3670 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3671 /* if one of them is a literal then we can */
3672 if ( ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
3673 (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic)))) &&
3674 (getSize (operandType (IC_RESULT (uic))) <= 1))
3675 {
3676 OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
3677 return;
3678 }
3679 #endif
3680
3681 debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
3682 /* if the other one is not on stack then we can */
3683 if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
3684 (IS_ITEMP (IC_RIGHT (uic)) ||
3685 (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
3686 !OP_SYMBOL (IC_RIGHT (uic))->onStack)))
3687 goto accuse;
3688
3689 if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
3690 (IS_ITEMP (IC_LEFT (uic)) ||
3691 (IS_TRUE_SYMOP (IC_LEFT (uic)) &&
3692 !OP_SYMBOL (IC_LEFT (uic))->onStack)))
3693 goto accuse;
3694
3695 return;
3696
3697 accuse:
3698 debugLog ("%s - Yes we are using the accumulator\n", __FUNCTION__);
3699 OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
3700
3701
3702 }
3703 #endif
3704
3705
3706 /*-----------------------------------------------------------------*/
3707 /* packForPush - hueristics to reduce iCode for pushing */
3708 /*-----------------------------------------------------------------*/
3709 static void
3710 packForReceive (iCode * ic, eBBlock * ebp)
3711 {
3712 iCode *dic;
3713
3714 debugLog ("%s\n", __FUNCTION__);
3715 debugAopGet (" result:", IC_RESULT (ic));
3716 debugAopGet (" left:", IC_LEFT (ic));
3717 debugAopGet (" right:", IC_RIGHT (ic));
3718
3719 if (!ic->next)
3720 return;
3721
3722 for (dic = ic->next; dic; dic = dic->next)
3723 {
3724 if (IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key))
3725 debugLog (" used on left\n");
3726 if (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key)
3727 debugLog (" used on right\n");
3728 if (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key)
3729 debugLog (" used on result\n");
3730
3731 if ((IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key)) ||
3732 (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key))
3733 return;
3734 }
3735
3736 debugLog (" hey we can remove this unnecessary assign\n");
3737 }
3738 /*-----------------------------------------------------------------*/
3739 /* packForPush - hueristics to reduce iCode for pushing */
3740 /*-----------------------------------------------------------------*/
3741 static void
3742 packForPush (iCode * ic, eBBlock * ebp)
3743 {
3744 iCode *dic, *lic;
3745 const char *iLine;
3746 bitVect *dbv;
3747 int disallowHiddenAssignment = 0;
3748
3749 debugLog ("%s\n", __FUNCTION__);
3750 if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
3751 return;
3752
3753 #if 0
3754 {
3755 int n1, n2;
3756
3757 n1 = bitVectnBitsOn( OP_DEFS(IC_LEFT(ic)));
3758 n2 = bitVectnBitsOn( OP_USES(IC_LEFT(ic)));
3759 iLine = printILine(ic);
3760 debugf3("defs: %d\tuses: %d\t%s\n", n1, n2, printILine(ic));
3761 dbuf_free(iLine);
3762 debugf2("IC_LEFT(ic): from %d to %d\n", OP_LIVEFROM(IC_LEFT(ic)), OP_LIVETO(IC_LEFT(ic)));
3763 }
3764 #endif
3765
3766 /* must have only definition & one usage */
3767 if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
3768 bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
3769 return;
3770
3771 /* find the definition */
3772 if (!(dic = hTabItemWithKey (iCodehTab,
3773 bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
3774 return;
3775
3776 /* if definition is not assignment,
3777 * or is not pointer (because pointer might have changed) */
3778 if (dic->op != '=' || POINTER_SET (dic))
3779 return;
3780
3781 /* we must ensure that we can use the delete the assignment,
3782 * because the source might have been modified in between.
3783 * Until I know how to fix this, I'll use the adhoc fix
3784 * to check the liveranges */
3785 if((OP_LIVEFROM(IC_RIGHT(dic))==0) || (OP_LIVETO(IC_RIGHT(dic))==0))
3786 return;
3787 // debugf2("IC_RIGHT(dic): from %d to %d\n", OP_LIVEFROM(IC_RIGHT(dic)), OP_LIVETO(IC_RIGHT(dic)));
3788
3789 /* If the defining iCode is outside of this block, we need to recompute */
3790 /* ebp (see the mcs51 version of packForPush), but we weren't passed */
3791 /* enough data to do that. Just bail out instead if that happens. */
3792 if (dic->seq < ebp->fSeq)
3793 return;
3794
3795 if (IS_SYMOP (IC_RIGHT (dic)))
3796 {
3797 if (IC_RIGHT (dic)->isvolatile)
3798 return;
3799
3800 if (OP_SYMBOL (IC_RIGHT (dic))->addrtaken || isOperandGlobal (IC_RIGHT (dic)))
3801 disallowHiddenAssignment = 1;
3802
3803 /* make sure the right side does not have any definitions
3804 inbetween */
3805 dbv = OP_DEFS (IC_RIGHT (dic));
3806 for (lic = ic; lic && lic != dic; lic = lic->prev)
3807 {
3808 if (bitVectBitValue (dbv, lic->key))
3809 return;
3810 if (disallowHiddenAssignment && (lic->op == CALL || lic->op == PCALL || POINTER_SET (lic)))
3811 return;
3812 }
3813 /* make sure they have the same type */
3814 if (IS_SPEC (operandType (IC_LEFT (ic))))
3815 {
3816 sym_link *itype = operandType (IC_LEFT (ic));
3817 sym_link *ditype = operandType (IC_RIGHT (dic));
3818
3819 if (SPEC_USIGN (itype) != SPEC_USIGN (ditype) || SPEC_LONG (itype) != SPEC_LONG (ditype))
3820 return;
3821 }
3822 }
3823
3824
3825 /*
3826 * The following code causes segfaults, e.g.,
3827 * #2496919 Internal error with pic16 sdcc
3828 * and is thus disabled for now.
3829 */
3830 if (0)
3831 {
3832 /* we now we know that it has one & only one def & use
3833 and the that the definition is an assignment */
3834
3835 /* extend the live range of replaced operand if needed */
3836 if (IS_SYMOP (IC_RIGHT (dic)) && OP_SYMBOL (IC_RIGHT (dic))->liveTo < ic->seq)
3837 {
3838 OP_SYMBOL (IC_RIGHT (dic))->liveTo = ic->seq;
3839 }
3840 bitVectUnSetBit (OP_SYMBOL (IC_RESULT (dic))->defs, dic->key);
3841 if (IS_ITEMP (IC_RIGHT (dic)))
3842 OP_USES (IC_RIGHT (dic)) = bitVectSetBit (OP_USES (IC_RIGHT (dic)), ic->key);
3843
3844 IC_LEFT (ic) = IC_RIGHT (dic);
3845
3846 iLine = printILine(dic);
3847 debugf("remiCodeFromeBBlock: %s\n", iLine);
3848 dbuf_free(iLine);
3849
3850 remiCodeFromeBBlock (ebp, dic);
3851 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
3852 hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
3853 } // if
3854 }
3855
3856 static void printSymType(char * str, sym_link *sl)
3857 {
3858 if(!pic16_ralloc_debug)return;
3859
3860 debugLog (" %s Symbol type: ",str);
3861 printTypeChain (sl, debugF);
3862 debugLog ("\n");
3863 }
3864
3865 /*-----------------------------------------------------------------*/
3866 /* some debug code to print the symbol S_TYPE. Note that
3867 * the function checkSClass in src/SDCCsymt.c dinks with
3868 * the S_TYPE in ways the PIC port doesn't fully like...*/
3869 /*-----------------------------------------------------------------*/
3870 static void isData(sym_link *sl)
3871 {
3872 FILE *of = stderr;
3873
3874 if(!pic16_ralloc_debug)return;
3875
3876 if(!sl)return;
3877
3878 if(debugF)
3879 of = debugF;
3880
3881 for ( ; sl; sl=sl->next) {
3882 if(!IS_DECL(sl) ) {
3883 switch (SPEC_SCLS(sl)) {
3884 case S_DATA: fprintf (of, "data "); break;
3885 case S_XDATA: fprintf (of, "xdata "); break;
3886 case S_SFR: fprintf (of, "sfr "); break;
3887 case S_SBIT: fprintf (of, "sbit "); break;
3888 case S_CODE: fprintf (of, "code "); break;
3889 case S_IDATA: fprintf (of, "idata "); break;
3890 case S_PDATA: fprintf (of, "pdata "); break;
3891 case S_LITERAL: fprintf (of, "literal "); break;
3892 case S_STACK: fprintf (of, "stack "); break;
3893 case S_XSTACK: fprintf (of, "xstack "); break;
3894 case S_BIT: fprintf (of, "bit "); break;
3895 case S_EEPROM: fprintf (of, "eeprom "); break;
3896 default: break;
3897 }
3898 }
3899 }
3900 }
3901
3902
3903 /*--------------------------------------------------------------------*/
3904 /* pic16_packRegisters - does some transformations to reduce */
3905 /* register pressure */
3906 /* */
3907 /*--------------------------------------------------------------------*/
3908 static void
3909 pic16_packRegisters (eBBlock * ebp)
3910 {
3911 iCode *ic;
3912 int change = 0;
3913
3914 debugLog ("%s\n", __FUNCTION__);
3915
3916 while (1) {
3917
3918 change = 0;
3919
3920 /* look for assignments of the form */
3921 /* iTempNN = TRueSym (someoperation) SomeOperand */
3922 /* .... */
3923 /* TrueSym := iTempNN:1 */
3924 for (ic = ebp->sch; ic; ic = ic->next)
3925 {
3926 // debugLog("%d\n", __LINE__);
3927 /* find assignment of the form TrueSym := iTempNN:1 */
3928 if ( (ic->op == '=') && !POINTER_SET (ic) ) // patch 11
3929 change += packRegsForAssign (ic, ebp);
3930 /* debug stuff */
3931 if (ic->op == '=')
3932 {
3933 if (POINTER_SET (ic))
3934 debugLog ("pointer is set\n");
3935 debugAopGet (" result:", IC_RESULT (ic));
3936 debugAopGet (" left:", IC_LEFT (ic));
3937 debugAopGet (" right:", IC_RIGHT (ic));
3938 }
3939
3940 }
3941
3942 if (!change)
3943 break;
3944 }
3945
3946 for (ic = ebp->sch; ic; ic = ic->next) {
3947
3948 if(IS_SYMOP ( IC_LEFT(ic))) {
3949 sym_link *etype = getSpec (operandType (IC_LEFT (ic)));
3950
3951 debugAopGet ("x left:", IC_LEFT (ic));
3952 #if 0
3953 if(IS_PTR_CONST(OP_SYMBOL(IC_LEFT(ic))->type))
3954 #else
3955 if(IS_CODEPTR(OP_SYMBOL(IC_LEFT(ic))->type))
3956 #endif
3957 debugLog (" is a pointer\n");
3958
3959 if(IS_PTR(OP_SYMBOL(IC_LEFT(ic))->type))
3960 debugLog (" is a ptr\n");
3961
3962 if(IS_OP_VOLATILE(IC_LEFT(ic)))
3963 debugLog (" is volatile\n");
3964
3965 isData(etype);
3966
3967 if(IS_OP_VOLATILE(IC_LEFT(ic))) {
3968 debugLog (" %d - left is not temp, allocating\n", __LINE__);
3969 pic16_allocDirReg(IC_LEFT (ic));
3970 }
3971
3972 printSymType("c ", OP_SYMBOL(IC_LEFT(ic))->type);
3973 }
3974
3975 if(IS_SYMOP ( IC_RIGHT(ic))) {
3976 debugAopGet (" right:", IC_RIGHT (ic));
3977 printSymType(" ", OP_SYMBOL(IC_RIGHT(ic))->type);
3978 }
3979
3980 if(IS_SYMOP ( IC_RESULT(ic))) {
3981 debugAopGet (" result:", IC_RESULT (ic));
3982 printSymType(" ", OP_SYMBOL(IC_RESULT(ic))->type);
3983 }
3984
3985 if(IS_TRUE_SYMOP ( IC_RIGHT(ic))) {
3986 debugAopGet (" right:", IC_RIGHT (ic));
3987 printSymType(" ", OP_SYMBOL(IC_RIGHT(ic))->type);
3988 // pic16_allocDirReg(IC_RIGHT(ic));
3989 }
3990
3991 if(IS_TRUE_SYMOP ( IC_RESULT(ic))) {
3992 debugAopGet (" result:", IC_RESULT (ic));
3993 printSymType(" ", OP_SYMBOL(IC_RESULT(ic))->type);
3994 // pic16_allocDirReg(IC_RESULT(ic));
3995 }
3996
3997
3998 if (POINTER_SET (ic))
3999 debugLog (" %d - Pointer set\n", __LINE__);
4000
4001 /* Look for two subsequent iCodes with */
4002 /* iTemp := _c; */
4003 /* _c = iTemp & op; */
4004 /* and replace them by */
4005 /* iTemp := _c; */
4006 /* _c = _c & op; */
4007 if ((ic->op == BITWISEAND || ic->op == '|' || ic->op == '^')
4008 && ic->prev
4009 && ic->prev->op == '='
4010 && IS_ITEMP (IC_LEFT (ic))
4011 && IC_LEFT (ic) == IC_RESULT (ic->prev)
4012 && isOperandEqual (IC_RESULT(ic), IC_RIGHT(ic->prev)))
4013 {
4014 iCode* ic_prev = ic->prev;
4015 symbol* prev_result_sym = OP_SYMBOL (IC_RESULT (ic_prev));
4016
4017 ReplaceOpWithCheaperOp (&IC_LEFT (ic), IC_RESULT (ic));
4018 if (IC_RESULT (ic_prev) != IC_RIGHT (ic)) {
4019 bitVectUnSetBit (OP_USES (IC_RESULT (ic_prev)), ic->key);
4020 if (/*IS_ITEMP (IC_RESULT (ic_prev)) && */
4021 prev_result_sym->liveTo == ic->seq)
4022 {
4023 prev_result_sym->liveTo = ic_prev->seq;
4024 }
4025 }
4026 bitVectSetBit (OP_USES (IC_RESULT (ic)), ic->key);
4027
4028 bitVectSetBit (ic->rlive, IC_RESULT (ic)->key);
4029
4030 if (bitVectIsZero (OP_USES (IC_RESULT (ic_prev)))) {
4031 bitVectUnSetBit (ic->rlive, IC_RESULT (ic)->key);
4032 bitVectUnSetBit (OP_DEFS (IC_RESULT (ic_prev)), ic_prev->key);
4033 remiCodeFromeBBlock (ebp, ic_prev);
4034 hTabDeleteItem (&iCodehTab, ic_prev->key, ic_prev, DELETE_ITEM, NULL);
4035 }
4036 }
4037
4038 /* if this is an itemp & result of a address of a true sym
4039 then mark this as rematerialisable */
4040 if (ic->op == ADDRESS_OF &&
4041 IS_ITEMP (IC_RESULT (ic)) &&
4042 IS_TRUE_SYMOP (IC_LEFT (ic)) &&
4043 bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
4044 !OP_SYMBOL (IC_LEFT (ic))->onStack)
4045 {
4046
4047 debugLog (" %d - %s. result is rematerializable\n", __LINE__,__FUNCTION__);
4048
4049 OP_SYMBOL (IC_RESULT (ic))->remat = 1;
4050 OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
4051 SPIL_LOC (IC_RESULT (ic)) = NULL;
4052
4053 }
4054
4055 /* if straight assignment then carry remat flag if
4056 this is the only definition */
4057 if (ic->op == '=' &&
4058 !POINTER_SET (ic) &&
4059 IS_SYMOP (IC_RIGHT (ic)) &&
4060 OP_SYMBOL (IC_RIGHT (ic))->remat &&
4061 bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1 &&
4062 !isOperandGlobal (IC_RESULT (ic)) &&
4063 !OP_SYMBOL (IC_RESULT (ic))->addrtaken)
4064 {
4065 debugLog (" %d - %s. straight rematerializable\n", __LINE__,__FUNCTION__);
4066
4067 OP_SYMBOL (IC_RESULT (ic))->remat =
4068 OP_SYMBOL (IC_RIGHT (ic))->remat;
4069 OP_SYMBOL (IC_RESULT (ic))->rematiCode =
4070 OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
4071 }
4072
4073 /* if this is a +/- operation with a rematerizable
4074 then mark this as rematerializable as well */
4075 if ((ic->op == '+' || ic->op == '-') &&
4076 (IS_SYMOP (IC_LEFT (ic)) &&
4077 IS_ITEMP (IC_RESULT (ic)) &&
4078 OP_SYMBOL (IC_LEFT (ic))->remat &&
4079 bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
4080 IS_OP_LITERAL (IC_RIGHT (ic))))
4081 {
4082 debugLog (" %d - %s. rematerializable because op is +/-\n", __LINE__,__FUNCTION__);
4083 //int i =
4084 operandLitValue (IC_RIGHT (ic));
4085 OP_SYMBOL (IC_RESULT (ic))->remat = 1;
4086 OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
4087 SPIL_LOC (IC_RESULT (ic)) = NULL;
4088 }
4089
4090
4091 #if 0
4092 /* try to optimize FSR0 usage when reading data memory pointers */
4093
4094 if(getenv("OPTIMIZE_NEAR_POINTER_GET")) {
4095 static int fsr0usage=0;
4096 static iCode *usic;
4097
4098 if(POINTER_GET(ic) /* this is a memory read */
4099 && ic->loop /* this is in a loop */
4100 ) {
4101 fprintf(stderr, "might optimize FSR0 usage\n");
4102 }
4103 }
4104 #endif
4105
4106 /* mark the pointer usages */
4107 if (POINTER_SET (ic) && IS_SYMOP (IC_RESULT (ic)))
4108 {
4109 OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
4110 debugLog (" marking as a pointer (set) =>");
4111 debugAopGet (" result:", IC_RESULT (ic));
4112
4113 }
4114
4115 if (POINTER_GET (ic))
4116 {
4117 if(IS_SYMOP(IC_LEFT(ic))) {
4118 OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
4119 debugLog (" marking as a pointer (get) =>");
4120 debugAopGet (" left:", IC_LEFT (ic));
4121 }
4122
4123 if(getenv("OPTIMIZE_BITFIELD_POINTER_GET")) {
4124 if(IS_ITEMP(IC_LEFT(ic)) && IS_BITFIELD(OP_SYM_ETYPE(IC_LEFT(ic)))) {
4125 iCode *dic = ic->prev;
4126
4127 fprintf(stderr, "%s:%d might give opt POINTER_GET && IS_BITFIELD(IC_LEFT)\n", __FILE__, __LINE__);
4128
4129 if(dic && dic->op == '='
4130 && isOperandEqual(IC_RESULT(dic), IC_LEFT(ic))) {
4131
4132 fprintf(stderr, "%s:%d && prev is '=' && prev->result == ic->left\n", __FILE__, __LINE__);
4133
4134
4135 /* replace prev->left with ic->left */
4136 IC_LEFT(ic) = IC_RIGHT(dic);
4137 IC_RIGHT(ic->prev) = NULL;
4138
4139 /* remove ic->prev iCode (assignment) */
4140 remiCodeFromeBBlock (ebp, dic);
4141 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,ic->key);
4142
4143
4144 hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
4145 }
4146 }
4147 }
4148 }
4149
4150 //debugLog(" %d %s\n", __LINE__, __FUNCTION__);
4151
4152 if (!SKIP_IC2 (ic))
4153 {
4154 //debugLog(" %d %s\n", __LINE__, __FUNCTION__ );
4155 /* if we are using a symbol on the stack
4156 then we should say pic16_ptrRegReq */
4157 if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
4158 pic16_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ||
4159 OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0);
4160 else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
4161 pic16_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ||
4162 OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0);
4163 else
4164 {
4165
4166 //debugLog(" %d %s\n", __LINE__, __FUNCTION__ );
4167 if (IS_SYMOP (IC_LEFT (ic)))
4168 pic16_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ||
4169 OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0);
4170 if (IS_SYMOP (IC_RIGHT (ic)))
4171 pic16_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ||
4172 OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0);
4173 if (IS_SYMOP (IC_RESULT (ic)))
4174 pic16_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ||
4175 OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0);
4176 }
4177
4178 debugLog (" %d - pointer reg req = %d\n", __LINE__,pic16_ptrRegReq);
4179
4180 }
4181
4182 /* if the condition of an if instruction
4183 is defined in the previous instruction then
4184 mark the itemp as a conditional */
4185 if ((IS_CONDITIONAL (ic) ||
4186 ((ic->op == BITWISEAND ||
4187 ic->op == '|' ||
4188 ic->op == '^') &&
4189 isBitwiseOptimizable (ic))) &&
4190 ic->next && ic->next->op == IFX &&
4191 isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
4192 OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
4193 {
4194
4195 debugLog (" %d\n", __LINE__);
4196 OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
4197 continue;
4198 }
4199
4200 debugLog(" %d\n", __LINE__);
4201
4202 #ifndef NO_packRegsForSupport
4203 /* reduce for support function calls */
4204 if (ic->supportRtn || ic->op == '+' || ic->op == '-')
4205 packRegsForSupport (ic, ebp);
4206 #endif
4207
4208 /* if a parameter is passed, it's in W, so we may not
4209 need to place a copy in a register */
4210 if (ic->op == RECEIVE)
4211 packForReceive (ic, ebp);
4212
4213 #ifndef NO_packRegsForOneuse
4214 /* some cases the redundant moves can
4215 can be eliminated for return statements */
4216 if ((ic->op == RETURN || ic->op == SEND) &&
4217 !isOperandInFarSpace (IC_LEFT (ic)) &&
4218 !options.model)
4219 packRegsForOneuse (ic, IC_LEFT (ic), ebp);
4220 #endif
4221
4222 #ifndef NO_packRegsForOneuse
4223 /* if pointer set & left has a size more than
4224 one and right is not in far space */
4225 if (POINTER_SET (ic) &&
4226 !isOperandInFarSpace (IC_RIGHT (ic)) &&
4227 !OP_SYMBOL (IC_RESULT (ic))->remat &&
4228 !IS_OP_RUONLY (IC_RIGHT (ic)) &&
4229 getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
4230
4231 packRegsForOneuse (ic, IC_RESULT (ic), ebp);
4232 #endif
4233
4234 #ifndef NO_packRegsForOneuse
4235 /* if pointer get */
4236 if (POINTER_GET (ic) &&
4237 !isOperandInFarSpace (IC_RESULT (ic)) &&
4238 !OP_SYMBOL (IC_LEFT (ic))->remat &&
4239 !IS_OP_RUONLY (IC_RESULT (ic)) &&
4240 getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
4241
4242 packRegsForOneuse (ic, IC_LEFT (ic), ebp);
4243 debugLog("%d - return from packRegsForOneuse\n", __LINE__);
4244 #endif
4245
4246 #ifndef NO_cast_peep
4247 /* if this is cast for intergral promotion then
4248 check if only use of the definition of the
4249 operand being casted/ if yes then replace
4250 the result of that arithmetic operation with
4251 this result and get rid of the cast */
4252 if (ic->op == CAST) {
4253
4254 sym_link *fromType = operandType (IC_RIGHT (ic));
4255 sym_link *toType = operandType (IC_LEFT (ic));
4256
4257 debugLog (" %d - casting\n", __LINE__);
4258
4259 if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
4260 getSize (fromType) != getSize (toType)) {
4261
4262
4263 iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
4264 if (dic) {
4265
4266 if (IS_ARITHMETIC_OP (dic)) {
4267 debugLog(" %d %s\n", __LINE__, __FUNCTION__ );
4268
4269 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
4270 IC_RESULT (dic) = IC_RESULT (ic);
4271 remiCodeFromeBBlock (ebp, ic);
4272 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
4273 hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
4274 OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
4275 ic = ic->prev;
4276 } else
4277
4278 OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
4279 }
4280 } else {
4281
4282 /* if the type from and type to are the same
4283 then if this is the only use then packit */
4284 if (compareType (operandType (IC_RIGHT (ic)),
4285 operandType (IC_LEFT (ic))) == 1) {
4286
4287 iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
4288 if (dic) {
4289
4290 debugLog(" %d\n", __LINE__);
4291
4292 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
4293 IC_RESULT (dic) = IC_RESULT (ic);
4294 bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
4295 remiCodeFromeBBlock (ebp, ic);
4296 hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
4297 OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
4298 ic = ic->prev;
4299 }
4300 }
4301 }
4302 }
4303 #endif
4304
4305 #if 1
4306 /* there are some problems with packing variables
4307 * it seems that the live range estimator doesn't
4308 * estimate correctly the liveranges of some symbols */
4309
4310 /* pack for PUSH
4311 iTempNN := (some variable in farspace) V1
4312 push iTempNN ;
4313 -------------
4314 push V1
4315 */
4316 if (ic->op == IPUSH)
4317 {
4318 packForPush (ic, ebp);
4319 }
4320 #endif
4321
4322 #ifndef NO_packRegsForAccUse
4323 /* pack registers for accumulator use, when the
4324 result of an arithmetic or bit wise operation
4325 has only one use, that use is immediately following
4326 the defintion and the using iCode has only one
4327 operand or has two operands but one is literal &
4328 the result of that operation is not on stack then
4329 we can leave the result of this operation in acc:b
4330 combination */
4331 if ((IS_ARITHMETIC_OP (ic)
4332
4333 || IS_BITWISE_OP (ic)
4334
4335 || ic->op == LEFT_OP || ic->op == RIGHT_OP
4336
4337 ) &&
4338 IS_ITEMP (IC_RESULT (ic)) &&
4339 getSize (operandType (IC_RESULT (ic))) <= 1)
4340
4341 packRegsForAccUse (ic);
4342 #endif
4343
4344 }
4345 }
4346
4347 static void
4348 dumpEbbsToDebug (eBBlock ** ebbs, int count)
4349 {
4350 int i;
4351
4352 if (!pic16_ralloc_debug || !debugF)
4353 return;
4354
4355 for (i = 0; i < count; i++)
4356 {
4357 fprintf (debugF, "\n----------------------------------------------------------------\n");
4358 fprintf (debugF, "Basic Block %s : loop Depth = %d noPath = %d , lastinLoop = %d\n",
4359 ebbs[i]->entryLabel->name,
4360 ebbs[i]->depth,
4361 ebbs[i]->noPath,
4362 ebbs[i]->isLastInLoop);
4363 fprintf (debugF, "depth 1st num %d : bbnum = %d 1st iCode = %d , last iCode = %d\n",
4364 ebbs[i]->dfnum,
4365 ebbs[i]->bbnum,
4366 ebbs[i]->fSeq,
4367 ebbs[i]->lSeq);
4368 fprintf (debugF, "visited %d : hasFcall = %d\n",
4369 ebbs[i]->visited,
4370 ebbs[i]->hasFcall);
4371
4372 fprintf (debugF, "\ndefines bitVector :");
4373 bitVectDebugOn (ebbs[i]->defSet, debugF);
4374 fprintf (debugF, "\nlocal defines bitVector :");
4375 bitVectDebugOn (ebbs[i]->ldefs, debugF);
4376 fprintf (debugF, "\npointers Set bitvector :");
4377 bitVectDebugOn (ebbs[i]->ptrsSet, debugF);
4378 fprintf (debugF, "\nin pointers Set bitvector :");
4379 bitVectDebugOn (ebbs[i]->inPtrsSet, debugF);
4380 fprintf (debugF, "\ninDefs Set bitvector :");
4381 bitVectDebugOn (ebbs[i]->inDefs, debugF);
4382 fprintf (debugF, "\noutDefs Set bitvector :");
4383 bitVectDebugOn (ebbs[i]->outDefs, debugF);
4384 fprintf (debugF, "\nusesDefs Set bitvector :");
4385 bitVectDebugOn (ebbs[i]->usesDefs, debugF);
4386 fprintf (debugF, "\n----------------------------------------------------------------\n");
4387 printiCChain (ebbs[i]->sch, debugF);
4388 }
4389 }
4390
4391 void dbg_dumpregusage(void);
4392
4393 /*-----------------------------------------------------------------*/
4394 /* pic16_assignRegisters - assigns registers to each live range as need */
4395 /*-----------------------------------------------------------------*/
4396 void
4397 pic16_assignRegisters (ebbIndex * ebbi)
4398 {
4399 eBBlock ** ebbs = ebbi->bbOrder;
4400 int count = ebbi->count;
4401 iCode *ic;
4402 int i;
4403
4404 debugLog ("<><><><><><><><><><><><><><><><><>\nstarting\t%s:%s", __FILE__, __FUNCTION__);
4405 debugLog ("\nebbs before optimizing:\n");
4406 dumpEbbsToDebug (ebbs, count);
4407
4408 _inRegAllocator = 1;
4409
4410 pic16_freeAllRegs();
4411 #if 0
4412 dbg_dumpregusage();
4413 /* clear whats left over from peephole parser */
4414 pic16_dynAllocRegs= newSet(); //NULL;
4415 // pic16_dynStackRegs= newSet(); //NULL;
4416 // pic16_dynProcessorRegs=newSet(); //NULL;
4417 // pic16_dynDirectRegs=newSet(); //NULL;
4418 // pic16_dynDirectBitRegs=newSet(); //NULL;
4419 // pic16_dynInternalRegs=newSet(); //NULL;
4420 // pic16_dynAccessRegs=newSet(); //NULL;
4421
4422 // dynDirectRegNames=NULL;
4423 dynAllocRegNames=NULL;
4424 // dynProcRegNames=NULL;
4425 // dynAccessRegNames=NULL;
4426 #endif
4427
4428 setToNull ((void *) &_G.funcrUsed);
4429 pic16_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
4430
4431
4432 /* change assignments this will remove some
4433 live ranges reducing some register pressure */
4434 for (i = 0; i < count; i++)
4435 pic16_packRegisters (ebbs[i]);
4436
4437
4438 if (0)
4439 {
4440 reg_info *reg;
4441 int hkey;
4442
4443 debugLog("dir registers allocated so far:\n");
4444 reg = hTabFirstItem(dynDirectRegNames, &hkey);
4445
4446 while(reg) {
4447 debugLog(" -- #%d reg = %s key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
4448 // fprintf(stderr, " -- #%d reg = %s key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
4449 reg = hTabNextItem(dynDirectRegNames, &hkey);
4450 }
4451 }
4452
4453 /* liveranges probably changed by register packing
4454 so we compute them again */
4455 recomputeLiveRanges (ebbs, count, FALSE);
4456
4457 if (options.dump_i_code)
4458 dumpEbbsToFileExt (DUMP_PACK, ebbi);
4459
4460 /* first determine for each live range the number of
4461 registers & the type of registers required for each */
4462 regTypeNum ();
4463
4464 /* start counting function temporary registers from zero */
4465 /* XXX: Resetting dynrIdx breaks register allocation,
4466 * see #1489055, #1483693 (?), and #1445850! */
4467 //dynrIdx = 0;
4468
4469 /* and serially allocate registers */
4470 serialRegAssign (ebbs, count);
4471
4472 #if 0
4473 debugLog ("ebbs after serialRegAssign:\n");
4474 dumpEbbsToDebug (ebbs, count);
4475 #endif
4476
4477 //pic16_freeAllRegs();
4478
4479 /* if stack was extended then tell the user */
4480 if (_G.stackExtend)
4481 {
4482 /* werror(W_TOOMANY_SPILS,"stack", */
4483 /* _G.stackExtend,currFunc->name,""); */
4484 _G.stackExtend = 0;
4485 }
4486
4487 if (_G.dataExtend)
4488 {
4489 /* werror(W_TOOMANY_SPILS,"data space", */
4490 /* _G.dataExtend,currFunc->name,""); */
4491 _G.dataExtend = 0;
4492 }
4493
4494 /* after that create the register mask
4495 for each of the instruction */
4496 createRegMask (ebbs, count);
4497
4498 /* redo that offsets for stacked automatic variables */
4499 redoStackOffsets ();
4500
4501 if (options.dump_i_code)
4502 dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
4503
4504 // dumpLR(ebbs, count);
4505
4506 /* now get back the chain */
4507 ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
4508
4509 debugLog ("ebbs after optimizing:\n");
4510 dumpEbbsToDebug (ebbs, count);
4511
4512
4513 _inRegAllocator = 0;
4514
4515 genpic16Code (ic);
4516
4517 /* free up any _G.stackSpil locations allocated */
4518 applyToSet (_G.stackSpil, deallocStackSpil);
4519 _G.slocNum = 0;
4520 setToNull ((void *) &_G.stackSpil);
4521 setToNull ((void *) &_G.spiltSet);
4522 /* mark all registers as free */
4523 pic16_freeAllRegs ();
4524
4525
4526 debugLog ("leaving\n<><><><><><><><><><><><><><><><><>\n");
4527 debugLogClose ();
4528 return;
4529 }
4530