/*------------------------------------------------------------------------
SDCCralloc.c - source file for register allocation. (8051) specific
-
- Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
- Added Pic Port T.scott Dattalo scott@dattalo.com (2000)
-
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by the
- Free Software Foundation; either version 2, or (at your option) any
- later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- In other words, you are welcome to use, share and improve this program.
- You are forbidden to forbid anyone else to use, share and improve
- what you give them. Help stamp out software-hoarding!
+
+ Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
+ Added Pic Port T.scott Dattalo scott@dattalo.com (2000)
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ In other words, you are welcome to use, share and improve this program.
+ You are forbidden to forbid anyone else to use, share and improve
+ what you give them. Help stamp out software-hoarding!
-------------------------------------------------------------------------*/
#include "common.h"
#include "ralloc.h"
+#include "device.h"
#include "pcode.h"
#include "gen.h"
+
+#if defined(__BORLANDC__) || defined(_MSC_VER)
+#define STRCASECMP stricmp
+#define FENTRY2 1 ? (void)0 : printf
+#else
+#define STRCASECMP strcasecmp
+//#define FENTRY2(fmt,...) do { fprintf (stderr, "%s:%d: called.\n", __FUNCTION__, __LINE__); fprintf (stderr, fmt, ## __VA_ARGS__); } while (0)
+#define FENTRY2 1 ? (void)0 : printf
+#endif
+
+/* this should go in SDCCicode.h, but it doesn't. */
+#define IS_REF(op) (IS_SYMOP(op) && op->operand.symOperand->isref == 1)
+
/*-----------------------------------------------------------------*/
/* At this point we start getting processor specific although */
/* some routines are non-processor specific & can be reused when */
/*-----------------------------------------------------------------*/
extern void genpic14Code (iCode *);
+extern void pic14_assignConfigWordValue(int address, int value);
/* Global data */
static struct
- {
- bitVect *spiltSet;
- set *stackSpil;
- bitVect *regAssigned;
- short blockSpil;
- int slocNum;
- bitVect *funcrUsed; /* registers used in a function */
- int stackExtend;
- int dataExtend;
- }
+{
+ bitVect *spiltSet;
+ set *stackSpil;
+ bitVect *regAssigned;
+ short blockSpil;
+ int slocNum;
+ bitVect *funcrUsed; /* registers used in a function */
+ int stackExtend;
+ int dataExtend;
+}
_G;
/* Shared with gen.c */
int pic14_ptrRegReq; /* one byte pointer register required */
-/* pic14 registers */
-/* A nasty, awful, disgusting hack for register declarations */
-#ifdef p16c84
-
-regs regspic14[] =
-{
-
- {REG_GPR, PO_GPR_TEMP, 0x0C, "r0x0C", "r0x0C", 0x0C, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x0D, "r0x0D", "r0x0C", 0x0D, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x0E, "r0x0E", "r0x0C", 0x0E, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x0F, "r0x0F", "r0x0C", 0x0F, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x10, "r0x10", "r0x10", 0x10, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x11, "r0x11", "r0x11", 0x11, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x12, "r0x12", "r0x12", 0x12, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x13, "r0x13", "r0x13", 0x13, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x14, "r0x14", "r0x14", 0x14, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x15, "r0x15", "r0x15", 0x15, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x16, "r0x16", "r0x16", 0x16, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x17, "r0x17", "r0x17", 0x17, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x18, "r0x18", "r0x18", 0x18, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x19, "r0x19", "r0x19", 0x19, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x1A, "r0x1A", "r0x1A", 0x1A, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x1B, "r0x1B", "r0x1B", 0x1B, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x1C, "r0x1C", "r0x1C", 0x1C, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x1D, "r0x1D", "r0x1D", 0x1D, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x1E, "r0x1E", "r0x1E", 0x1E, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x1F, "r0x1F", "r0x1F", 0x1F, 1, 0},
- {REG_PTR, PO_FSR, 4, "FSR", "FSR", 4, 1, 0},
-
-};
-#else
-int Gstack_base_addr=0x38; /* The starting address of registers that
- * are used to pass and return parameters */
-regs regspic14[] =
-{
- {REG_GPR, PO_GPR_TEMP, 0x20, "r0x20", "r0x20", 0x20, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x21, "r0x21", "r0x21", 0x21, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x22, "r0x22", "r0x22", 0x22, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x23, "r0x23", "r0x23", 0x23, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x24, "r0x24", "r0x24", 0x24, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x25, "r0x25", "r0x25", 0x25, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x26, "r0x26", "r0x26", 0x26, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x27, "r0x27", "r0x27", 0x27, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x28, "r0x28", "r0x28", 0x28, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x29, "r0x29", "r0x29", 0x29, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x2A, "r0x2A", "r0x2A", 0x2A, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x2B, "r0x2B", "r0x2B", 0x2B, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x2C, "r0x2C", "r0x2C", 0x2C, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x2D, "r0x2D", "r0x2D", 0x2D, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x2E, "r0x2E", "r0x2E", 0x2E, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x2F, "r0x2F", "r0x2F", 0x2F, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x30, "r0x30", "r0x30", 0x30, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x31, "r0x31", "r0x31", 0x31, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x32, "r0x32", "r0x32", 0x32, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x33, "r0x33", "r0x33", 0x33, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x34, "r0x34", "r0x34", 0x34, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x35, "r0x35", "r0x35", 0x35, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x36, "r0x36", "r0x36", 0x36, 1, 0},
- {REG_GPR, PO_GPR_TEMP, 0x37, "r0x37", "r0x37", 0x37, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x38, "r0x38", "r0x38", 0x38, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x39, "r0x39", "r0x39", 0x39, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x3A, "r0x3A", "r0x3A", 0x3A, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x3B, "r0x3B", "r0x3B", 0x3B, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x3C, "r0x3C", "r0x3C", 0x3C, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x3D, "r0x3D", "r0x3D", 0x3D, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x3E, "r0x3E", "r0x3E", 0x3E, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x3F, "r0x3F", "r0x3F", 0x3F, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x40, "r0x40", "r0x40", 0x40, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x41, "r0x41", "r0x41", 0x41, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x42, "r0x42", "r0x42", 0x42, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x43, "r0x43", "r0x43", 0x43, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x44, "r0x44", "r0x44", 0x44, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x45, "r0x45", "r0x45", 0x45, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x46, "r0x46", "r0x46", 0x46, 1, 0},
- {REG_STK, PO_GPR_TEMP, 0x47, "r0x47", "r0x47", 0x47, 1, 0},
-
- {REG_PTR, PO_FSR, 4, "FSR", "FSR", 4, 1, 0},
-
-};
+set *dynAllocRegs=NULL;
+set *dynStackRegs=NULL;
+set *dynProcessorRegs=NULL;
+set *dynDirectRegs=NULL;
+set *dynDirectBitRegs=NULL;
+set *dynInternalRegs=NULL;
+
+static hTab *dynDirectRegNames= NULL;
+// static hTab *regHash = NULL; /* a hash table containing ALL registers */
+
+static int dynrIdx = 0x1000;
+
+int pic14_nRegs = 128; // = sizeof (regspic14) / sizeof (regs);
+
+int Gstack_base_addr=0; /* The starting address of registers that
+ * are used to pass and return parameters */
+int Gstack_size = 0;
+
+
-#endif
-int pic14_nRegs = sizeof (regspic14) / sizeof (regs);
static void spillThis (symbol *);
static int debug = 1;
static FILE *debugF = NULL;
/*-----------------------------------------------------------------*/
//static void debugLog(char *inst,char *fmt, ...)
static void
-debugLog (char *fmt,...)
+ debugLog (char *fmt,...)
{
- static int append = 0; // First time through, open the file without append.
-
- char buffer[256];
- //char *bufferP=buffer;
- va_list ap;
+ static int append = 0; // First time through, open the file without append.
- if (!debug || !srcFileName)
- return;
+ char buffer[256];
+ //char *bufferP=buffer;
+ va_list ap;
+ if (!debug || !dstFileName)
+ return;
- if (!debugF)
- {
- /* create the file name */
- strcpy (buffer, srcFileName);
- strcat (buffer, ".d");
- if (!(debugF = fopen (buffer, (append ? "a+" : "w"))))
+ if (!debugF)
{
- werror (E_FILE_OPEN_ERR, buffer);
- exit (1);
- }
- append = 1; // Next time debubLog is called, we'll append the debug info
+ /* create the file name */
+ strcpy (buffer, dstFileName);
+ strcat (buffer, ".d");
+
+ if (!(debugF = fopen (buffer, (append ? "a+" : "w"))))
+ {
+ werror (E_FILE_OPEN_ERR, buffer);
+ exit (1);
+ }
+ append = 1; // Next time debubLog is called, we'll append the debug info
- }
+ }
- va_start (ap, fmt);
+ va_start (ap, fmt);
- vsprintf (buffer, fmt, ap);
+ vsprintf (buffer, fmt, ap);
- fprintf (debugF, "%s", buffer);
-/*
- while (isspace(*bufferP)) bufferP++;
+ fprintf (debugF, "%s", buffer);
+ //if (options.verbose) fprintf (stderr, "%s: %s", __FUNCTION__, buffer);
+ /*
+ while (isspace((unsigned char)*bufferP)) bufferP++;
- if (bufferP && *bufferP)
- lineCurr = (lineCurr ?
- connectLine(lineCurr,newLineNode(lb)) :
- (lineHead = newLineNode(lb)));
- lineCurr->isInline = _G.inLine;
- lineCurr->isDebug = _G.debugLine;
- */
- va_end (ap);
+ if (bufferP && *bufferP)
+ lineCurr = (lineCurr ?
+ connectLine(lineCurr,newLineNode(lb)) :
+ (lineHead = newLineNode(lb)));
+ lineCurr->isInline = _G.inLine;
+ lineCurr->isDebug = _G.debugLine;
+ */
+ va_end (ap);
}
-
+
static void
-debugNewLine (void)
+ debugNewLine (void)
{
- if (debugF)
- fputc ('\n', debugF);
+ if (debugF)
+ fputc ('\n', debugF);
}
-/*-----------------------------------------------------------------*/
-/* debugLogClose - closes the debug log file (if opened) */
-/*-----------------------------------------------------------------*/
+ /*-----------------------------------------------------------------*/
+ /* debugLogClose - closes the debug log file (if opened) */
+ /*-----------------------------------------------------------------*/
static void
-debugLogClose (void)
+ debugLogClose (void)
{
- if (debugF)
- {
- fclose (debugF);
- debugF = NULL;
- }
+ if (debugF)
+ {
+ fclose (debugF);
+ debugF = NULL;
+ }
}
#define AOP(op) op->aop
-
+
static char *
-debugAopGet (char *str, operand * op)
+ debugAopGet (char *str, operand * op)
{
- if (str)
- debugLog (str);
+ if (str)
+ debugLog (str);
- printOperand (op, debugF);
- debugNewLine ();
+ printOperand (op, debugF);
+ debugNewLine ();
- return NULL;
+ return NULL;
}
static char *
-decodeOp (unsigned int op)
-{
-
- if (op < 128 && op > ' ')
- {
- buffer[0] = (op & 0xff);
- buffer[1] = 0;
- return buffer;
- }
-
- switch (op)
- {
- case IDENTIFIER:
- return "IDENTIFIER";
- case TYPE_NAME:
- return "TYPE_NAME";
- case CONSTANT:
- return "CONSTANT";
- case STRING_LITERAL:
- return "STRING_LITERAL";
- case SIZEOF:
- return "SIZEOF";
- case PTR_OP:
- return "PTR_OP";
- case INC_OP:
- return "INC_OP";
- case DEC_OP:
- return "DEC_OP";
- case LEFT_OP:
- return "LEFT_OP";
- case RIGHT_OP:
- return "RIGHT_OP";
- case LE_OP:
- return "LE_OP";
- case GE_OP:
- return "GE_OP";
- case EQ_OP:
- return "EQ_OP";
- case NE_OP:
- return "NE_OP";
- case AND_OP:
- return "AND_OP";
- case OR_OP:
- return "OR_OP";
- case MUL_ASSIGN:
- return "MUL_ASSIGN";
- case DIV_ASSIGN:
- return "DIV_ASSIGN";
- case MOD_ASSIGN:
- return "MOD_ASSIGN";
- case ADD_ASSIGN:
- return "ADD_ASSIGN";
- case SUB_ASSIGN:
- return "SUB_ASSIGN";
- case LEFT_ASSIGN:
- return "LEFT_ASSIGN";
- case RIGHT_ASSIGN:
- return "RIGHT_ASSIGN";
- case AND_ASSIGN:
- return "AND_ASSIGN";
- case XOR_ASSIGN:
- return "XOR_ASSIGN";
- case OR_ASSIGN:
- return "OR_ASSIGN";
- case TYPEDEF:
- return "TYPEDEF";
- case EXTERN:
- return "EXTERN";
- case STATIC:
- return "STATIC";
- case AUTO:
- return "AUTO";
- case REGISTER:
- return "REGISTER";
- case CODE:
- return "CODE";
- case EEPROM:
- return "EEPROM";
- case INTERRUPT:
- return "INTERRUPT";
- case SFR:
- return "SFR";
- case AT:
- return "AT";
- case SBIT:
- return "SBIT";
- case REENTRANT:
- return "REENTRANT";
- case USING:
- return "USING";
- case XDATA:
- return "XDATA";
- case DATA:
- return "DATA";
- case IDATA:
- return "IDATA";
- case PDATA:
- return "PDATA";
- case VAR_ARGS:
- return "VAR_ARGS";
- case CRITICAL:
- return "CRITICAL";
- case NONBANKED:
- return "NONBANKED";
- case BANKED:
- return "BANKED";
- case CHAR:
- return "CHAR";
- case SHORT:
- return "SHORT";
- case INT:
- return "INT";
- case LONG:
- return "LONG";
- case SIGNED:
- return "SIGNED";
- case UNSIGNED:
- return "UNSIGNED";
- case FLOAT:
- return "FLOAT";
- case DOUBLE:
- return "DOUBLE";
- case CONST:
- return "CONST";
- case VOLATILE:
- return "VOLATILE";
- case VOID:
- return "VOID";
- case BIT:
- return "BIT";
- case STRUCT:
- return "STRUCT";
- case UNION:
- return "UNION";
- case ENUM:
- return "ENUM";
- case ELIPSIS:
- return "ELIPSIS";
- case RANGE:
- return "RANGE";
- case FAR:
- return "FAR";
- case CASE:
- return "CASE";
- case DEFAULT:
- return "DEFAULT";
- case IF:
- return "IF";
- case ELSE:
- return "ELSE";
- case SWITCH:
- return "SWITCH";
- case WHILE:
- return "WHILE";
- case DO:
- return "DO";
- case FOR:
- return "FOR";
- case GOTO:
- return "GOTO";
- case CONTINUE:
- return "CONTINUE";
- case BREAK:
- return "BREAK";
- case RETURN:
- return "RETURN";
- case INLINEASM:
- return "INLINEASM";
- case IFX:
- return "IFX";
- case ADDRESS_OF:
- return "ADDRESS_OF";
- case GET_VALUE_AT_ADDRESS:
- return "GET_VALUE_AT_ADDRESS";
- case SPIL:
- return "SPIL";
- case UNSPIL:
- return "UNSPIL";
- case GETHBIT:
- return "GETHBIT";
- case BITWISEAND:
- return "BITWISEAND";
- case UNARYMINUS:
- return "UNARYMINUS";
- case IPUSH:
- return "IPUSH";
- case IPOP:
- return "IPOP";
- case PCALL:
- return "PCALL";
- case ENDFUNCTION:
- return "ENDFUNCTION";
- case JUMPTABLE:
- return "JUMPTABLE";
- case RRC:
- return "RRC";
- case RLC:
- return "RLC";
- case CAST:
- return "CAST";
- case CALL:
- return "CALL";
- case PARAM:
- return "PARAM ";
- case NULLOP:
- return "NULLOP";
- case BLOCK:
- return "BLOCK";
- case LABEL:
- return "LABEL";
- case RECEIVE:
- return "RECEIVE";
- case SEND:
- return "SEND";
- }
- sprintf (buffer, "unkown op %d %c", op, op & 0xff);
- return buffer;
+ decodeOp (unsigned int op)
+{
+
+ if (op < 128 && op > ' ')
+ {
+ buffer[0] = (op & 0xff);
+ buffer[1] = 0;
+ return buffer;
+ }
+
+ switch (op)
+ {
+ case IDENTIFIER: return "IDENTIFIER";
+ case TYPE_NAME: return "TYPE_NAME";
+ case CONSTANT: return "CONSTANT";
+ case STRING_LITERAL: return "STRING_LITERAL";
+ case SIZEOF: return "SIZEOF";
+ case PTR_OP: return "PTR_OP";
+ case INC_OP: return "INC_OP";
+ case DEC_OP: return "DEC_OP";
+ case LEFT_OP: return "LEFT_OP";
+ case RIGHT_OP: return "RIGHT_OP";
+ case LE_OP: return "LE_OP";
+ case GE_OP: return "GE_OP";
+ case EQ_OP: return "EQ_OP";
+ case NE_OP: return "NE_OP";
+ case AND_OP: return "AND_OP";
+ case OR_OP: return "OR_OP";
+ case MUL_ASSIGN: return "MUL_ASSIGN";
+ case DIV_ASSIGN: return "DIV_ASSIGN";
+ case MOD_ASSIGN: return "MOD_ASSIGN";
+ case ADD_ASSIGN: return "ADD_ASSIGN";
+ case SUB_ASSIGN: return "SUB_ASSIGN";
+ case LEFT_ASSIGN: return "LEFT_ASSIGN";
+ case RIGHT_ASSIGN: return "RIGHT_ASSIGN";
+ case AND_ASSIGN: return "AND_ASSIGN";
+ case XOR_ASSIGN: return "XOR_ASSIGN";
+ case OR_ASSIGN: return "OR_ASSIGN";
+ case TYPEDEF: return "TYPEDEF";
+ case EXTERN: return "EXTERN";
+ case STATIC: return "STATIC";
+ case AUTO: return "AUTO";
+ case REGISTER: return "REGISTER";
+ case CODE: return "CODE";
+ case EEPROM: return "EEPROM";
+ case INTERRUPT: return "INTERRUPT";
+ case SFR: return "SFR";
+ case AT: return "AT";
+ case SBIT: return "SBIT";
+ case REENTRANT: return "REENTRANT";
+ case USING: return "USING";
+ case XDATA: return "XDATA";
+ case DATA: return "DATA";
+ case IDATA: return "IDATA";
+ case PDATA: return "PDATA";
+ case VAR_ARGS: return "VAR_ARGS";
+ case CRITICAL: return "CRITICAL";
+ case NONBANKED: return "NONBANKED";
+ case BANKED: return "BANKED";
+ case CHAR: return "CHAR";
+ case SHORT: return "SHORT";
+ case INT: return "INT";
+ case LONG: return "LONG";
+ case SIGNED: return "SIGNED";
+ case UNSIGNED: return "UNSIGNED";
+ case FLOAT: return "FLOAT";
+ case DOUBLE: return "DOUBLE";
+ case CONST: return "CONST";
+ case VOLATILE: return "VOLATILE";
+ case VOID: return "VOID";
+ case BIT: return "BIT";
+ case STRUCT: return "STRUCT";
+ case UNION: return "UNION";
+ case ENUM: return "ENUM";
+ case ELIPSIS: return "ELIPSIS";
+ case RANGE: return "RANGE";
+ case FAR: return "FAR";
+ case CASE: return "CASE";
+ case DEFAULT: return "DEFAULT";
+ case IF: return "IF";
+ case ELSE: return "ELSE";
+ case SWITCH: return "SWITCH";
+ case WHILE: return "WHILE";
+ case DO: return "DO";
+ case FOR: return "FOR";
+ case GOTO: return "GOTO";
+ case CONTINUE: return "CONTINUE";
+ case BREAK: return "BREAK";
+ case RETURN: return "RETURN";
+ case INLINEASM: return "INLINEASM";
+ case IFX: return "IFX";
+ case ADDRESS_OF: return "ADDRESS_OF";
+ case GET_VALUE_AT_ADDRESS: return "GET_VALUE_AT_ADDRESS";
+ case SPIL: return "SPIL";
+ case UNSPIL: return "UNSPIL";
+ case GETHBIT: return "GETHBIT";
+ case BITWISEAND: return "BITWISEAND";
+ case UNARYMINUS: return "UNARYMINUS";
+ case IPUSH: return "IPUSH";
+ case IPOP: return "IPOP";
+ case PCALL: return "PCALL";
+ case ENDFUNCTION: return "ENDFUNCTION";
+ case JUMPTABLE: return "JUMPTABLE";
+ case RRC: return "RRC";
+ case RLC: return "RLC";
+ case CAST: return "CAST";
+ case CALL: return "CALL";
+ case PARAM: return "PARAM ";
+ case NULLOP: return "NULLOP";
+ case BLOCK: return "BLOCK";
+ case LABEL: return "LABEL";
+ case RECEIVE: return "RECEIVE";
+ case SEND: return "SEND";
+ }
+ sprintf (buffer, "unknown op %d %c", op, op & 0xff);
+ return buffer;
}
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
static char *
debugLogRegType (short type)
{
-
- switch (type)
- {
- case REG_GPR:
- return "REG_GPR";
- case REG_PTR:
- return "REG_PTR";
- case REG_CND:
- return "REG_CND";
- }
-
- sprintf (buffer, "unkown reg type %d", type);
- return buffer;
+
+ switch (type)
+ {
+ case REG_GPR: return "REG_GPR";
+ case REG_PTR: return "REG_PTR";
+ case REG_CND: return "REG_CND";
+ }
+
+ sprintf (buffer, "unknown reg type %d", type);
+ return buffer;
}
/*-----------------------------------------------------------------*/
-/* allocReg - allocates register of given type */
/*-----------------------------------------------------------------*/
-static regs *
-allocReg (short type)
+static int regname2key(char const *name)
{
- int i;
-
- debugLog ("%s of type %s\n", __FUNCTION__, debugLogRegType (type));
-
- for (i = 0; i < pic14_nRegs; i++)
- {
-
- /* if type is given as 0 then any
- free register will do */
- if (!type &&
- regspic14[i].isFree)
- {
- regspic14[i].isFree = 0;
- regspic14[i].wasUsed = 1;
- if (currFunc)
- currFunc->regsUsed =
- bitVectSetBit (currFunc->regsUsed, i);
- debugLog (" returning %s\n", regspic14[i].name);
- return ®spic14[i];
- }
- /* other wise look for specific type
- of register */
- if (regspic14[i].isFree &&
- regspic14[i].type == type)
- {
- regspic14[i].isFree = 0;
- regspic14[i].wasUsed = 1;
- if (currFunc)
- currFunc->regsUsed =
- bitVectSetBit (currFunc->regsUsed, i);
- debugLog (" returning %s\n", regspic14[i].name);
- return ®spic14[i];
+ int key = 0;
+
+ if(!name)
+ return 0;
+
+ while(*name) {
+
+ key += (*name++) + 1;
+
}
- }
- return NULL;
+
+ return ( (key + (key >> 4) + (key>>8)) & 0x3f);
+
}
+static regs *regWithIdx (set *dRegs, int idx, int fixed);
/*-----------------------------------------------------------------*/
-/* pic14_regWithIdx - returns pointer to register wit index number */
+/* newReg - allocate and init memory for a new register */
/*-----------------------------------------------------------------*/
-regs *
-pic14_regWithIdx (int idx)
+static regs* newReg(short type, PIC_OPTYPE pc_type, int rIdx, char *name, int size, int alias)
{
- int i;
-
- debugLog ("%s - requesting index = 0x%x\n", __FUNCTION__,idx);
-
- for (i = 0; i < pic14_nRegs; i++)
- if (regspic14[i].rIdx == idx)
- return ®spic14[i];
+
+ regs *dReg, *reg_alias;
- //return ®spic14[0];
- fprintf(stderr,"%s %d - requested register: 0x%x\n",__FUNCTION__,__LINE__,idx);
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "regWithIdx not found");
- exit (1);
+ /* check whether a matching register already exists */
+ dReg = dirregWithName( name );
+ if (dReg) {
+ //printf( "%s: already present: %s\n", __FUNCTION__, name );
+ return (dReg);
+ }
+
+ // check whether a register at that location exists
+ reg_alias = regWithIdx( dynDirectRegs, rIdx, 0 );
+ if (!reg_alias) reg_alias = regWithIdx( dynDirectRegs, rIdx, 1 );
+
+ // create a new register
+ dReg = Safe_calloc(1,sizeof(regs));
+ dReg->type = type;
+ dReg->pc_type = pc_type;
+ dReg->rIdx = rIdx;
+ if(name) {
+ dReg->name = Safe_strdup(name);
+ } else {
+ sprintf(buffer,"r0x%02X", dReg->rIdx);
+ dReg->name = Safe_strdup(buffer);
+ }
+ dReg->isFree = 0;
+ dReg->wasUsed = 0;
+ if (type == REG_SFR)
+ dReg->isFixed = 1;
+ else
+ dReg->isFixed = 0;
+
+ dReg->isMapped = 0;
+ dReg->isEmitted = 0;
+ dReg->isPublic = 0;
+ dReg->isExtern = 0;
+ dReg->address = 0;
+ dReg->size = size;
+ dReg->alias = alias;
+ dReg->reg_alias = reg_alias;
+ dReg->reglives.usedpFlows = newSet();
+ dReg->reglives.assignedpFlows = newSet();
+ if (type != REG_STK) hTabAddItem(&dynDirectRegNames, regname2key(dReg->name), dReg);
+ debugLog( "%s: Created register %s.\n", __FUNCTION__, dReg->name);
+
+ return dReg;
}
/*-----------------------------------------------------------------*/
+/* regWithIdx - Search through a set of registers that matches idx */
/*-----------------------------------------------------------------*/
-regs *
-pic14_findFreeReg(short type)
+static regs *
+regWithIdx (set *dRegs, int idx, int fixed)
{
- int i;
-
- for (i = 0; i < pic14_nRegs; i++) {
- if (!type && regspic14[i].isFree)
- return ®spic14[i];
- if (regspic14[i].isFree &&
- regspic14[i].type == type)
- return ®spic14[i];
- }
- return NULL;
+ regs *dReg;
+
+ for (dReg = setFirstItem(dRegs) ; dReg ;
+ dReg = setNextItem(dRegs)) {
+
+ if(idx == dReg->rIdx && (fixed == (int)dReg->isFixed)) {
+ while (dReg->reg_alias) dReg = dReg->reg_alias;
+ return dReg;
+ }
+ }
+
+ return NULL;
}
+
/*-----------------------------------------------------------------*/
-/* freeReg - frees a register */
+/* regWithName - Search through a set of registers that matches name */
/*-----------------------------------------------------------------*/
-static void
-freeReg (regs * reg)
+static regs *
+regWithName (set *dRegs, const char *name)
{
- debugLog ("%s\n", __FUNCTION__);
- reg->isFree = 1;
+ regs *dReg;
+
+ for (dReg = setFirstItem(dRegs) ; dReg ;
+ dReg = setNextItem(dRegs)) {
+
+ if((strcmp(name,dReg->name)==0)) {
+ return dReg;
+ }
+ }
+
+ return NULL;
}
-
/*-----------------------------------------------------------------*/
-/* nFreeRegs - returns number of free registers */
+/* regWithName - Search for a registers that matches name */
/*-----------------------------------------------------------------*/
-static int
-nFreeRegs (int type)
+regs *
+regFindWithName (const char *name)
{
- int i;
- int nfr = 0;
-
- debugLog ("%s\n", __FUNCTION__);
- for (i = 0; i < pic14_nRegs; i++)
- if (regspic14[i].isFree && regspic14[i].type == type)
- nfr++;
- return nfr;
+ regs *dReg;
+
+ if( (dReg = regWithName ( dynDirectRegs, name)) != NULL ) {
+ debugLog ("Found a Direct Register!\n");
+ return dReg;
+ }
+ if( (dReg = regWithName ( dynDirectBitRegs, name)) != NULL) {
+ debugLog ("Found a Direct Bit Register!\n");
+ return dReg;
+ }
+
+ if (*name=='_') name++; // Step passed '_'
+
+ if( (dReg = regWithName ( dynAllocRegs, name)) != NULL) {
+ debugLog ("Found a Dynamic Register!\n");
+ return dReg;
+ }
+ if( (dReg = regWithName ( dynProcessorRegs, name)) != NULL) {
+ debugLog ("Found a Processor Register!\n");
+ return dReg;
+ }
+ if( (dReg = regWithName ( dynInternalRegs, name)) != NULL) {
+ debugLog ("Found an Internal Register!\n");
+ return dReg;
+ }
+ if( (dReg = regWithName ( dynStackRegs, name)) != NULL) {
+ debugLog ("Found an Stack Register!\n");
+ return dReg;
+ }
+
+ return NULL;
}
/*-----------------------------------------------------------------*/
-/* nfreeRegsType - free registers with type */
+/* regFindFree - Search for a free register in a set of registers */
/*-----------------------------------------------------------------*/
-static int
-nfreeRegsType (int type)
+static regs *
+regFindFree (set *dRegs)
{
- int nfr;
- debugLog ("%s\n", __FUNCTION__);
- if (type == REG_PTR)
- {
- if ((nfr = nFreeRegs (type)) == 0)
- return nFreeRegs (REG_GPR);
- }
-
- return nFreeRegs (type);
+ regs *dReg;
+
+ for (dReg = setFirstItem(dRegs) ; dReg ;
+ dReg = setNextItem(dRegs)) {
+
+ if(dReg->isFree)
+ return dReg;
+ }
+
+ return NULL;
}
-
-
/*-----------------------------------------------------------------*/
-/* allDefsOutOfRange - all definitions are out of a range */
+/* initStack - allocate registers for a pseudo stack */
/*-----------------------------------------------------------------*/
-static bool
-allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
+void initStack(int base_address, int size, int shared)
{
- int i;
-
- debugLog ("%s\n", __FUNCTION__);
- if (!defs)
- return TRUE;
-
- for (i = 0; i < defs->size; i++)
- {
- iCode *ic;
+
+ int i;
+ PIC_device *pic;
- if (bitVectBitValue (defs, i) &&
- (ic = hTabItemWithKey (iCodehTab, i)) &&
- (ic->seq >= fseq && ic->seq <= toseq))
+ pic = pic14_getPIC();
+ Gstack_base_addr = base_address;
+ Gstack_size = size;
+ //fprintf(stderr,"initStack [base:0x%02x, size:%d]\n", base_address, size);
+
+ for(i = 0; i<size; i++) {
+ char buffer[16];
+ regs *r;
+ SNPRINTF(&buffer[0], 16, "STK%02d", i);
+ // multi-bank device, sharebank prohibited by user
+ r = newReg(REG_STK, PO_GPR_TEMP, base_address--, buffer, 1, shared ? (pic ? pic->bankMask : 0x180) : 0x0);
+ r->isFixed = 1;
+ r->isPublic = 1;
+ r->isEmitted = 1;
+ //r->name[0] = 's';
+ addSet(&dynStackRegs,r);
+ }
+}
- return FALSE;
+/*-----------------------------------------------------------------*
+*-----------------------------------------------------------------*/
+regs *
+allocProcessorRegister(int rIdx, char * name, short po_type, int alias)
+{
+
+ //fprintf(stderr,"allocProcessorRegister %s addr =0x%x\n",name,rIdx);
+ return addSet(&dynProcessorRegs,newReg(REG_SFR, po_type, rIdx, name,1,alias));
+}
- }
+/*-----------------------------------------------------------------*
+*-----------------------------------------------------------------*/
- return TRUE;
+regs *
+allocInternalRegister(int rIdx, char * name, PIC_OPTYPE po_type, int alias)
+{
+ regs * reg = newReg(REG_GPR, po_type, rIdx, name,1,alias);
+
+ //fprintf(stderr,"allocInternalRegister %s addr =0x%x\n",name,rIdx);
+ if(reg) {
+ reg->wasUsed = 0;
+ return addSet(&dynInternalRegs,reg);
+ }
+
+ return NULL;
}
-
/*-----------------------------------------------------------------*/
-/* computeSpillable - given a point find the spillable live ranges */
+/* allocReg - allocates register of given type */
/*-----------------------------------------------------------------*/
-static bitVect *
-computeSpillable (iCode * ic)
+static regs *
+allocReg (short type)
{
- bitVect *spillable;
-
- debugLog ("%s\n", __FUNCTION__);
- /* spillable live ranges are those that are live at this
- point . the following categories need to be subtracted
- from this set.
- a) - those that are already spilt
- b) - if being used by this one
- c) - defined by this one */
+ regs *reg;
+
+ debugLog ("%s of type %s\n", __FUNCTION__, debugLogRegType (type));
+ //fprintf(stderr,"allocReg\n");
+
+ reg = pic14_findFreeReg (type);
- spillable = bitVectCopy (ic->rlive);
- spillable =
- bitVectCplAnd (spillable, _G.spiltSet); /* those already spilt */
- spillable =
- bitVectCplAnd (spillable, ic->uses); /* used in this one */
- bitVectUnSetBit (spillable, ic->defKey);
- spillable = bitVectIntersect (spillable, _G.regAssigned);
- return spillable;
+ reg->isFree = 0;
+ reg->wasUsed = 1;
+ return reg;
+
+
+ //return addSet(&dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0));
+
}
+
/*-----------------------------------------------------------------*/
-/* noSpilLoc - return true if a variable has no spil location */
+/* dirregWithName - search for register by name */
/*-----------------------------------------------------------------*/
-static int
-noSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
+regs *
+dirregWithName (char *name)
{
- debugLog ("%s\n", __FUNCTION__);
- return (sym->usl.spillLoc ? 0 : 1);
+ int hkey;
+ regs *reg;
+
+ if(!name)
+ return NULL;
+
+ /* hash the name to get a key */
+
+ hkey = regname2key(name);
+
+ reg = hTabFirstItemWK(dynDirectRegNames, hkey);
+
+ while(reg) {
+
+ if(STRCASECMP(reg->name, name) == 0) {
+ // handle registers with multiple names
+ while (reg->reg_alias) reg = reg->reg_alias;
+ return(reg);
+ }
+
+ reg = hTabNextItemWK (dynDirectRegNames);
+
+ }
+
+ return NULL; // name wasn't found in the hash table
}
-/*-----------------------------------------------------------------*/
-/* hasSpilLoc - will return 1 if the symbol has spil location */
-/*-----------------------------------------------------------------*/
-static int
-hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
+int IS_CONFIG_ADDRESS(int address)
{
- debugLog ("%s\n", __FUNCTION__);
- return (sym->usl.spillLoc ? 1 : 0);
+
+ return ((address == 0x2007) || (address == 0x2008));
}
/*-----------------------------------------------------------------*/
-/* directSpilLoc - will return 1 if the splilocation is in direct */
+/* allocNewDirReg - allocates a new register of given type */
/*-----------------------------------------------------------------*/
-static int
-directSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
+regs *
+allocNewDirReg (sym_link *symlnk,const char *name)
{
- debugLog ("%s\n", __FUNCTION__);
- if (sym->usl.spillLoc &&
- (IN_DIRSPACE (SPEC_OCLS (sym->usl.spillLoc->etype))))
- return 1;
- else
- return 0;
+ regs *reg;
+ int address = 0;
+ sym_link *spec = getSpec (symlnk);
+
+ /* if this is at an absolute address, then get the address. */
+ if (SPEC_ABSA (spec) ) {
+ address = SPEC_ADDR (spec);
+ //fprintf(stderr,"reg %s is at an absolute address: 0x%03x\n",name,address);
+ }
+
+ /* Register wasn't found in hash, so let's create
+ * a new one and put it in the hash table AND in the
+ * dynDirectRegNames set */
+ if (IS_CONFIG_ADDRESS(address)) {
+ debugLog (" -- %s is declared at address 0x2007\n",name);
+ reg = 0;
+ } else {
+ int idx;
+ if (address) {
+ if (IS_BITVAR (spec))
+ idx = address >> 3;
+ else
+ idx = address;
+ } else {
+ idx = dynrIdx++;
+ }
+ reg = newReg(REG_GPR, PO_DIR, idx, (char*)name,getSize (symlnk),0 );
+ debugLog (" -- added %s to hash, size = %d\n", (char*)name,reg->size);
+
+ if (SPEC_ABSA (spec) ) {
+ reg->type = REG_SFR;
+ }
+
+ if (IS_BITVAR (spec)) {
+ addSet(&dynDirectBitRegs, reg);
+ reg->isBitField = 1;
+ } else
+ addSet(&dynDirectRegs, reg);
+
+ if (!IS_STATIC (spec)) {
+ reg->isPublic = 1;
+ }
+ if (IS_EXTERN (spec)) {
+ reg->isExtern = 1;
+ }
+
+ }
+
+ if (address && reg) {
+ reg->isFixed = 1;
+ reg->address = address;
+ debugLog (" -- and it is at a fixed address 0x%02x\n",reg->address);
+ }
+
+ return reg;
}
/*-----------------------------------------------------------------*/
-/* hasSpilLocnoUptr - will return 1 if the symbol has spil location */
-/* but is not used as a pointer */
+/* allocDirReg - allocates register of given type */
/*-----------------------------------------------------------------*/
-static int
-hasSpilLocnoUptr (symbol * sym, eBBlock * ebp, iCode * ic)
+regs *
+allocDirReg (operand *op )
{
- debugLog ("%s\n", __FUNCTION__);
- return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
+
+ regs *reg;
+ char *name;
+
+ if(!IS_SYMOP(op)) {
+ debugLog ("%s BAD, op is NULL\n", __FUNCTION__);
+ return NULL;
+ }
+
+ name = OP_SYMBOL (op)->rname[0] ? OP_SYMBOL (op)->rname : OP_SYMBOL (op)->name;
+
+ /* If the symbol is at a fixed address, then remove the leading underscore
+ * from the name. This is hack to allow the .asm include file named registers
+ * to match the .c declared register names */
+
+ //if (SPEC_ABSA ( OP_SYM_ETYPE(op)) && (*name == '_'))
+ //name++;
+
+ debugLog ("%s symbol name %s\n", __FUNCTION__,name);
+ {
+ if(SPEC_CONST ( OP_SYM_ETYPE(op)) && (IS_CHAR ( OP_SYM_ETYPE(op)) )) {
+ debugLog(" %d const char\n",__LINE__);
+ debugLog(" value = %s \n",SPEC_CVAL( OP_SYM_ETYPE(op)));
+ }
+
+ debugLog(" %d storage class %d \n",__LINE__,SPEC_SCLS( OP_SYM_ETYPE(op)));
+ if (IS_CODE ( OP_SYM_ETYPE(op)) )
+ debugLog(" %d code space\n",__LINE__);
+
+ if (IS_INTEGRAL ( OP_SYM_ETYPE(op)) )
+ debugLog(" %d integral\n",__LINE__);
+ if (IS_LITERAL ( OP_SYM_ETYPE(op)) )
+ debugLog(" %d literal\n",__LINE__);
+ if (IS_SPEC ( OP_SYM_ETYPE(op)) )
+ debugLog(" %d specifier\n",__LINE__);
+ debugAopGet(NULL, op);
+ }
+
+ if (IS_CODE ( OP_SYM_ETYPE(op)) )
+ return NULL;
+
+ /* First, search the hash table to see if there is a register with this name */
+ if (SPEC_ABSA ( OP_SYM_ETYPE(op)) && !(IS_BITVAR (OP_SYM_ETYPE(op))) ) {
+ reg = regWithIdx (dynProcessorRegs, SPEC_ADDR ( OP_SYM_ETYPE(op)), 1);
+ /*
+ if(!reg)
+ fprintf(stderr,"ralloc %s is at fixed address but not a processor reg, addr=0x%x\n",
+ name, SPEC_ADDR ( OP_SYM_ETYPE(op)));
+ else
+ fprintf(stderr,"ralloc %s at fixed address has already been declared, addr=0x%x\n",
+ name, SPEC_ADDR ( OP_SYM_ETYPE(op)));
+ */
+ } else {
+ //fprintf(stderr,"ralloc:%d %s \n", __LINE__,name);
+
+ reg = dirregWithName(name);
+ }
+
+#if 0
+ if(!reg) {
+ int address = 0;
+
+ /* if this is at an absolute address, then get the address. */
+ if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
+ address = SPEC_ADDR ( OP_SYM_ETYPE(op));
+ //fprintf(stderr,"reg %s is at an absolute address: 0x%03x\n",name,address);
+ }
+
+ /* Register wasn't found in hash, so let's create
+ * a new one and put it in the hash table AND in the
+ * dynDirectRegNames set */
+ if(!IS_CONFIG_ADDRESS(address)) {
+ //fprintf(stderr,"allocating new reg %s\n",name);
+
+ reg = newReg(REG_GPR, PO_DIR, dynrIdx++, name,getSize (OP_SYMBOL (op)->type),0 );
+ debugLog (" -- added %s to hash, size = %d\n", name,reg->size);
+
+ //hTabAddItem(&dynDirectRegNames, regname2key(name), reg);
+
+ if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
+
+ //fprintf(stderr, " ralloc.c at fixed address: %s - changing to REG_SFR\n",name);
+ reg->type = REG_SFR;
+ }
+
+ if (IS_BITVAR (OP_SYM_ETYPE(op))) {
+ addSet(&dynDirectBitRegs, reg);
+ reg->isBitField = 1;
+ } else
+ addSet(&dynDirectRegs, reg);
+
+ if (!IS_STATIC (OP_SYM_ETYPE(op))) {
+ reg->isPublic = 1;
+ }
+ if (IS_EXTERN (OP_SYM_ETYPE(op))) {
+ reg->isExtern = 1;
+ }
+
+
+ } else {
+ debugLog (" -- %s is declared at address 0x2007\n",name);
+
+ }
+ }
+
+ if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
+ reg->isFixed = 1;
+ reg->address = SPEC_ADDR ( OP_SYM_ETYPE(op));
+ debugLog (" -- and it is at a fixed address 0x%02x\n",reg->address);
+ }
+#endif
+
+ if(reg) {
+ if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) {
+ reg->isFixed = 1;
+ reg->address = SPEC_ADDR ( OP_SYM_ETYPE(op));
+ debugLog (" -- and it is at a fixed address 0x%02x\n",reg->address);
+ }
+ } else {
+ allocNewDirReg (OP_SYM_TYPE(op),name);
+ }
+
+ return reg;
}
+
/*-----------------------------------------------------------------*/
-/* rematable - will return 1 if the remat flag is set */
+/* allocRegByName - allocates register with given name */
/*-----------------------------------------------------------------*/
-static int
-rematable (symbol * sym, eBBlock * ebp, iCode * ic)
+regs *
+allocRegByName (char *name, int size)
{
- debugLog ("%s\n", __FUNCTION__);
- return sym->remat;
+
+ regs *reg;
+
+ if(!name) {
+ fprintf(stderr, "%s - allocating a NULL register\n",__FUNCTION__);
+ exit(1);
+ }
+
+ /* First, search the hash table to see if there is a register with this name */
+ reg = dirregWithName(name);
+
+
+ if(!reg) {
+ int found = 0;
+ symbol *sym;
+ /* Register wasn't found in hash, so let's create
+ * a new one and put it in the hash table AND in the
+ * dynDirectRegNames set */
+ //fprintf (stderr,"%s symbol name %s, size:%d\n", __FUNCTION__,name,size);
+ reg = newReg(REG_GPR, PO_DIR, dynrIdx++, name,size,0 );
+ for (sym = setFirstItem(sfr->syms); sym; sym = setNextItem(sfr->syms)) {
+ if (strcmp(reg->name+1,sym->name)==0) {
+ unsigned a = SPEC_ADDR(sym->etype);
+ reg->address = a;
+ reg->isFixed = 1;
+ reg->type = REG_SFR;
+ if (!IS_STATIC (sym->etype)) {
+ reg->isPublic = 1;
+ }
+ if (IS_EXTERN (sym->etype)) {
+ reg->isExtern = 1;
+ }
+ if (IS_BITVAR (sym->etype))
+ reg->isBitField = 1;
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ for (sym = setFirstItem(data->syms); sym; sym = setNextItem(data->syms)) {
+ if (strcmp(reg->name+1,sym->name)==0) {
+ unsigned a = SPEC_ADDR(sym->etype);
+ reg->address = a;
+ if (!IS_STATIC (sym->etype)) {
+ reg->isPublic = 1;
+ }
+ if (IS_EXTERN (sym->etype)) {
+ reg->isExtern = 1;
+ }
+ if (IS_BITVAR (sym->etype))
+ reg->isBitField = 1;
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ debugLog (" -- added %s to hash, size = %d\n", name,reg->size);
+
+ //hTabAddItem(&dynDirectRegNames, regname2key(name), reg);
+ if (reg->isBitField) {
+ addSet(&dynDirectBitRegs, reg);
+ } else
+ addSet(&dynDirectRegs, reg);
+ }
+
+ return reg;
}
/*-----------------------------------------------------------------*/
-/* notUsedInBlock - not used in this block */
+/* RegWithIdx - returns pointer to register with index number */
/*-----------------------------------------------------------------*/
-static int
-notUsedInBlock (symbol * sym, eBBlock * ebp, iCode * ic)
+regs *
+typeRegWithIdx (int idx, int type, int fixed)
{
- debugLog ("%s\n", __FUNCTION__);
- return (!bitVectBitsInCommon (sym->defs, ebp->usesDefs) &&
- allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
-/* return (!bitVectBitsInCommon(sym->defs,ebp->usesDefs)); */
+
+ regs *dReg;
+
+ debugLog ("%s - requesting index = 0x%x\n", __FUNCTION__,idx);
+
+ switch (type) {
+
+ case REG_GPR:
+ if( (dReg = regWithIdx ( dynAllocRegs, idx, fixed)) != NULL) {
+
+ debugLog ("Found a Dynamic Register!\n");
+ return dReg;
+ }
+ if( (dReg = regWithIdx ( dynDirectRegs, idx, fixed)) != NULL ) {
+ debugLog ("Found a Direct Register!\n");
+ return dReg;
+ }
+
+ break;
+ case REG_STK:
+ if( (dReg = regWithIdx ( dynStackRegs, idx, 0)) != NULL ) {
+ debugLog ("Found a Stack Register!\n");
+ return dReg;
+ } else
+ if( (dReg = regWithIdx ( dynStackRegs, idx, 1)) != NULL ) {
+ debugLog ("Found a Stack Register!\n");
+ return dReg;
+ }
+ else {
+ werror (E_STACK_OUT, "Register");
+ /* return an existing register just to avoid the SDCC crash */
+ return regWithIdx ( dynStackRegs, 0x7f, 0);
+ }
+ break;
+ case REG_SFR:
+ if( (dReg = regWithIdx ( dynProcessorRegs, idx, fixed)) != NULL ) {
+ debugLog ("Found a Processor Register!\n");
+ return dReg;
+ }
+
+ case REG_CND:
+ case REG_PTR:
+ default:
+ break;
+ }
+
+
+ return NULL;
}
/*-----------------------------------------------------------------*/
-/* notUsedInRemaining - not used or defined in remain of the block */
+/* pic14_regWithIdx - returns pointer to register with index number*/
/*-----------------------------------------------------------------*/
-static int
-notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
+regs *
+pic14_regWithIdx (int idx)
{
- debugLog ("%s\n", __FUNCTION__);
- return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
- allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
+ regs *dReg;
+
+ if( (dReg = typeRegWithIdx(idx,REG_GPR,0)) != NULL)
+ return dReg;
+
+ if( (dReg = typeRegWithIdx(idx,REG_SFR,0)) != NULL)
+ return dReg;
+
+ return NULL;
}
/*-----------------------------------------------------------------*/
-/* allLRs - return true for all */
+/* pic14_regWithIdx - returns pointer to register with index number */
/*-----------------------------------------------------------------*/
-static int
-allLRs (symbol * sym, eBBlock * ebp, iCode * ic)
+regs *
+pic14_allocWithIdx (int idx)
{
- debugLog ("%s\n", __FUNCTION__);
- return 1;
+
+ regs *dReg;
+
+ debugLog ("%s - allocating with index = 0x%x\n", __FUNCTION__,idx);
+
+ if( (dReg = regWithIdx ( dynAllocRegs, idx,0)) != NULL) {
+
+ debugLog ("Found a Dynamic Register!\n");
+ } else if( (dReg = regWithIdx ( dynStackRegs, idx,0)) != NULL ) {
+ debugLog ("Found a Stack Register!\n");
+ } else if( (dReg = regWithIdx ( dynProcessorRegs, idx,0)) != NULL ) {
+ debugLog ("Found a Processor Register!\n");
+ } else if( (dReg = regWithIdx ( dynInternalRegs, idx,0)) != NULL ) {
+ debugLog ("Found an Internal Register!\n");
+ } else if( (dReg = regWithIdx ( dynInternalRegs, idx,1)) != NULL ) {
+ debugLog ("Found an Internal Register!\n");
+ } else {
+
+ debugLog ("Dynamic Register not found\n");
+
+
+ //fprintf(stderr,"%s %d - requested register: 0x%x\n",__FUNCTION__,__LINE__,idx);
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "regWithIdx not found");
+ exit (1);
+
+ }
+
+ dReg->wasUsed = 1;
+ dReg->isFree = 0;
+
+ return dReg;
}
-
/*-----------------------------------------------------------------*/
-/* liveRangesWith - applies function to a given set of live range */
/*-----------------------------------------------------------------*/
-static set *
-liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
- eBBlock * ebp, iCode * ic)
+regs *
+pic14_findFreeReg(short type)
{
- set *rset = NULL;
- int i;
-
- debugLog ("%s\n", __FUNCTION__);
- if (!lrs || !lrs->size)
- return NULL;
-
- for (i = 1; i < lrs->size; i++)
- {
- symbol *sym;
- if (!bitVectBitValue (lrs, i))
- continue;
-
- /* if we don't find it in the live range
- hash table we are in serious trouble */
- if (!(sym = hTabItemWithKey (liveRanges, i)))
- {
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "liveRangesWith could not find liveRange");
- exit (1);
+ // int i;
+ regs* dReg;
+
+ switch (type) {
+ case REG_GPR:
+ if((dReg = regFindFree(dynAllocRegs)) != NULL)
+ return dReg;
+ return addSet(&dynAllocRegs,newReg(REG_GPR, PO_GPR_TEMP,dynrIdx++,NULL,1,0));
+
+ case REG_STK:
+
+ if((dReg = regFindFree(dynStackRegs)) != NULL)
+ return dReg;
+
+ return NULL;
+
+ case REG_PTR:
+ case REG_CND:
+ case REG_SFR:
+ default:
+ return NULL;
}
-
- if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
- addSetHead (&rset, sym);
- }
-
- return rset;
}
-
-
/*-----------------------------------------------------------------*/
-/* leastUsedLR - given a set determines which is the least used */
+/* freeReg - frees a register */
/*-----------------------------------------------------------------*/
-static symbol *
-leastUsedLR (set * sset)
+static void
+freeReg (regs * reg)
{
- symbol *sym = NULL, *lsym = NULL;
-
- debugLog ("%s\n", __FUNCTION__);
- sym = lsym = setFirstItem (sset);
-
- if (!lsym)
- return NULL;
-
- for (; lsym; lsym = setNextItem (sset))
- {
-
- /* if usage is the same then prefer
- the spill the smaller of the two */
- if (lsym->used == sym->used)
- if (getSize (lsym->type) < getSize (sym->type))
- sym = lsym;
-
- /* if less usage */
- if (lsym->used < sym->used)
- sym = lsym;
-
- }
-
- setToNull ((void **) &sset);
- sym->blockSpil = 0;
- return sym;
+ debugLog ("%s\n", __FUNCTION__);
+ reg->isFree = 1;
}
+
/*-----------------------------------------------------------------*/
-/* noOverLap - will iterate through the list looking for over lap */
+/* nFreeRegs - returns number of free registers */
/*-----------------------------------------------------------------*/
static int
-noOverLap (set * itmpStack, symbol * fsym)
+nFreeRegs (int type)
{
- symbol *sym;
- debugLog ("%s\n", __FUNCTION__);
-
-
- for (sym = setFirstItem (itmpStack); sym;
- sym = setNextItem (itmpStack))
- {
- if (sym->liveTo > fsym->liveFrom)
- return 0;
-
- }
-
- return 1;
+/* dynamically allocate as many as we need and worry about
+ * fitting them into a PIC later */
+
+ return 100;
+#if 0
+ int i;
+ int nfr = 0;
+
+ debugLog ("%s\n", __FUNCTION__);
+ for (i = 0; i < pic14_nRegs; i++)
+ if (regspic14[i].isFree && regspic14[i].type == type)
+ nfr++;
+ return nfr;
+#endif
}
/*-----------------------------------------------------------------*/
-/* isFree - will return 1 if the a free spil location is found */
+/* nfreeRegsType - free registers with type */
/*-----------------------------------------------------------------*/
-static
-DEFSETFUNC (isFree)
+static int
+nfreeRegsType (int type)
{
- symbol *sym = item;
- V_ARG (symbol **, sloc);
- V_ARG (symbol *, fsym);
-
- debugLog ("%s\n", __FUNCTION__);
- /* if already found */
- if (*sloc)
- return 0;
-
- /* if it is free && and the itmp assigned to
- this does not have any overlapping live ranges
- with the one currently being assigned and
- the size can be accomodated */
- if (sym->isFree &&
- noOverLap (sym->usl.itmpStack, fsym) &&
- getSize (sym->type) >= getSize (fsym->type))
- {
- *sloc = sym;
- return 1;
- }
-
- return 0;
+ int nfr;
+ debugLog ("%s\n", __FUNCTION__);
+ if (type == REG_PTR)
+ {
+ if ((nfr = nFreeRegs (type)) == 0)
+ return nFreeRegs (REG_GPR);
+ }
+
+ return nFreeRegs (type);
}
-/*-----------------------------------------------------------------*/
-/* spillLRWithPtrReg :- will spil those live ranges which use PTR */
-/*-----------------------------------------------------------------*/
-static void
-spillLRWithPtrReg (symbol * forSym)
+void writeSetUsedRegs(FILE *of, set *dRegs)
{
- symbol *lrsym;
- regs *r0, *r1;
- int k;
-
- debugLog ("%s\n", __FUNCTION__);
- if (!_G.regAssigned ||
- bitVectIsZero (_G.regAssigned))
- return;
-
- r0 = pic14_regWithIdx (R0_IDX);
- r1 = pic14_regWithIdx (R1_IDX);
+
+ regs *dReg;
+
+ for (dReg = setFirstItem(dRegs) ; dReg ;
+ dReg = setNextItem(dRegs)) {
+
+ if(dReg->wasUsed)
+ fprintf (of, "\t%s\n",dReg->name);
+ }
+
+}
+extern void assignFixedRegisters(set *regset);
+extern void assignRelocatableRegisters(set *regset,int used);
+extern void dump_map(void);
+extern void dump_sfr(FILE *of);
- /* for all live ranges */
- for (lrsym = hTabFirstItem (liveRanges, &k); lrsym;
- lrsym = hTabNextItem (liveRanges, &k))
- {
- int j;
+void packBits(set *bregs)
+{
+ set *regset;
+ regs *breg;
+ regs *bitfield=NULL;
+ regs *relocbitfield=NULL;
+ int bit_no=0;
+ int byte_no=-1;
+ char buffer[20];
+
+
+ for (regset = bregs ; regset ;
+ regset = regset->next) {
+
+ breg = regset->item;
+ breg->isBitField = 1;
+ //fprintf(stderr,"bit reg: %s\n",breg->name);
+
+ if(breg->isFixed) {
+ //fprintf(stderr,"packing bit at fixed address = 0x%03x\n",breg->address);
+
+ bitfield = typeRegWithIdx (breg->address >> 3, -1 , 1);
+ breg->rIdx = breg->address & 7;
+ breg->address >>= 3;
+
+ if(!bitfield) {
+ //sprintf (buffer, "fbitfield%02x", breg->address);
+ sprintf (buffer, "0x%02x", breg->address);
+ //fprintf(stderr,"new bit field\n");
+ bitfield = newReg(REG_SFR, PO_GPR_BIT,breg->address,buffer,1,0);
+ bitfield->isBitField = 1;
+ bitfield->isFixed = 1;
+ bitfield->address = breg->address;
+ //addSet(&dynDirectRegs,bitfield);
+ addSet(&dynInternalRegs,bitfield);
+ //hTabAddItem(&dynDirectRegNames, regname2key(buffer), bitfield);
+ } else {
+ //fprintf(stderr," which is occupied by %s (addr = %d)\n",bitfield->name,bitfield->address);
+ ;
+ }
+ breg->reg_alias = bitfield;
+ bitfield = NULL;
+
+ } else {
+ if(!relocbitfield || bit_no >7) {
+ byte_no++;
+ bit_no=0;
+ sprintf (buffer, "bitfield%d", byte_no);
+ //fprintf(stderr,"new relocatable bit field\n");
+ relocbitfield = newReg(REG_GPR, PO_GPR_BIT,dynrIdx++,buffer,1,0);
+ relocbitfield->isBitField = 1;
+ //addSet(&dynDirectRegs,relocbitfield);
+ addSet(&dynInternalRegs,relocbitfield);
+ //hTabAddItem(&dynDirectRegNames, regname2key(buffer), relocbitfield);
+
+ }
+
+ breg->reg_alias = relocbitfield;
+ breg->address = dynrIdx; /* byte_no; */
+ breg->rIdx = bit_no++;
+ }
+ }
+
+}
- /* if no registers assigned to it or
- spilt */
- /* if it does not overlap with this then
- not need to spill it */
- if (lrsym->isspilt || !lrsym->nRegs ||
- (lrsym->liveTo < forSym->liveFrom))
- continue;
- /* go thru the registers : if it is either
- r0 or r1 then spil it */
- for (j = 0; j < lrsym->nRegs; j++)
- if (lrsym->regs[j] == r0 ||
- lrsym->regs[j] == r1)
- {
- spillThis (lrsym);
- break;
- }
- }
+void bitEQUs(FILE *of, set *bregs)
+{
+ regs *breg,*bytereg;
+ int bit_no=0;
+
+ //fprintf(stderr," %s\n",__FUNCTION__);
+ for (breg = setFirstItem(bregs) ; breg ;
+ breg = setNextItem(bregs)) {
+
+ //fprintf(stderr,"bit reg: %s\n",breg->name);
+
+ bytereg = breg->reg_alias;
+ if(bytereg)
+ fprintf (of, "%s\tEQU\t( (%s<<3)+%d)\n",
+ breg->name,
+ bytereg->name,
+ breg->rIdx & 0x0007);
+
+ else {
+ //fprintf(stderr, "bit field is not assigned to a register\n");
+ fprintf (of, "%s\tEQU\t( (bitfield%d<<3)+%d)\n",
+ breg->name,
+ bit_no>>3,
+ bit_no & 0x0007);
+
+ bit_no++;
+ }
+ }
+
+}
+void aliasEQUs(FILE *of, set *fregs, int use_rIdx)
+{
+ regs *reg;
+
+
+ for (reg = setFirstItem(fregs) ; reg ;
+ reg = setNextItem(fregs)) {
+
+ //if(!reg->isEmitted && reg->wasUsed) {
+ if(reg->wasUsed) {
+ if(use_rIdx)
+ fprintf (of, "%s\tEQU\t0x%03x\n",
+ reg->name,
+ reg->rIdx);
+ else
+ fprintf (of, "%s\tEQU\t0x%03x\n",
+ reg->name,
+ reg->address);
+ }
+ }
+
+}
+void writeUsedRegs(FILE *of)
+{
+ packBits(dynDirectBitRegs);
+
+ assignFixedRegisters(dynInternalRegs);
+ assignFixedRegisters(dynAllocRegs);
+ assignFixedRegisters(dynStackRegs);
+ assignFixedRegisters(dynDirectRegs);
+
+ assignRelocatableRegisters(dynInternalRegs,0);
+ assignRelocatableRegisters(dynAllocRegs,0);
+ assignRelocatableRegisters(dynStackRegs,0);
+
+ assignRelocatableRegisters(dynDirectRegs,0);
+ /*
+ assignRelocatableRegisters(dynDirectRegs,0);
+ printf("assignRelocatableRegisters(dynDirectRegs,0);\n");
+ */
+ //dump_map();
+
+ dump_sfr(of);
+ bitEQUs(of,dynDirectBitRegs);
+ /*
+ aliasEQUs(of,dynAllocRegs,0);
+ aliasEQUs(of,dynDirectRegs,0);
+ aliasEQUs(of,dynStackRegs,0);
+ aliasEQUs(of,dynProcessorRegs,1);
+ */
}
+#if 0
/*-----------------------------------------------------------------*/
-/* createStackSpil - create a location on the stack to spil */
+/* allDefsOutOfRange - all definitions are out of a range */
/*-----------------------------------------------------------------*/
-static symbol *
-createStackSpil (symbol * sym)
+static bool
+allDefsOutOfRange (bitVect * defs, int fseq, int toseq)
{
- symbol *sloc = NULL;
- int useXstack, model, noOverlay;
-
- char slocBuffer[30];
- debugLog ("%s\n", __FUNCTION__);
-
- /* first go try and find a free one that is already
- existing on the stack */
- if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
- {
- /* found a free one : just update & return */
- sym->usl.spillLoc = sloc;
- sym->stackSpil = 1;
- sloc->isFree = 0;
- addSetHead (&sloc->usl.itmpStack, sym);
- return sym;
- }
-
- /* could not then have to create one , this is the hard part
- we need to allocate this on the stack : this is really a
- hack!! but cannot think of anything better at this time */
-
- if (sprintf (slocBuffer, "sloc%d", _G.slocNum++) >= sizeof (slocBuffer))
- {
- fprintf (stderr, "kkkInternal error: slocBuffer overflowed: %s:%d\n",
- __FILE__, __LINE__);
- exit (1);
- }
-
- sloc = newiTemp (slocBuffer);
-
- /* set the type to the spilling symbol */
- sloc->type = copyLinkChain (sym->type);
- sloc->etype = getSpec (sloc->type);
- SPEC_SCLS (sloc->etype) = S_DATA;
- SPEC_EXTR (sloc->etype) = 0;
- SPEC_STAT (sloc->etype) = 0;
-
- /* we don't allow it to be allocated`
- onto the external stack since : so we
- temporarily turn it off ; we also
- turn off memory model to prevent
- the spil from going to the external storage
- and turn off overlaying
- */
-
- useXstack = options.useXstack;
- model = options.model;
- noOverlay = options.noOverlay;
- options.noOverlay = 1;
- options.model = options.useXstack = 0;
-
- allocLocal (sloc);
-
- options.useXstack = useXstack;
- options.model = model;
- options.noOverlay = noOverlay;
- sloc->isref = 1; /* to prevent compiler warning */
-
- /* if it is on the stack then update the stack */
- if (IN_STACK (sloc->etype))
- {
- currFunc->stack += getSize (sloc->type);
- _G.stackExtend += getSize (sloc->type);
- }
- else
- _G.dataExtend += getSize (sloc->type);
-
- /* add it to the _G.stackSpil set */
- addSetHead (&_G.stackSpil, sloc);
- sym->usl.spillLoc = sloc;
- sym->stackSpil = 1;
-
- /* add it to the set of itempStack set
- of the spill location */
- addSetHead (&sloc->usl.itmpStack, sym);
- return sym;
+ int i;
+
+ debugLog ("%s\n", __FUNCTION__);
+ if (!defs)
+ return TRUE;
+
+ for (i = 0; i < defs->size; i++)
+ {
+ iCode *ic;
+
+ if (bitVectBitValue (defs, i) &&
+ (ic = hTabItemWithKey (iCodehTab, i)) &&
+ (ic->seq >= fseq && ic->seq <= toseq))
+
+ return FALSE;
+
+ }
+
+ return TRUE;
}
+#endif
/*-----------------------------------------------------------------*/
-/* isSpiltOnStack - returns true if the spil location is on stack */
+/* computeSpillable - given a point find the spillable live ranges */
/*-----------------------------------------------------------------*/
-static bool
-isSpiltOnStack (symbol * sym)
+static bitVect *
+computeSpillable (iCode * ic)
{
- sym_link *etype;
-
- debugLog ("%s\n", __FUNCTION__);
- if (!sym)
- return FALSE;
-
- if (!sym->isspilt)
- return FALSE;
-
-/* if (sym->_G.stackSpil) */
-/* return TRUE; */
-
- if (!sym->usl.spillLoc)
- return FALSE;
-
- etype = getSpec (sym->usl.spillLoc->type);
- if (IN_STACK (etype))
- return TRUE;
-
- return FALSE;
+ bitVect *spillable;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* spillable live ranges are those that are live at this
+ point . the following categories need to be subtracted
+ from this set.
+ a) - those that are already spilt
+ b) - if being used by this one
+ c) - defined by this one */
+
+ spillable = bitVectCopy (ic->rlive);
+ spillable =
+ bitVectCplAnd (spillable, _G.spiltSet); /* those already spilt */
+ spillable =
+ bitVectCplAnd (spillable, ic->uses); /* used in this one */
+ bitVectUnSetBit (spillable, ic->defKey);
+ spillable = bitVectIntersect (spillable, _G.regAssigned);
+ return spillable;
+
}
/*-----------------------------------------------------------------*/
-/* spillThis - spils a specific operand */
+/* noSpilLoc - return true if a variable has no spil location */
/*-----------------------------------------------------------------*/
-static void
-spillThis (symbol * sym)
+static int
+noSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
{
- int i;
- debugLog ("%s : %s\n", __FUNCTION__, sym->rname);
-
- /* if this is rematerializable or has a spillLocation
- we are okay, else we need to create a spillLocation
- for it */
- if (!(sym->remat || sym->usl.spillLoc))
- createStackSpil (sym);
-
-
- /* mark it has spilt & put it in the spilt set */
- sym->isspilt = 1;
- _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
-
- bitVectUnSetBit (_G.regAssigned, sym->key);
-
- for (i = 0; i < sym->nRegs; i++)
-
- if (sym->regs[i])
- {
- freeReg (sym->regs[i]);
- sym->regs[i] = NULL;
- }
-
- /* if spilt on stack then free up r0 & r1
- if they could have been assigned to some
- LIVE ranges */
- if (!pic14_ptrRegReq && isSpiltOnStack (sym))
- {
- pic14_ptrRegReq++;
- spillLRWithPtrReg (sym);
- }
-
- if (sym->usl.spillLoc && !sym->remat)
- sym->usl.spillLoc->allocreq = 1;
- return;
+ debugLog ("%s\n", __FUNCTION__);
+ return (sym->usl.spillLoc ? 0 : 1);
}
/*-----------------------------------------------------------------*/
-/* selectSpil - select a iTemp to spil : rather a simple procedure */
+/* hasSpilLoc - will return 1 if the symbol has spil location */
/*-----------------------------------------------------------------*/
-static symbol *
-selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
+static int
+hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
{
- bitVect *lrcs = NULL;
- set *selectS;
- symbol *sym;
-
- debugLog ("%s\n", __FUNCTION__);
- /* get the spillable live ranges */
- lrcs = computeSpillable (ic);
-
- /* get all live ranges that are rematerizable */
- if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
- {
-
- /* return the least used of these */
- return leastUsedLR (selectS);
- }
-
- /* get live ranges with spillLocations in direct space */
- if ((selectS = liveRangesWith (lrcs, directSpilLoc, ebp, ic)))
- {
- sym = leastUsedLR (selectS);
- strcpy (sym->rname, (sym->usl.spillLoc->rname[0] ?
- sym->usl.spillLoc->rname :
- sym->usl.spillLoc->name));
- sym->spildir = 1;
- /* mark it as allocation required */
- sym->usl.spillLoc->allocreq = 1;
- return sym;
- }
-
- /* if the symbol is local to the block then */
- if (forSym->liveTo < ebp->lSeq)
- {
-
- /* check if there are any live ranges allocated
- to registers that are not used in this block */
- if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
- {
- sym = leastUsedLR (selectS);
- /* if this is not rematerializable */
- if (!sym->remat)
- {
- _G.blockSpil++;
- sym->blockSpil = 1;
- }
- return sym;
- }
-
- /* check if there are any live ranges that not
- used in the remainder of the block */
- if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
- {
- sym = leastUsedLR (selectS);
- if (!sym->remat)
- {
- sym->remainSpil = 1;
- _G.blockSpil++;
- }
- return sym;
- }
- }
-
- /* find live ranges with spillocation && not used as pointers */
- if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
- {
-
- sym = leastUsedLR (selectS);
- /* mark this as allocation required */
- sym->usl.spillLoc->allocreq = 1;
- return sym;
- }
-
- /* find live ranges with spillocation */
- if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
- {
-
- sym = leastUsedLR (selectS);
- sym->usl.spillLoc->allocreq = 1;
- return sym;
- }
-
- /* couldn't find then we need to create a spil
- location on the stack , for which one? the least
- used ofcourse */
- if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
- {
-
- /* return a created spil location */
- sym = createStackSpil (leastUsedLR (selectS));
- sym->usl.spillLoc->allocreq = 1;
- return sym;
- }
-
- /* this is an extreme situation we will spill
- this one : happens very rarely but it does happen */
- spillThis (forSym);
- return forSym;
-
+ debugLog ("%s\n", __FUNCTION__);
+ return (sym->usl.spillLoc ? 1 : 0);
}
/*-----------------------------------------------------------------*/
-/* spilSomething - spil some variable & mark registers as free */
+/* directSpilLoc - will return 1 if the splilocation is in direct */
/*-----------------------------------------------------------------*/
-static bool
-spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
+static int
+directSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
{
- symbol *ssym;
- int i;
-
- debugLog ("%s\n", __FUNCTION__);
- /* get something we can spil */
- ssym = selectSpil (ic, ebp, forSym);
-
- /* mark it as spilt */
- ssym->isspilt = 1;
- _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
-
- /* mark it as not register assigned &
- take it away from the set */
- bitVectUnSetBit (_G.regAssigned, ssym->key);
-
- /* mark the registers as free */
- for (i = 0; i < ssym->nRegs; i++)
- if (ssym->regs[i])
- freeReg (ssym->regs[i]);
-
- /* if spilt on stack then free up r0 & r1
- if they could have been assigned to as gprs */
- if (!pic14_ptrRegReq && isSpiltOnStack (ssym))
- {
- pic14_ptrRegReq++;
- spillLRWithPtrReg (ssym);
- }
-
- /* if this was a block level spil then insert push & pop
- at the start & end of block respectively */
- if (ssym->blockSpil)
- {
- iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
- /* add push to the start of the block */
- addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ?
- ebp->sch->next : ebp->sch));
- nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
- /* add pop to the end of the block */
- addiCodeToeBBlock (ebp, nic, NULL);
- }
-
- /* if spilt because not used in the remainder of the
- block then add a push before this instruction and
- a pop at the end of the block */
- if (ssym->remainSpil)
- {
-
- iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
- /* add push just before this instruction */
- addiCodeToeBBlock (ebp, nic, ic);
-
- nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
- /* add pop to the end of the block */
- addiCodeToeBBlock (ebp, nic, NULL);
- }
-
- if (ssym == forSym)
- return FALSE;
- else
- return TRUE;
+ debugLog ("%s\n", __FUNCTION__);
+ if (sym->usl.spillLoc &&
+ (IN_DIRSPACE (SPEC_OCLS (sym->usl.spillLoc->etype))))
+ return 1;
+ else
+ return 0;
}
/*-----------------------------------------------------------------*/
-/* getRegPtr - will try for PTR if not a GPR type if not spil */
+/* hasSpilLocnoUptr - will return 1 if the symbol has spil location */
+/* but is not used as a pointer */
/*-----------------------------------------------------------------*/
-static regs *
-getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym)
+static int
+hasSpilLocnoUptr (symbol * sym, eBBlock * ebp, iCode * ic)
{
- regs *reg;
-
- debugLog ("%s\n", __FUNCTION__);
-tryAgain:
- /* try for a ptr type */
- if ((reg = allocReg (REG_PTR)))
- return reg;
-
- /* try for gpr type */
- if ((reg = allocReg (REG_GPR)))
- return reg;
-
- /* we have to spil */
- if (!spilSomething (ic, ebp, sym))
- return NULL;
-
- /* this looks like an infinite loop but
- in really selectSpil will abort */
- goto tryAgain;
+ debugLog ("%s\n", __FUNCTION__);
+ return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
}
/*-----------------------------------------------------------------*/
-/* getRegGpr - will try for GPR if not spil */
+/* rematable - will return 1 if the remat flag is set */
/*-----------------------------------------------------------------*/
-static regs *
-getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
+static int
+rematable (symbol * sym, eBBlock * ebp, iCode * ic)
{
- regs *reg;
-
- debugLog ("%s\n", __FUNCTION__);
-tryAgain:
- /* try for gpr type */
- if ((reg = allocReg (REG_GPR)))
- return reg;
-
- if (!pic14_ptrRegReq)
- if ((reg = allocReg (REG_PTR)))
- return reg;
-
- /* we have to spil */
- if (!spilSomething (ic, ebp, sym))
- return NULL;
-
- /* this looks like an infinite loop but
- in really selectSpil will abort */
- goto tryAgain;
+ debugLog ("%s\n", __FUNCTION__);
+ return sym->remat;
}
/*-----------------------------------------------------------------*/
-/* symHasReg - symbol has a given register */
+/* notUsedInRemaining - not used or defined in remain of the block */
/*-----------------------------------------------------------------*/
-static bool
-symHasReg (symbol * sym, regs * reg)
+static int
+notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
{
- int i;
-
- debugLog ("%s\n", __FUNCTION__);
- for (i = 0; i < sym->nRegs; i++)
- if (sym->regs[i] == reg)
- return TRUE;
-
- return FALSE;
+ debugLog ("%s\n", __FUNCTION__);
+ return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
+ allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
}
/*-----------------------------------------------------------------*/
-/* deassignLRs - check the live to and if they have registers & are */
-/* not spilt then free up the registers */
+/* allLRs - return true for all */
/*-----------------------------------------------------------------*/
-static void
-deassignLRs (iCode * ic, eBBlock * ebp)
+static int
+allLRs (symbol * sym, eBBlock * ebp, iCode * ic)
{
- symbol *sym;
- int k;
- symbol *result;
-
- debugLog ("%s\n", __FUNCTION__);
- for (sym = hTabFirstItem (liveRanges, &k); sym;
- sym = hTabNextItem (liveRanges, &k))
- {
-
- symbol *psym = NULL;
- /* if it does not end here */
- if (sym->liveTo > ic->seq)
- continue;
+ debugLog ("%s\n", __FUNCTION__);
+ return 1;
+}
- /* if it was spilt on stack then we can
- mark the stack spil location as free */
- if (sym->isspilt)
- {
- if (sym->stackSpil)
- {
- sym->usl.spillLoc->isFree = 1;
- sym->stackSpil = 0;
- }
- continue;
- }
-
- if (!bitVectBitValue (_G.regAssigned, sym->key))
- continue;
-
- /* special case check if this is an IFX &
- the privious one was a pop and the
- previous one was not spilt then keep track
- of the symbol */
- if (ic->op == IFX && ic->prev &&
- ic->prev->op == IPOP &&
- !ic->prev->parmPush &&
- !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt)
- psym = OP_SYMBOL (IC_LEFT (ic->prev));
-
- if (sym->nRegs)
+/*-----------------------------------------------------------------*/
+/* liveRangesWith - applies function to a given set of live range */
+/*-----------------------------------------------------------------*/
+static set *
+liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
+ eBBlock * ebp, iCode * ic)
+{
+ set *rset = NULL;
+ int i;
+
+ debugLog ("%s\n", __FUNCTION__);
+ if (!lrs || !lrs->size)
+ return NULL;
+
+ for (i = 1; i < lrs->size; i++)
{
- int i = 0;
-
- bitVectUnSetBit (_G.regAssigned, sym->key);
-
- /* if the result of this one needs registers
- and does not have it then assign it right
- away */
- if (IC_RESULT (ic) &&
- !(SKIP_IC2 (ic) || /* not a special icode */
- ic->op == JUMPTABLE ||
- ic->op == IFX ||
- ic->op == IPUSH ||
- ic->op == IPOP ||
- ic->op == RETURN ||
- POINTER_SET (ic)) &&
- (result = OP_SYMBOL (IC_RESULT (ic))) && /* has a result */
- result->liveTo > ic->seq && /* and will live beyond this */
- result->liveTo <= ebp->lSeq && /* does not go beyond this block */
- result->regType == sym->regType && /* same register types */
- result->nRegs && /* which needs registers */
- !result->isspilt && /* and does not already have them */
- !result->remat &&
- !bitVectBitValue (_G.regAssigned, result->key) &&
- /* the number of free regs + number of regs in this LR
- can accomodate the what result Needs */
- ((nfreeRegsType (result->regType) +
- sym->nRegs) >= result->nRegs)
- )
- {
-
- for (i = 0; i < max (sym->nRegs, result->nRegs); i++)
- if (i < sym->nRegs)
- result->regs[i] = sym->regs[i];
- else
- result->regs[i] = getRegGpr (ic, ebp, result);
-
- _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
-
- }
-
- /* free the remaining */
- for (; i < sym->nRegs; i++)
- {
- if (psym)
+ symbol *sym;
+ if (!bitVectBitValue (lrs, i))
+ continue;
+
+ /* if we don't find it in the live range
+ hash table we are in serious trouble */
+ if (!(sym = hTabItemWithKey (liveRanges, i)))
{
- if (!symHasReg (psym, sym->regs[i]))
- freeReg (sym->regs[i]);
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "liveRangesWith could not find liveRange");
+ exit (1);
}
- else
- freeReg (sym->regs[i]);
- }
+
+ if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
+ addSetHead (&rset, sym);
}
- }
+
+ return rset;
}
/*-----------------------------------------------------------------*/
-/* reassignLR - reassign this to registers */
+/* leastUsedLR - given a set determines which is the least used */
/*-----------------------------------------------------------------*/
-static void
-reassignLR (operand * op)
+static symbol *
+leastUsedLR (set * sset)
{
- symbol *sym = OP_SYMBOL (op);
- int i;
-
- debugLog ("%s\n", __FUNCTION__);
- /* not spilt any more */
- sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
- bitVectUnSetBit (_G.spiltSet, sym->key);
-
- _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
-
- _G.blockSpil--;
-
- for (i = 0; i < sym->nRegs; i++)
- sym->regs[i]->isFree = 0;
+ symbol *sym = NULL, *lsym = NULL;
+
+ debugLog ("%s\n", __FUNCTION__);
+ sym = lsym = setFirstItem (sset);
+
+ if (!lsym)
+ return NULL;
+
+ for (; lsym; lsym = setNextItem (sset))
+ {
+
+ /* if usage is the same then prefer
+ the spill the smaller of the two */
+ if (lsym->used == sym->used)
+ if (getSize (lsym->type) < getSize (sym->type))
+ sym = lsym;
+
+ /* if less usage */
+ if (lsym->used < sym->used)
+ sym = lsym;
+
+ }
+
+ setToNull ((void *) &sset);
+ sym->blockSpil = 0;
+ return sym;
}
/*-----------------------------------------------------------------*/
-/* willCauseSpill - determines if allocating will cause a spill */
+/* noOverLap - will iterate through the list looking for over lap */
/*-----------------------------------------------------------------*/
static int
-willCauseSpill (int nr, int rt)
+noOverLap (set * itmpStack, symbol * fsym)
{
- debugLog ("%s\n", __FUNCTION__);
- /* first check if there are any avlb registers
- of te type required */
- if (rt == REG_PTR)
- {
- /* special case for pointer type
- if pointer type not avlb then
- check for type gpr */
- if (nFreeRegs (rt) >= nr)
- return 0;
- if (nFreeRegs (REG_GPR) >= nr)
- return 0;
- }
- else
- {
- if (pic14_ptrRegReq)
- {
- if (nFreeRegs (rt) >= nr)
- return 0;
- }
- else
+ symbol *sym;
+ debugLog ("%s\n", __FUNCTION__);
+
+
+ for (sym = setFirstItem (itmpStack); sym;
+ sym = setNextItem (itmpStack))
{
- if (nFreeRegs (REG_PTR) +
- nFreeRegs (REG_GPR) >= nr)
- return 0;
+ if (sym->liveTo > fsym->liveFrom)
+ return 0;
+
}
- }
-
- debugLog (" ... yep it will (cause a spill)\n");
- /* it will cause a spil */
- return 1;
+
+ return 1;
}
/*-----------------------------------------------------------------*/
-/* positionRegs - the allocator can allocate same registers to res- */
-/* ult and operand, if this happens make sure they are in the same */
-/* position as the operand otherwise chaos results */
+/* isFree - will return 1 if the a free spil location is found */
/*-----------------------------------------------------------------*/
-static void
-positionRegs (symbol * result, symbol * opsym, int lineno)
+static
+DEFSETFUNC (isFree)
{
- int count = min (result->nRegs, opsym->nRegs);
- int i, j = 0, shared = 0;
-
- debugLog ("%s\n", __FUNCTION__);
- /* if the result has been spilt then cannot share */
- if (opsym->isspilt)
- return;
-again:
- shared = 0;
- /* first make sure that they actually share */
- for (i = 0; i < count; i++)
- {
- for (j = 0; j < count; j++)
+ symbol *sym = item;
+ V_ARG (symbol **, sloc);
+ V_ARG (symbol *, fsym);
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* if already found */
+ if (*sloc)
+ return 0;
+
+ /* if it is free && and the itmp assigned to
+ this does not have any overlapping live ranges
+ with the one currently being assigned and
+ the size can be accomodated */
+ if (sym->isFree &&
+ noOverLap (sym->usl.itmpStack, fsym) &&
+ getSize (sym->type) >= getSize (fsym->type))
{
- if (result->regs[i] == opsym->regs[j] && i != j)
- {
- shared = 1;
- goto xchgPositions;
- }
+ *sloc = sym;
+ return 1;
}
- }
-xchgPositions:
- if (shared)
- {
- regs *tmp = result->regs[i];
- result->regs[i] = result->regs[j];
- result->regs[j] = tmp;
- goto again;
- }
+
+ return 0;
}
/*-----------------------------------------------------------------*/
-/* serialRegAssign - serially allocate registers to the variables */
+/* spillLRWithPtrReg :- will spil those live ranges which use PTR */
/*-----------------------------------------------------------------*/
static void
-serialRegAssign (eBBlock ** ebbs, int count)
+spillLRWithPtrReg (symbol * forSym)
{
- int i;
+ symbol *lrsym;
+ regs *r0, *r1;
+ int k;
+
+ debugLog ("%s\n", __FUNCTION__);
+ if (!_G.regAssigned ||
+ bitVectIsZero (_G.regAssigned))
+ return;
+
+ r0 = pic14_regWithIdx (R0_IDX);
+ r1 = pic14_regWithIdx (R1_IDX);
+
+ /* for all live ranges */
+ for (lrsym = hTabFirstItem (liveRanges, &k); lrsym;
+ lrsym = hTabNextItem (liveRanges, &k))
+ {
+ int j;
+
+ /* if no registers assigned to it or
+ spilt */
+ /* if it does not overlap with this then
+ not need to spill it */
+
+ if (lrsym->isspilt || !lrsym->nRegs ||
+ (lrsym->liveTo < forSym->liveFrom))
+ continue;
+
+ /* go thru the registers : if it is either
+ r0 or r1 then spil it */
+ for (j = 0; j < lrsym->nRegs; j++)
+ if (lrsym->regs[j] == r0 ||
+ lrsym->regs[j] == r1)
+ {
+ spillThis (lrsym);
+ break;
+ }
+ }
+
+}
- debugLog ("%s\n", __FUNCTION__);
- /* for all blocks */
- for (i = 0; i < count; i++)
- {
+/*-----------------------------------------------------------------*/
+/* createStackSpil - create a location on the stack to spil */
+/*-----------------------------------------------------------------*/
+static symbol *
+createStackSpil (symbol * sym)
+{
+ symbol *sloc = NULL;
+ int useXstack, model, noOverlay;
+
+ char slocBuffer[30];
+ debugLog ("%s\n", __FUNCTION__);
- iCode *ic;
+ FENTRY2("called.");
+
+ /* first go try and find a free one that is already
+ existing on the stack */
+ if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
+ {
+ /* found a free one : just update & return */
+ sym->usl.spillLoc = sloc;
+ sym->stackSpil = 1;
+ sloc->isFree = 0;
+ addSetHead (&sloc->usl.itmpStack, sym);
+ return sym;
+ }
+
+ /* could not then have to create one , this is the hard part
+ we need to allocate this on the stack : this is really a
+ hack!! but cannot think of anything better at this time */
+
+ if (sprintf (slocBuffer, "sloc%d", _G.slocNum++) >= sizeof (slocBuffer))
+ {
+ fprintf (stderr, "kkkInternal error: slocBuffer overflowed: %s:%d\n",
+ __FILE__, __LINE__);
+ exit (1);
+ }
+
+ sloc = newiTemp (slocBuffer);
+
+ /* set the type to the spilling symbol */
+ sloc->type = copyLinkChain (sym->type);
+ sloc->etype = getSpec (sloc->type);
+ SPEC_SCLS (sloc->etype) = S_DATA;
+ SPEC_EXTR (sloc->etype) = 0;
+ SPEC_STAT (sloc->etype) = 0;
+
+ /* we don't allow it to be allocated`
+ onto the external stack since : so we
+ temporarily turn it off ; we also
+ turn off memory model to prevent
+ the spil from going to the external storage
+ and turn off overlaying
+ */
+
+ useXstack = options.useXstack;
+ model = options.model;
+ noOverlay = options.noOverlay;
+ options.noOverlay = 1;
+ options.model = options.useXstack = 0;
+
+ allocLocal (sloc);
+
+ options.useXstack = useXstack;
+ options.model = model;
+ options.noOverlay = noOverlay;
+ sloc->isref = 1; /* to prevent compiler warning */
+
+ /* if it is on the stack then update the stack */
+ if (IN_STACK (sloc->etype))
+ {
+ currFunc->stack += getSize (sloc->type);
+ _G.stackExtend += getSize (sloc->type);
+ }
+ else
+ _G.dataExtend += getSize (sloc->type);
+
+ /* add it to the _G.stackSpil set */
+ addSetHead (&_G.stackSpil, sloc);
+ sym->usl.spillLoc = sloc;
+ sym->stackSpil = 1;
+
+ /* add it to the set of itempStack set
+ of the spill location */
+ addSetHead (&sloc->usl.itmpStack, sym);
+ return sym;
+}
- if (ebbs[i]->noPath &&
- (ebbs[i]->entryLabel != entryLabel &&
- ebbs[i]->entryLabel != returnLabel))
- continue;
+/*-----------------------------------------------------------------*/
+/* isSpiltOnStack - returns true if the spil location is on stack */
+/*-----------------------------------------------------------------*/
+static bool
+isSpiltOnStack (symbol * sym)
+{
+ sym_link *etype;
+
+ debugLog ("%s\n", __FUNCTION__);
+ FENTRY2("called.");
+
+ if (!sym)
+ return FALSE;
+
+ if (!sym->isspilt)
+ return FALSE;
+
+ /* if (sym->_G.stackSpil) */
+ /* return TRUE; */
+
+ if (!sym->usl.spillLoc)
+ return FALSE;
+
+ etype = getSpec (sym->usl.spillLoc->type);
+ if (IN_STACK (etype))
+ return TRUE;
+
+ return FALSE;
+}
- /* of all instructions do */
- for (ic = ebbs[i]->sch; ic; ic = ic->next)
+/*-----------------------------------------------------------------*/
+/* spillThis - spils a specific operand */
+/*-----------------------------------------------------------------*/
+static void
+spillThis (symbol * sym)
+{
+ int i;
+ debugLog ("%s : %s\n", __FUNCTION__, sym->rname);
+ FENTRY2("sym: %s, spillLoc:%p (%s)\n", sym->rname, sym->usl.spillLoc, sym->usl.spillLoc ? sym->usl.spillLoc->rname : "<unknown>");
+
+ /* if this is rematerializable or has a spillLocation
+ we are okay, else we need to create a spillLocation
+ for it */
+ if (!(sym->remat || sym->usl.spillLoc))
+ createStackSpil (sym);
+
+
+ /* mark it has spilt & put it in the spilt set */
+ sym->isspilt = 1;
+ _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
+
+ bitVectUnSetBit (_G.regAssigned, sym->key);
+
+ for (i = 0; i < sym->nRegs; i++)
{
-
- debugLog (" op: %s\n", decodeOp (ic->op));
-
- /* if this is an ipop that means some live
- range will have to be assigned again */
- if (ic->op == IPOP)
- reassignLR (IC_LEFT (ic));
-
- /* if result is present && is a true symbol */
- if (IC_RESULT (ic) && ic->op != IFX &&
- IS_TRUE_SYMOP (IC_RESULT (ic)))
- OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
-
- /* take away registers from live
- ranges that end at this instruction */
- deassignLRs (ic, ebbs[i]);
-
- /* some don't need registers */
- if (SKIP_IC2 (ic) ||
- ic->op == JUMPTABLE ||
- ic->op == IFX ||
- ic->op == IPUSH ||
- ic->op == IPOP ||
- (IC_RESULT (ic) && POINTER_SET (ic)))
- continue;
-
- /* now we need to allocate registers
- only for the result */
- if (IC_RESULT (ic))
- {
- symbol *sym = OP_SYMBOL (IC_RESULT (ic));
- bitVect *spillable;
- int willCS;
- int j;
- int ptrRegSet = 0;
-
- /* if it does not need or is spilt
- or is already assigned to registers
- or will not live beyond this instructions */
- if (!sym->nRegs ||
- sym->isspilt ||
- bitVectBitValue (_G.regAssigned, sym->key) ||
- sym->liveTo <= ic->seq)
- continue;
-
- /* if some liverange has been spilt at the block level
- and this one live beyond this block then spil this
- to be safe */
- if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
- {
- spillThis (sym);
- continue;
- }
- /* if trying to allocate this will cause
- a spill and there is nothing to spill
- or this one is rematerializable then
- spill this one */
- willCS = willCauseSpill (sym->nRegs, sym->regType);
- spillable = computeSpillable (ic);
- if (sym->remat ||
- (willCS && bitVectIsZero (spillable)))
+ if (sym->regs[i])
{
+ freeReg (sym->regs[i]);
+ sym->regs[i] = NULL;
+ }
+ }
+
+ /* if spilt on stack then free up r0 & r1
+ if they could have been assigned to some
+ LIVE ranges */
+ if (!pic14_ptrRegReq && isSpiltOnStack (sym))
+ {
+ pic14_ptrRegReq++;
+ spillLRWithPtrReg (sym);
+ }
+
+ if (sym->usl.spillLoc && !sym->remat)
+ sym->usl.spillLoc->allocreq = 1;
+
+ return;
+}
- spillThis (sym);
- continue;
+/*-----------------------------------------------------------------*/
+/* selectSpil - select a iTemp to spil : rather a simple procedure */
+/*-----------------------------------------------------------------*/
+static symbol *
+selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
+{
+ bitVect *lrcs = NULL;
+ set *selectS;
+ symbol *sym;
+
+ debugLog ("%s\n", __FUNCTION__);
+ FENTRY2("called.");
+ /* get the spillable live ranges */
+ lrcs = computeSpillable (ic);
- }
- /* if it has a spillocation & is used less than
- all other live ranges then spill this */
- if (willCS) {
- if (sym->usl.spillLoc) {
- symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
- allLRs, ebbs[i], ic));
- if (leastUsed && leastUsed->used > sym->used) {
- spillThis (sym);
- continue;
+ /* get all live ranges that are rematerizable */
+ if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
+ {
+ /* return the least used of these */
+ return leastUsedLR (selectS);
+ }
+
+ /* get live ranges with spillLocations in direct space */
+ if ((selectS = liveRangesWith (lrcs, directSpilLoc, ebp, ic)))
+ {
+ sym = leastUsedLR (selectS);
+ strcpy (sym->rname, (sym->usl.spillLoc->rname[0] ?
+ sym->usl.spillLoc->rname :
+ sym->usl.spillLoc->name));
+ sym->spildir = 1;
+ /* mark it as allocation required */
+ sym->usl.spillLoc->allocreq = 1;
+ return sym;
+ }
+
+ /* if the symbol is local to the block then */
+ if (forSym->liveTo < ebp->lSeq)
+ {
+
+ /* check if there are any live ranges allocated
+ to registers that are not used in this block */
+ if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
+ {
+ sym = leastUsedLR (selectS);
+ /* if this is not rematerializable */
+ if (!sym->remat)
+ {
+ _G.blockSpil++;
+ sym->blockSpil = 1;
}
- } else {
- /* if none of the liveRanges have a spillLocation then better
- to spill this one than anything else already assigned to registers */
- if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
- /* if this is local to this block then we might find a block spil */
- if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
- spillThis (sym);
- continue;
- }
+ return sym;
+ }
+
+ /* check if there are any live ranges that not
+ used in the remainder of the block */
+ if (!_G.blockSpil &&
+ !isiCodeInFunctionCall (ic) &&
+ (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
+ {
+ sym = leastUsedLR (selectS);
+ if (!sym->remat)
+ {
+ sym->remainSpil = 1;
+ _G.blockSpil++;
}
- }
+ return sym;
}
+ }
+
+ /* find live ranges with spillocation && not used as pointers */
+ if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
+ {
+
+ sym = leastUsedLR (selectS);
+ /* mark this as allocation required */
+ sym->usl.spillLoc->allocreq = 1;
+ return sym;
+ }
+
+ /* find live ranges with spillocation */
+ if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
+ {
+
+ sym = leastUsedLR (selectS);
+ sym->usl.spillLoc->allocreq = 1;
+ return sym;
+ }
- if (ic->op == RECEIVE)
- debugLog ("When I get clever, I'll optimize the receive logic\n");
+ /* couldn't find then we need to create a spil
+ location on the stack , for which one? the least
+ used ofcourse */
+ if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
+ {
+
+ /* return a created spil location */
+ sym = createStackSpil (leastUsedLR (selectS));
+ sym->usl.spillLoc->allocreq = 1;
+ return sym;
+ }
+
+ /* this is an extreme situation we will spill
+ this one : happens very rarely but it does happen */
+ spillThis (forSym);
+ return forSym;
+
+}
- /* if we need ptr regs for the right side
- then mark it */
- if (POINTER_GET (ic) && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
- <= (unsigned) PTRSIZE)
+/*-----------------------------------------------------------------*/
+/* spilSomething - spil some variable & mark registers as free */
+/*-----------------------------------------------------------------*/
+static bool
+spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
+{
+ symbol *ssym;
+ int i;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* get something we can spil */
+ ssym = selectSpil (ic, ebp, forSym);
+
+ /* mark it as spilt */
+ ssym->isspilt = 1;
+ _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
+
+ /* mark it as not register assigned &
+ take it away from the set */
+ bitVectUnSetBit (_G.regAssigned, ssym->key);
+
+ /* mark the registers as free */
+ for (i = 0; i < ssym->nRegs; i++)
+ if (ssym->regs[i])
+ freeReg (ssym->regs[i]);
+
+ /* if spilt on stack then free up r0 & r1
+ if they could have been assigned to as gprs */
+ if (!pic14_ptrRegReq && isSpiltOnStack (ssym))
{
- pic14_ptrRegReq++;
- ptrRegSet = 1;
+ pic14_ptrRegReq++;
+ spillLRWithPtrReg (ssym);
}
- /* else we assign registers to it */
- _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
-
- debugLog (" %d - \n", __LINE__);
- if(debugF)
- bitVectDebugOn(_G.regAssigned, debugF);
-
- for (j = 0; j < sym->nRegs; j++)
+
+ /* if this was a block level spil then insert push & pop
+ at the start & end of block respectively */
+ if (ssym->blockSpil)
{
- if (sym->regType == REG_PTR)
- sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
- else
- sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
-
- /* if the allocation falied which means
- this was spilt then break */
- if (!sym->regs[j])
- break;
- }
- debugLog (" %d - \n", __LINE__);
-
- /* if it shares registers with operands make sure
- that they are in the same position */
- if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
- OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=')
- positionRegs (OP_SYMBOL (IC_RESULT (ic)),
- OP_SYMBOL (IC_LEFT (ic)), ic->lineno);
- /* do the same for the right operand */
- if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
- OP_SYMBOL (IC_RIGHT (ic))->nRegs && ic->op != '=')
- positionRegs (OP_SYMBOL (IC_RESULT (ic)),
- OP_SYMBOL (IC_RIGHT (ic)), ic->lineno);
-
- debugLog (" %d - \n", __LINE__);
- if (ptrRegSet)
+ iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
+ /* add push to the start of the block */
+ addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ?
+ ebp->sch->next : ebp->sch));
+ nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
+ /* add pop to the end of the block */
+ addiCodeToeBBlock (ebp, nic, NULL);
+ }
+
+ /* if spilt because not used in the remainder of the
+ block then add a push before this instruction and
+ a pop at the end of the block */
+ if (ssym->remainSpil)
{
- debugLog (" %d - \n", __LINE__);
- pic14_ptrRegReq--;
- ptrRegSet = 0;
+
+ iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
+ /* add push just before this instruction */
+ addiCodeToeBBlock (ebp, nic, ic);
+
+ nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
+ /* add pop to the end of the block */
+ addiCodeToeBBlock (ebp, nic, NULL);
}
+
+ if (ssym == forSym)
+ return FALSE;
+ else
+ return TRUE;
+}
- }
- }
- }
+/*-----------------------------------------------------------------*/
+/* getRegPtr - will try for PTR if not a GPR type if not spil */
+/*-----------------------------------------------------------------*/
+static regs *
+getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym)
+{
+ regs *reg;
+ int j;
+
+ debugLog ("%s\n", __FUNCTION__);
+tryAgain:
+ /* try for a ptr type */
+ if ((reg = allocReg (REG_PTR)))
+ return reg;
+
+ /* try for gpr type */
+ if ((reg = allocReg (REG_GPR)))
+ return reg;
+
+ /* we have to spil */
+ if (!spilSomething (ic, ebp, sym))
+ return NULL;
+
+ /* make sure partially assigned registers aren't reused */
+ for (j=0; j<=sym->nRegs; j++)
+ if (sym->regs[j])
+ sym->regs[j]->isFree = 0;
+
+ /* this looks like an infinite loop but
+ in really selectSpil will abort */
+ goto tryAgain;
}
/*-----------------------------------------------------------------*/
-/* rUmaskForOp :- returns register mask for an operand */
+/* getRegGpr - will try for GPR if not spil */
/*-----------------------------------------------------------------*/
-static bitVect *
-rUmaskForOp (operand * op)
+static regs *
+getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
{
- bitVect *rumask;
- symbol *sym;
- int j;
+ regs *reg;
+ int j;
+
+ debugLog ("%s\n", __FUNCTION__);
+tryAgain:
+ /* try for gpr type */
+ if ((reg = allocReg (REG_GPR)))
+ return reg;
+
+ if (!pic14_ptrRegReq)
+ if ((reg = allocReg (REG_PTR)))
+ return reg;
+
+ /* we have to spil */
+ if (!spilSomething (ic, ebp, sym))
+ return NULL;
+
+ /* make sure partially assigned registers aren't reused */
+ for (j=0; j<=sym->nRegs; j++)
+ if (sym->regs[j])
+ sym->regs[j]->isFree = 0;
+
+ /* this looks like an infinite loop but
+ in really selectSpil will abort */
+ goto tryAgain;
+}
- debugLog ("%s\n", __FUNCTION__);
- /* only temporaries are assigned registers */
- if (!IS_ITEMP (op))
- return NULL;
+/*-----------------------------------------------------------------*/
+/* symHasReg - symbol has a given register */
+/*-----------------------------------------------------------------*/
+static bool
+symHasReg (symbol * sym, regs * reg)
+{
+ int i;
+
+ debugLog ("%s\n", __FUNCTION__);
+ for (i = 0; i < sym->nRegs; i++)
+ if (sym->regs[i] == reg)
+ return TRUE;
+
+ return FALSE;
+}
- sym = OP_SYMBOL (op);
+/*-----------------------------------------------------------------*/
+/* deassignLRs - check the live to and if they have registers & are */
+/* not spilt then free up the registers */
+/*-----------------------------------------------------------------*/
+static void
+deassignLRs (iCode * ic, eBBlock * ebp)
+{
+ symbol *sym;
+ int k;
+ symbol *result;
+
+ debugLog ("%s\n", __FUNCTION__);
+ for (sym = hTabFirstItem (liveRanges, &k); sym;
+ sym = hTabNextItem (liveRanges, &k))
+ {
+
+ symbol *psym = NULL;
+ /* if it does not end here */
+ if (sym->liveTo > ic->seq)
+ continue;
+
+ /* Prevent the result from being assigned the same registers as (one)
+ * operand as many genXXX-functions fail otherwise.
+ * POINTER_GET(ic) || ic->op == LEFT_OP || ic->op == RIGHT_OP || ic->op == NOT
+ * are known to fail. */
+ if (sym->liveTo == ic->seq && IC_RESULT(ic))
+ {
+ switch (ic->op)
+ {
+ case '=': /* assignment */
+ case BITWISEAND: /* bitwise AND */
+ case '|': /* bitwise OR */
+ case '^': /* bitwise XOR */
+ case '~': /* bitwise negate */
+ case RLC: /* rotate through carry */
+ case RRC:
+ case UNARYMINUS:
+ case '+': /* addition */
+ case '-': /* subtraction */
+ /* go ahead, these are safe to use with
+ * non-disjoint register sets */
+ break;
+
+ default:
+ /* do not release operand registers */
+ //fprintf (stderr, "%s:%u: operand not freed: ", __FILE__, __LINE__); piCode (ic, stderr); fprintf (stderr, "\n");
+ continue;
+ } // switch
+ }
+
+ /* if it was spilt on stack then we can
+ mark the stack spil location as free */
+ if (sym->isspilt)
+ {
+ if (sym->stackSpil)
+ {
+ sym->usl.spillLoc->isFree = 1;
+ sym->stackSpil = 0;
+ }
+ continue;
+ }
+
+ if (!bitVectBitValue (_G.regAssigned, sym->key))
+ continue;
+ /* special case check if this is an IFX &
+ the privious one was a pop and the
+ previous one was not spilt then keep track
+ of the symbol */
+ if (ic->op == IFX && ic->prev &&
+ ic->prev->op == IPOP &&
+ !ic->prev->parmPush &&
+ IS_SYMOP(IC_LEFT (ic->prev)) &&
+ !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt)
+ psym = OP_SYMBOL (IC_LEFT (ic->prev));
+
+ if (sym->nRegs)
+ {
+ int i = 0;
+
+ bitVectUnSetBit (_G.regAssigned, sym->key);
+
+ /* if the result of this one needs registers
+ and does not have it then assign it right
+ away */
+ if (IC_RESULT (ic) &&
+ !(SKIP_IC2 (ic) || /* not a special icode */
+ ic->op == JUMPTABLE ||
+ ic->op == IFX ||
+ ic->op == IPUSH ||
+ ic->op == IPOP ||
+ ic->op == RETURN ||
+ POINTER_SET (ic)) &&
+ IS_SYMOP (IC_RESULT (ic)) &&
+ (result = OP_SYMBOL (IC_RESULT (ic))) && /* has a result */
+ result->liveTo > ic->seq && /* and will live beyond this */
+ result->liveTo <= ebp->lSeq && /* does not go beyond this block */
+ result->liveFrom == ic->seq && /* does not start before here */
+ result->regType == sym->regType && /* same register types */
+ result->regType == sym->regType && /* same register types */
+ result->nRegs && /* which needs registers */
+ !result->isspilt && /* and does not already have them */
+ !result->remat &&
+ !bitVectBitValue (_G.regAssigned, result->key) &&
+ /* the number of free regs + number of regs in this LR
+ can accomodate the what result Needs */
+ ((nfreeRegsType (result->regType) +
+ sym->nRegs) >= result->nRegs)
+ )
+ {
+
+ for (i = 0; i < max (sym->nRegs, result->nRegs); i++)
+ if (i < sym->nRegs)
+ result->regs[i] = sym->regs[i];
+ else
+ result->regs[i] = getRegGpr (ic, ebp, result);
+
+ _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
+
+ }
+
+ /* free the remaining */
+ for (; i < sym->nRegs; i++)
+ {
+ if (psym)
+ {
+ if (!symHasReg (psym, sym->regs[i]))
+ freeReg (sym->regs[i]);
+ }
+ else
+ freeReg (sym->regs[i]);
+ }
+ }
+ }
+}
- /* if spilt or no registers assigned to it
- then nothing */
- if (sym->isspilt || !sym->nRegs)
- return NULL;
- rumask = newBitVect (pic14_nRegs);
+/*-----------------------------------------------------------------*/
+/* reassignLR - reassign this to registers */
+/*-----------------------------------------------------------------*/
+static void
+reassignLR (operand * op)
+{
+ symbol *sym = OP_SYMBOL (op);
+ int i;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* not spilt any more */
+ sym->isspilt = sym->blockSpil = sym->remainSpil = 0;
+ bitVectUnSetBit (_G.spiltSet, sym->key);
+
+ _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+
+ _G.blockSpil--;
+
+ for (i = 0; i < sym->nRegs; i++)
+ sym->regs[i]->isFree = 0;
+}
- for (j = 0; j < sym->nRegs; j++)
- {
- rumask = bitVectSetBit (rumask,
- sym->regs[j]->rIdx);
- }
+/*-----------------------------------------------------------------*/
+/* willCauseSpill - determines if allocating will cause a spill */
+/*-----------------------------------------------------------------*/
+static int
+willCauseSpill (int nr, int rt)
+{
+ debugLog ("%s\n", __FUNCTION__);
+ /* first check if there are any avlb registers
+ of te type required */
+ if (rt == REG_PTR)
+ {
+ /* special case for pointer type
+ if pointer type not avlb then
+ check for type gpr */
+ if (nFreeRegs (rt) >= nr)
+ return 0;
+ if (nFreeRegs (REG_GPR) >= nr)
+ return 0;
+ }
+ else
+ {
+ if (pic14_ptrRegReq)
+ {
+ if (nFreeRegs (rt) >= nr)
+ return 0;
+ }
+ else
+ {
+ if (nFreeRegs (REG_PTR) +
+ nFreeRegs (REG_GPR) >= nr)
+ return 0;
+ }
+ }
+
+ debugLog (" ... yep it will (cause a spill)\n");
+ /* it will cause a spil */
+ return 1;
+}
- return rumask;
+/*-----------------------------------------------------------------*/
+/* positionRegs - the allocator can allocate same registers to res- */
+/* ult and operand, if this happens make sure they are in the same */
+/* position as the operand otherwise chaos results */
+/*-----------------------------------------------------------------*/
+static void
+positionRegs (symbol * result, symbol * opsym, int lineno)
+{
+ int count = min (result->nRegs, opsym->nRegs);
+ int i, j = 0, shared = 0;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* if the result has been spilt then cannot share */
+ if (opsym->isspilt)
+ return;
+again:
+ shared = 0;
+ /* first make sure that they actually share */
+ for (i = 0; i < count; i++)
+ {
+ for (j = 0; j < count; j++)
+ {
+ if (result->regs[i] == opsym->regs[j] && i != j)
+ {
+ shared = 1;
+ goto xchgPositions;
+ }
+ }
+ }
+xchgPositions:
+ if (shared)
+ {
+ regs *tmp = result->regs[i];
+ result->regs[i] = result->regs[j];
+ result->regs[j] = tmp;
+ goto again;
+ }
+}
+
+/*------------------------------------------------------------------*/
+/* verifyRegsAssigned - make sure an iTemp is properly initialized; */
+/* it should either have registers or have beed spilled. Otherwise, */
+/* there was an uninitialized variable, so just spill this to get */
+/* the operand in a valid state. */
+/*------------------------------------------------------------------*/
+static void
+verifyRegsAssigned (operand *op, iCode * ic)
+{
+ symbol * sym;
+
+ if (!op) return;
+ if (!IS_ITEMP (op)) return;
+
+ sym = OP_SYMBOL (op);
+ if (sym->isspilt) return;
+ if (!sym->nRegs) return;
+ if (sym->regs[0]) return;
+
+ werrorfl (ic->filename, ic->lineno, W_LOCAL_NOINIT,
+ sym->prereqv ? sym->prereqv->name : sym->name);
+ spillThis (sym);
}
+
/*-----------------------------------------------------------------*/
-/* regsUsedIniCode :- returns bit vector of registers used in iCode */
+/* serialRegAssign - serially allocate registers to the variables */
/*-----------------------------------------------------------------*/
-static bitVect *
-regsUsedIniCode (iCode * ic)
+static void
+serialRegAssign (eBBlock ** ebbs, int count)
{
- bitVect *rmask = newBitVect (pic14_nRegs);
+ int i;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* for all blocks */
+ for (i = 0; i < count; i++)
+ {
+
+ iCode *ic;
+
+ if (ebbs[i]->noPath &&
+ (ebbs[i]->entryLabel != entryLabel &&
+ ebbs[i]->entryLabel != returnLabel))
+ continue;
+
+ /* of all instructions do */
+ for (ic = ebbs[i]->sch; ic; ic = ic->next)
+ {
+ debugLog (" op: %s\n", decodeOp (ic->op));
+
+ /* if this is an ipop that means some live
+ range will have to be assigned again */
+ if (ic->op == IPOP)
+ reassignLR (IC_LEFT (ic));
+
+ /* if result is present && is a true symbol */
+ if (IC_RESULT (ic) && ic->op != IFX &&
+ IS_TRUE_SYMOP (IC_RESULT (ic)))
+ OP_SYMBOL (IC_RESULT (ic))->allocreq = 1;
+
+ /* take away registers from live
+ ranges that end at this instruction */
+ deassignLRs (ic, ebbs[i]);
+
+ /* some don't need registers */
+ if (SKIP_IC2 (ic) ||
+ ic->op == JUMPTABLE ||
+ ic->op == IFX ||
+ ic->op == IPUSH ||
+ ic->op == IPOP ||
+ (IC_RESULT (ic) && POINTER_SET (ic)))
+ continue;
+
+ /* now we need to allocate registers
+ only for the result */
+ if (IC_RESULT (ic) && IS_SYMOP (IC_RESULT (ic)))
+ {
+ symbol *sym = OP_SYMBOL (IC_RESULT (ic));
+ bitVect *spillable;
+ int willCS;
+ int j;
+ int ptrRegSet = 0;
+
+ /* Make sure any spill location is definately allocated */
+ if (sym->isspilt && !sym->remat && sym->usl.spillLoc &&
+ !sym->usl.spillLoc->allocreq)
+ {
+ sym->usl.spillLoc->allocreq++;
+ }
+
+ /* if it does not need or is spilt
+ or is already assigned to registers
+ or will not live beyond this instructions */
+ if (!sym->nRegs ||
+ sym->isspilt ||
+ bitVectBitValue (_G.regAssigned, sym->key) ||
+ sym->liveTo <= ic->seq)
+ continue;
+
+ /* if some liverange has been spilt at the block level
+ and this one live beyond this block then spil this
+ to be safe */
+ if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq)
+ {
+ spillThis (sym);
+ continue;
+ }
+ /* if trying to allocate this will cause
+ a spill and there is nothing to spill
+ or this one is rematerializable then
+ spill this one */
+ willCS = willCauseSpill (sym->nRegs, sym->regType);
+ spillable = computeSpillable (ic);
+ if (sym->remat ||
+ (willCS && bitVectIsZero (spillable)))
+ {
+
+ spillThis (sym);
+ continue;
+
+ }
+
+ /* If the live range preceeds the point of definition
+ then ideally we must take into account registers that
+ have been allocated after sym->liveFrom but freed
+ before ic->seq. This is complicated, so spill this
+ symbol instead and let fillGaps handle the allocation. */
+ if (sym->liveFrom < ic->seq)
+ {
+ spillThis (sym);
+ continue;
+ }
+
+ /* if it has a spillocation & is used less than
+ all other live ranges then spill this */
+ if (willCS) {
+ if (sym->usl.spillLoc) {
+ symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
+ allLRs, ebbs[i], ic));
+ if (leastUsed && leastUsed->used > sym->used) {
+ spillThis (sym);
+ continue;
+ }
+ } else {
+ /* if none of the liveRanges have a spillLocation then better
+ to spill this one than anything else already assigned to registers */
+ if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
+ /* if this is local to this block then we might find a block spil */
+ if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
+ spillThis (sym);
+ continue;
+ }
+ }
+ }
+ }
+
+ if (ic->op == RECEIVE)
+ debugLog ("When I get clever, I'll optimize the receive logic\n");
+
+ /* if we need ptr regs for the right side
+ then mark it */
+ if (POINTER_GET (ic)
+ && IS_SYMOP(IC_LEFT(ic))
+ && getSize (OP_SYMBOL (IC_LEFT (ic))->type)
+ <= (unsigned) PTRSIZE)
+ {
+ pic14_ptrRegReq++;
+ ptrRegSet = 1;
+ }
+ /* else we assign registers to it */
+ _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+
+ debugLog (" %d - \n", __LINE__);
+ if(debugF)
+ bitVectDebugOn(_G.regAssigned, debugF);
+ for (j = 0; j < sym->nRegs; j++)
+ {
+ if (sym->regType == REG_PTR)
+ sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
+ else
+ sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
+
+ /* if the allocation failed which means
+ this was spilt then break */
+ if (!sym->regs[j])
+ break;
+ }
+ debugLog (" %d - \n", __LINE__);
+
+ /* if it shares registers with operands make sure
+ that they are in the same position */
+ if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
+ IS_SYMOP(IC_RESULT(ic)) &&
+ OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=')
+ positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+ OP_SYMBOL (IC_LEFT (ic)), ic->lineno);
+ /* do the same for the right operand */
+ if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
+ IS_SYMOP(IC_RESULT(ic)) &&
+ OP_SYMBOL (IC_RIGHT (ic))->nRegs && ic->op != '=')
+ positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+ OP_SYMBOL (IC_RIGHT (ic)), ic->lineno);
+
+ debugLog (" %d - \n", __LINE__);
+ if (ptrRegSet)
+ {
+ debugLog (" %d - \n", __LINE__);
+ pic14_ptrRegReq--;
+ ptrRegSet = 0;
+ }
+
+ }
+ }
+ }
+
+ /* Check for and fix any problems with uninitialized operands */
+ for (i = 0; i < count; i++)
+ {
+ iCode *ic;
- debugLog ("%s\n", __FUNCTION__);
- /* do the special cases first */
- if (ic->op == IFX)
- {
- rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_COND (ic)));
- goto ret;
- }
+ if (ebbs[i]->noPath &&
+ (ebbs[i]->entryLabel != entryLabel &&
+ ebbs[i]->entryLabel != returnLabel))
+ continue;
- /* for the jumptable */
- if (ic->op == JUMPTABLE)
- {
- rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_JTCOND (ic)));
+ for (ic = ebbs[i]->sch; ic; ic = ic->next)
+ {
+ if (SKIP_IC2 (ic))
+ continue;
- goto ret;
- }
+ if (ic->op == IFX)
+ {
+ verifyRegsAssigned (IC_COND (ic), ic);
+ continue;
+ }
- /* of all other cases */
- if (IC_LEFT (ic))
- rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_LEFT (ic)));
+ if (ic->op == JUMPTABLE)
+ {
+ verifyRegsAssigned (IC_JTCOND (ic), ic);
+ continue;
+ }
+ verifyRegsAssigned (IC_RESULT (ic), ic);
+ verifyRegsAssigned (IC_LEFT (ic), ic);
+ verifyRegsAssigned (IC_RIGHT (ic), ic);
+ }
+ }
- if (IC_RIGHT (ic))
- rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_RIGHT (ic)));
+}
- if (IC_RESULT (ic))
- rmask = bitVectUnion (rmask,
- rUmaskForOp (IC_RESULT (ic)));
+/*-----------------------------------------------------------------*/
+/* rUmaskForOp :- returns register mask for an operand */
+/*-----------------------------------------------------------------*/
+static bitVect *
+rUmaskForOp (operand * op)
+{
+ bitVect *rumask;
+ symbol *sym;
+ int j;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* only temporaries are assigned registers */
+ if (!IS_ITEMP (op))
+ return NULL;
+
+ sym = OP_SYMBOL (op);
+
+ /* if spilt or no registers assigned to it
+ then nothing */
+ if (sym->isspilt || !sym->nRegs)
+ return NULL;
+
+ rumask = newBitVect (pic14_nRegs);
+
+ for (j = 0; j < sym->nRegs; j++)
+ {
+ rumask = bitVectSetBit (rumask,
+ sym->regs[j]->rIdx);
+ }
+
+ return rumask;
+}
+/*-----------------------------------------------------------------*/
+/* regsUsedIniCode :- returns bit vector of registers used in iCode */
+/*-----------------------------------------------------------------*/
+static bitVect *
+regsUsedIniCode (iCode * ic)
+{
+ bitVect *rmask = newBitVect (pic14_nRegs);
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* do the special cases first */
+ if (ic->op == IFX)
+ {
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_COND (ic)));
+ goto ret;
+ }
+
+ /* for the jumptable */
+ if (ic->op == JUMPTABLE)
+ {
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_JTCOND (ic)));
+
+ goto ret;
+ }
+
+ /* of all other cases */
+ if (IC_LEFT (ic))
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_LEFT (ic)));
+
+
+ if (IC_RIGHT (ic))
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_RIGHT (ic)));
+
+ if (IC_RESULT (ic))
+ rmask = bitVectUnion (rmask,
+ rUmaskForOp (IC_RESULT (ic)));
+
ret:
- return rmask;
+ return rmask;
}
/*-----------------------------------------------------------------*/
static void
createRegMask (eBBlock ** ebbs, int count)
{
- int i;
-
- debugLog ("%s\n", __FUNCTION__);
- /* for all blocks */
- for (i = 0; i < count; i++)
- {
- iCode *ic;
-
- if (ebbs[i]->noPath &&
- (ebbs[i]->entryLabel != entryLabel &&
- ebbs[i]->entryLabel != returnLabel))
- continue;
-
- /* for all instructions */
- for (ic = ebbs[i]->sch; ic; ic = ic->next)
+ int i;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* for all blocks */
+ for (i = 0; i < count; i++)
{
-
- int j;
-
- if (SKIP_IC2 (ic) || !ic->rlive)
- continue;
-
- /* first mark the registers used in this
- instruction */
- ic->rUsed = regsUsedIniCode (ic);
- _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
-
- /* now create the register mask for those
- registers that are in use : this is a
- super set of ic->rUsed */
- ic->rMask = newBitVect (pic14_nRegs + 1);
-
- /* for all live Ranges alive at this point */
- for (j = 1; j < ic->rlive->size; j++)
- {
- symbol *sym;
- int k;
-
- /* if not alive then continue */
- if (!bitVectBitValue (ic->rlive, j))
- continue;
-
- /* find the live range we are interested in */
- if (!(sym = hTabItemWithKey (liveRanges, j)))
+ iCode *ic;
+
+ if (ebbs[i]->noPath &&
+ (ebbs[i]->entryLabel != entryLabel &&
+ ebbs[i]->entryLabel != returnLabel))
+ continue;
+
+ /* for all instructions */
+ for (ic = ebbs[i]->sch; ic; ic = ic->next)
{
- werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
- "createRegMask cannot find live range");
- exit (0);
+
+ int j;
+
+ if (SKIP_IC2 (ic) || !ic->rlive)
+ continue;
+
+ /* first mark the registers used in this
+ instruction */
+ ic->rUsed = regsUsedIniCode (ic);
+ _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
+
+ /* now create the register mask for those
+ registers that are in use : this is a
+ super set of ic->rUsed */
+ ic->rMask = newBitVect (pic14_nRegs + 1);
+
+ /* for all live Ranges alive at this point */
+ for (j = 1; j < ic->rlive->size; j++)
+ {
+ symbol *sym;
+ int k;
+
+ /* if not alive then continue */
+ if (!bitVectBitValue (ic->rlive, j))
+ continue;
+
+ /* find the live range we are interested in */
+ if (!(sym = hTabItemWithKey (liveRanges, j)))
+ {
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+ "createRegMask cannot find live range");
+ exit (0);
+ }
+
+ /* if no register assigned to it */
+ if (!sym->nRegs || sym->isspilt)
+ continue;
+
+ /* for all the registers allocated to it */
+ for (k = 0; k < sym->nRegs; k++)
+ if (sym->regs[k])
+ ic->rMask =
+ bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
+ }
}
-
- /* if no register assigned to it */
- if (!sym->nRegs || sym->isspilt)
- continue;
-
- /* for all the registers allocated to it */
- for (k = 0; k < sym->nRegs; k++)
- if (sym->regs[k])
- ic->rMask =
- bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
- }
}
- }
}
+#if 0
+/* This was the active version */
+/*-----------------------------------------------------------------*/
+/* rematStr - returns the rematerialized string for a remat var */
+/*-----------------------------------------------------------------*/
+static symbol *
+rematStr (symbol * sym)
+{
+ char *s = buffer;
+ iCode *ic = sym->rematiCode;
+ symbol *psym = NULL;
+
+ debugLog ("%s\n", __FUNCTION__);
+
+ //printf ("%s\n", s);
+
+ /* if plus or minus print the right hand side */
+
+ if (ic->op == '+' || ic->op == '-') {
+
+ iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+
+ sprintf (s, "(%s %c 0x%04x)",
+ OP_SYMBOL (IC_LEFT (ric))->rname,
+ ic->op,
+ (int) operandLitValue (IC_RIGHT (ic)));
+
+
+ //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
+
+ psym = newSymbol (OP_SYMBOL (IC_LEFT (ric))->rname, 1);
+ psym->offset = (int) operandLitValue (IC_RIGHT (ic));
+
+ return psym;
+ }
+
+ sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+ psym = newSymbol (OP_SYMBOL (IC_LEFT (ic))->rname, 1);
+
+ //printf ("ralloc.c:%d %s\n", __LINE__,buffer);
+ return psym;
+}
+#endif
+#if 0
+/* deprecated version */
/*-----------------------------------------------------------------*/
/* rematStr - returns the rematerialized string for a remat var */
/*-----------------------------------------------------------------*/
static char *
rematStr (symbol * sym)
{
- char *s = buffer;
- iCode *ic = sym->rematiCode;
-
- debugLog ("%s\n", __FUNCTION__);
- while (1)
- {
-
- printf ("%s\n", s);
- /* if plus or minus print the right hand side */
-/*
- if (ic->op == '+' || ic->op == '-') {
- sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
- ic->op );
- s += strlen(s);
- ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
- continue ;
- }
- */
- if (ic->op == '+' || ic->op == '-')
+ char *s = buffer;
+ iCode *ic = sym->rematiCode;
+
+ debugLog ("%s\n", __FUNCTION__);
+ while (1)
{
- iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
- sprintf (s, "(%s %c 0x%04x)",
- OP_SYMBOL (IC_LEFT (ric))->rname,
- ic->op,
- (int) operandLitValue (IC_RIGHT (ic)));
-
- //s += strlen(s);
- //ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
- //continue ;
- return buffer;
+
+ printf ("%s\n", s);
+ /* if plus or minus print the right hand side */
+ /*
+ if (ic->op == '+' || ic->op == '-') {
+ sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
+ ic->op );
+ s += strlen(s);
+ ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
+ continue ;
+ }
+ */
+ if (ic->op == '+' || ic->op == '-')
+ {
+ iCode *ric = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+ sprintf (s, "(%s %c 0x%04x)",
+ OP_SYMBOL (IC_LEFT (ric))->rname,
+ ic->op,
+ (int) operandLitValue (IC_RIGHT (ic)));
+
+ //s += strlen(s);
+ //ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
+ //continue ;
+ //fprintf(stderr, "ralloc.c:%d OOPS %s\n",__LINE__,s);
+ return buffer;
+ }
+
+ /* we reached the end */
+ sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+ break;
}
-
- /* we reached the end */
- sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
- break;
- }
-
- printf ("%s\n", buffer);
- return buffer;
+
+ printf ("%s\n", buffer);
+ return buffer;
}
+#endif
/*-----------------------------------------------------------------*/
/* regTypeNum - computes the type & number of registers required */
static void
regTypeNum ()
{
- symbol *sym;
- int k;
- iCode *ic;
-
- debugLog ("%s\n", __FUNCTION__);
- /* for each live range do */
- for (sym = hTabFirstItem (liveRanges, &k); sym;
- sym = hTabNextItem (liveRanges, &k)) {
-
- debugLog (" %d - %s\n", __LINE__, sym->rname);
-
- /* if used zero times then no registers needed */
- if ((sym->liveTo - sym->liveFrom) == 0)
- continue;
-
-
- /* if the live range is a temporary */
- if (sym->isitmp) {
-
- debugLog (" %d - itemp register\n", __LINE__);
-
- /* if the type is marked as a conditional */
- if (sym->regType == REG_CND)
- continue;
-
- /* if used in return only then we don't
- need registers */
- if (sym->ruonly || sym->accuse) {
- if (IS_AGGREGATE (sym->type) || sym->isptr)
- sym->type = aggrToPtr (sym->type, FALSE);
- debugLog (" %d - no reg needed - used as a return\n", __LINE__);
-
- continue;
- }
-
- /* if the symbol has only one definition &
- that definition is a get_pointer and the
- pointer we are getting is rematerializable and
- in "data" space */
-
- if (bitVectnBitsOn (sym->defs) == 1 &&
- (ic = hTabItemWithKey (iCodehTab,
- bitVectFirstBit (sym->defs))) &&
- POINTER_GET (ic) &&
- !sym->noSpilLoc &&
- !IS_BITVAR (sym->etype)) {
+ symbol *sym;
+ int k;
+ //iCode *ic;
-
- debugLog (" %d - \n", __LINE__);
-
- /* if remat in data space */
- if (OP_SYMBOL (IC_LEFT (ic))->remat &&
- DCL_TYPE (aggrToPtr (sym->type, FALSE)) == POINTER) {
-
- /* create a psuedo symbol & force a spil */
- symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
- psym->type = sym->type;
- psym->etype = sym->etype;
- strcpy (psym->rname, psym->name);
- sym->isspilt = 1;
- sym->usl.spillLoc = psym;
- continue;
+ debugLog ("%s\n", __FUNCTION__);
+ /* for each live range do */
+ for (sym = hTabFirstItem (liveRanges, &k); sym;
+ sym = hTabNextItem (liveRanges, &k)) {
+
+ debugLog (" %d - %s\n", __LINE__, sym->rname);
+
+ /* if used zero times then no registers needed */
+ if ((sym->liveTo - sym->liveFrom) == 0)
+ continue;
+
+
+ /* if the live range is a temporary */
+ if (sym->isitmp) {
+
+ debugLog (" %d - itemp register\n", __LINE__);
+
+ /* if the type is marked as a conditional */
+ if (sym->regType == REG_CND)
+ continue;
+
+ /* if used in return only then we don't
+ need registers */
+ if (sym->accuse) {
+ if (IS_AGGREGATE (sym->type) || sym->isptr)
+ sym->type = aggrToPtr (sym->type, FALSE);
+ debugLog (" %d - no reg needed - accumulator used\n", __LINE__);
+
+ continue;
+ }
+
+ if (sym->ruonly) {
+ //if (IS_AGGREGATE (sym->type) || sym->isptr)
+ // sym->type = aggrToPtr (sym->type, FALSE);
+ debugLog (" %d - used as a return\n", __LINE__);
+
+ //continue;
+ }
+
+ /* if the symbol has only one definition &
+ that definition is a get_pointer and the
+ pointer we are getting is rematerializable and
+ in "data" space */
+
+#if 0
+ if (bitVectnBitsOn (sym->defs) == 1 &&
+ (ic = hTabItemWithKey (iCodehTab,
+ bitVectFirstBit (sym->defs))) &&
+ POINTER_GET (ic) &&
+ !IS_BITVAR (sym->etype) &&
+ (aggrToPtrDclType (operandType (IC_LEFT (ic)), FALSE) == POINTER)) {
+
+ if (ptrPseudoSymSafe (sym, ic)) {
+
+ symbol *psym;
+
+ debugLog (" %d - \n", __LINE__);
+
+ /* create a pseudo symbol & force a spil */
+ //X symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
+ psym = rematStr (OP_SYMBOL (IC_LEFT (ic)));
+ psym->type = sym->type;
+ psym->etype = sym->etype;
+ psym->psbase = ptrBaseRematSym (OP_SYMBOL (IC_LEFT (ic)));
+ strcpy (psym->rname, psym->name);
+ sym->isspilt = 1;
+ sym->usl.spillLoc = psym;
+ continue;
+ }
+
+ /* if in data space or idata space then try to
+ allocate pointer register */
+
+ }
+#endif
+
+ /* if not then we require registers */
+ sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
+ getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
+ getSize (sym->type));
+
+
+ if(IS_PTR_CONST (sym->type)) {
+ debugLog (" %d const pointer type requires %d registers, changing to 2\n",__LINE__,sym->nRegs);
+ sym->nRegs = 2;
+ }
+
+ if (sym->nRegs > 4) {
+ fprintf (stderr, "allocated more than 4 or 0 registers for type ");
+ printTypeChain (sym->type, stderr);
+ fprintf (stderr, "\n");
+ }
+
+ /* determine the type of register required */
+ if (sym->nRegs == 1 &&
+ IS_PTR (sym->type) &&
+ sym->uptr)
+ sym->regType = REG_PTR;
+ else
+ sym->regType = REG_GPR;
+
+
+ debugLog (" reg name %s, reg type %s\n", sym->rname, debugLogRegType (sym->regType));
+
+ }
+ else
+ /* for the first run we don't provide */
+ /* registers for true symbols we will */
+ /* see how things go */
+ sym->nRegs = 0;
}
-
- /* if in data space or idata space then try to
- allocate pointer register */
-
- }
-
- /* if not then we require registers */
- sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
- getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
- getSize (sym->type));
-
- if (sym->nRegs > 4) {
- fprintf (stderr, "allocated more than 4 or 0 registers for type ");
- printTypeChain (sym->type, stderr);
- fprintf (stderr, "\n");
- }
-
- /* determine the type of register required */
- if (sym->nRegs == 1 &&
- IS_PTR (sym->type) &&
- sym->uptr)
- sym->regType = REG_PTR;
- else
- sym->regType = REG_GPR;
-
-
- debugLog (" reg name %s, reg type %s\n", sym->rname, debugLogRegType (sym->regType));
-
- }
- else
- /* for the first run we don't provide */
- /* registers for true symbols we will */
- /* see how things go */
- sym->nRegs = 0;
- }
-
+
+}
+DEFSETFUNC (markRegFree)
+{
+ ((regs *)item)->isFree = 1;
+
+ return 0;
}
+DEFSETFUNC (deallocReg)
+{
+ fprintf(stderr,"deallocting register %s\n",((regs *)item)->name);
+ ((regs *)item)->isFree = 1;
+ ((regs *)item)->wasUsed = 0;
+
+ return 0;
+}
/*-----------------------------------------------------------------*/
/* freeAllRegs - mark all registers as free */
/*-----------------------------------------------------------------*/
void
pic14_freeAllRegs ()
{
- int i;
-
- debugLog ("%s\n", __FUNCTION__);
- for (i = 0; i < pic14_nRegs; i++)
- regspic14[i].isFree = 1;
+ // int i;
+
+ debugLog ("%s\n", __FUNCTION__);
+
+ applyToSet(dynAllocRegs,markRegFree);
+ applyToSet(dynStackRegs,markRegFree);
+
+ /*
+ for (i = 0; i < pic14_nRegs; i++)
+ regspic14[i].isFree = 1;
+ */
}
/*-----------------------------------------------------------------*/
void
pic14_deallocateAllRegs ()
{
- int i;
-
- debugLog ("%s\n", __FUNCTION__);
- for (i = 0; i < pic14_nRegs; i++) {
- regspic14[i].isFree = 1;
- regspic14[i].wasUsed = 0;
- }
+ // int i;
+
+ debugLog ("%s\n", __FUNCTION__);
+
+ applyToSet(dynAllocRegs,deallocReg);
+
+ /*
+ for (i = 0; i < pic14_nRegs; i++) {
+ if(regspic14[i].pc_type == PO_GPR_TEMP) {
+ regspic14[i].isFree = 1;
+ regspic14[i].wasUsed = 0;
+ }
+ }
+ */
}
static
DEFSETFUNC (deallocStackSpil)
{
- symbol *sym = item;
-
- debugLog ("%s\n", __FUNCTION__);
- deallocLocal (sym);
- return 0;
+ symbol *sym = item;
+
+ debugLog ("%s\n", __FUNCTION__);
+ deallocLocal (sym);
+ return 0;
}
/*-----------------------------------------------------------------*/
static iCode *
farSpacePackable (iCode * ic)
{
- iCode *dic;
-
- debugLog ("%s\n", __FUNCTION__);
- /* go thru till we find a definition for the
- symbol on the right */
- for (dic = ic->prev; dic; dic = dic->prev)
- {
-
- /* if the definition is a call then no */
- if ((dic->op == CALL || dic->op == PCALL) &&
- IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+ iCode *dic;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* go thru till we find a definition for the
+ symbol on the right */
+ for (dic = ic->prev; dic; dic = dic->prev)
{
- return NULL;
+
+ /* if the definition is a call then no */
+ if ((dic->op == CALL || dic->op == PCALL) &&
+ IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+ {
+ return NULL;
+ }
+
+ /* if shift by unknown amount then not */
+ if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) &&
+ IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+ return NULL;
+
+ /* if pointer get and size > 1 */
+ if (POINTER_GET (dic) &&
+ getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1)
+ return NULL;
+
+ if (POINTER_SET (dic) &&
+ getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
+ return NULL;
+
+ /* if any three is a true symbol in far space */
+ if (IC_RESULT (dic) &&
+ IS_TRUE_SYMOP (IC_RESULT (dic)) &&
+ isOperandInFarSpace (IC_RESULT (dic)))
+ return NULL;
+
+ if (IC_RIGHT (dic) &&
+ IS_TRUE_SYMOP (IC_RIGHT (dic)) &&
+ isOperandInFarSpace (IC_RIGHT (dic)) &&
+ !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic)))
+ return NULL;
+
+ if (IC_LEFT (dic) &&
+ IS_TRUE_SYMOP (IC_LEFT (dic)) &&
+ isOperandInFarSpace (IC_LEFT (dic)) &&
+ !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic)))
+ return NULL;
+
+ if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic)))
+ {
+ if ((dic->op == LEFT_OP ||
+ dic->op == RIGHT_OP ||
+ dic->op == '-') &&
+ IS_OP_LITERAL (IC_RIGHT (dic)))
+ return NULL;
+ else
+ return dic;
+ }
}
-
- /* if shift by unknown amount then not */
- if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) &&
- IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
- return NULL;
-
- /* if pointer get and size > 1 */
- if (POINTER_GET (dic) &&
- getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1)
- return NULL;
-
- if (POINTER_SET (dic) &&
- getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
- return NULL;
-
- /* if any three is a true symbol in far space */
- if (IC_RESULT (dic) &&
- IS_TRUE_SYMOP (IC_RESULT (dic)) &&
- isOperandInFarSpace (IC_RESULT (dic)))
- return NULL;
-
- if (IC_RIGHT (dic) &&
- IS_TRUE_SYMOP (IC_RIGHT (dic)) &&
- isOperandInFarSpace (IC_RIGHT (dic)) &&
- !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic)))
- return NULL;
-
- if (IC_LEFT (dic) &&
- IS_TRUE_SYMOP (IC_LEFT (dic)) &&
- isOperandInFarSpace (IC_LEFT (dic)) &&
- !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic)))
+
return NULL;
-
- if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic)))
- {
- if ((dic->op == LEFT_OP ||
- dic->op == RIGHT_OP ||
- dic->op == '-') &&
- IS_OP_LITERAL (IC_RIGHT (dic)))
- return NULL;
- else
- return dic;
- }
- }
-
- return NULL;
}
/*-----------------------------------------------------------------*/
static int
packRegsForAssign (iCode * ic, eBBlock * ebp)
{
-
- iCode *dic, *sic;
-
- debugLog ("%s\n", __FUNCTION__);
-
- debugAopGet (" result:", IC_RESULT (ic));
- debugAopGet (" left:", IC_LEFT (ic));
- debugAopGet (" right:", IC_RIGHT (ic));
-
- if (!IS_ITEMP (IC_RIGHT (ic)) ||
- OP_SYMBOL (IC_RIGHT (ic))->isind ||
- OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
- {
- debugLog (" %d - not packing - right side fails \n", __LINE__);
- return 0;
- }
-
- /* if the true symbol is defined in far space or on stack
- then we should not since this will increase register pressure */
- if (isOperandInFarSpace (IC_RESULT (ic)))
- {
- if ((dic = farSpacePackable (ic)))
- goto pack;
- else
- return 0;
-
- }
- /* find the definition of iTempNN scanning backwards if we find a
- a use of the true symbol before we find the definition then
- we cannot pack */
- for (dic = ic->prev; dic; dic = dic->prev)
- {
-
- /* if there is a function call and this is
- a parameter & not my parameter then don't pack it */
- if ((dic->op == CALL || dic->op == PCALL) &&
- (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
- !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
- {
- debugLog (" %d - \n", __LINE__);
- dic = NULL;
- break;
+
+ iCode *dic, *sic;
+
+ debugLog ("%s\n", __FUNCTION__);
+
+ debugAopGet (" result:", IC_RESULT (ic));
+ debugAopGet (" left:", IC_LEFT (ic));
+ debugAopGet (" right:", IC_RIGHT (ic));
+
+ /* if this is at an absolute address, then get the address. */
+ if (SPEC_ABSA ( OP_SYM_ETYPE(IC_RESULT(ic))) ) {
+ if(IS_CONFIG_ADDRESS( SPEC_ADDR ( OP_SYM_ETYPE(IC_RESULT(ic))))) {
+ debugLog (" %d - found config word declaration\n", __LINE__);
+ if(IS_VALOP(IC_RIGHT(ic))) {
+ debugLog (" setting config word to %x\n",
+ (int) floatFromVal (IC_RIGHT(ic)->operand.valOperand));
+ pic14_assignConfigWordValue( SPEC_ADDR ( OP_SYM_ETYPE(IC_RESULT(ic))),
+ (int) floatFromVal (IC_RIGHT(ic)->operand.valOperand));
+ }
+
+ /* remove the assignment from the iCode chain. */
+
+ remiCodeFromeBBlock (ebp, ic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+ hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+
+ return 1;
+
+ }
}
-
- if (SKIP_IC2 (dic))
- continue;
-
- if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
- IS_OP_VOLATILE (IC_RESULT (dic)))
+
+ if (!IS_ITEMP (IC_RESULT (ic))) {
+ allocDirReg(IC_RESULT (ic));
+ debugLog (" %d - result is not temp\n", __LINE__);
+ }
+ /*
+ if (IC_LEFT (ic) && !IS_ITEMP (IC_LEFT (ic))) {
+ debugLog (" %d - left is not temp, allocating\n", __LINE__);
+ allocDirReg(IC_LEFT (ic));
+ }
+ */
+
+ if (!IS_ITEMP (IC_RIGHT (ic))) {
+ debugLog (" %d - not packing - right is not temp\n", __LINE__);
+
+ /* only pack if this is not a function pointer */
+ if (!IS_REF (IC_RIGHT (ic)))
+ allocDirReg(IC_RIGHT (ic));
+ return 0;
+ }
+
+ if (OP_SYMBOL (IC_RIGHT (ic))->isind ||
+ OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
{
- debugLog (" %d - \n", __LINE__);
- dic = NULL;
- break;
+ debugLog (" %d - not packing - right side fails \n", __LINE__);
+ return 0;
}
-
- if (IS_SYMOP (IC_RESULT (dic)) &&
- IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+
+ /* if the true symbol is defined in far space or on stack
+ then we should not since this will increase register pressure */
+ if (isOperandInFarSpace (IC_RESULT (ic)))
{
- debugLog (" %d - dic key == ic key -- pointer set=%c\n", __LINE__, ((POINTER_SET (dic)) ? 'Y' : 'N'));
- if (POINTER_SET (dic))
- dic = NULL;
-
- break;
+ if ((dic = farSpacePackable (ic)))
+ goto pack;
+ else
+ return 0;
+
}
-
- if (IS_SYMOP (IC_RIGHT (dic)) &&
- (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
- IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
+ /* find the definition of iTempNN scanning backwards if we find a
+ a use of the true symbol before we find the definition then
+ we cannot pack */
+ for (dic = ic->prev; dic; dic = dic->prev)
{
- debugLog (" %d - \n", __LINE__);
- dic = NULL;
- break;
+
+ /* if there is a function call and this is
+ a parameter & not my parameter then don't pack it */
+ if ((dic->op == CALL || dic->op == PCALL) &&
+ (OP_SYMBOL (IC_RESULT (ic))->_isparm &&
+ !OP_SYMBOL (IC_RESULT (ic))->ismyparm))
+ {
+ debugLog (" %d - \n", __LINE__);
+ dic = NULL;
+ break;
+ }
+
+ if (SKIP_IC2 (dic))
+ continue;
+
+ if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
+ IS_OP_VOLATILE (IC_RESULT (dic)))
+ {
+ debugLog (" %d - dic is VOLATILE \n", __LINE__);
+ dic = NULL;
+ break;
+ }
+
+ if (IS_SYMOP (IC_RESULT (dic)) &&
+ IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+ {
+ /* A previous result was assigned to the same register - we'll our definition */
+ debugLog (" %d - dic result key == ic right key -- pointer set=%c\n",
+ __LINE__, ((POINTER_SET (dic)) ? 'Y' : 'N'));
+ if (POINTER_SET (dic))
+ dic = NULL;
+
+ break;
+ }
+
+ if (IS_SYMOP (IC_RIGHT (dic)) &&
+ (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
+ IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
+ {
+ debugLog (" %d - dic right key == ic rightor result key\n", __LINE__);
+ dic = NULL;
+ break;
+ }
+
+ if (IS_SYMOP (IC_LEFT (dic)) &&
+ (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
+ IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
+ {
+ debugLog (" %d - dic left key == ic rightor result key\n", __LINE__);
+ dic = NULL;
+ break;
+ }
+
+ if (POINTER_SET (dic) &&
+ IC_RESULT (dic)->key == IC_RESULT (ic)->key)
+ {
+ debugLog (" %d - dic result key == ic result key -- pointer set=Y\n",
+ __LINE__);
+ dic = NULL;
+ break;
+ }
}
-
- if (IS_SYMOP (IC_LEFT (dic)) &&
- (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
- IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
+
+ if (!dic)
+ return 0; /* did not find */
+
+ /* if assignment then check that right is not a bit */
+ if (ASSIGNMENT (ic) && !POINTER_SET (ic))
{
- debugLog (" %d - \n", __LINE__);
- dic = NULL;
- break;
+ sym_link *etype = operandType (IC_RESULT (dic));
+ if (IS_BITFIELD (etype))
+ {
+ /* if result is a bit too then it's ok */
+ etype = operandType (IC_RESULT (ic));
+ if (!IS_BITFIELD (etype))
+ return 0;
+ }
}
- if (POINTER_SET (dic) &&
- IC_RESULT (dic)->key == IC_RESULT (ic)->key)
+ /* if the result is on stack or iaccess then it must be
+ the same at least one of the operands */
+ if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
+ OP_SYMBOL (IC_RESULT (ic))->iaccess)
{
- debugLog (" %d - \n", __LINE__);
- dic = NULL;
- break;
- }
- }
-
- if (!dic)
- return 0; /* did not find */
-
- /* if the result is on stack or iaccess then it must be
- the same atleast one of the operands */
- if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
- OP_SYMBOL (IC_RESULT (ic))->iaccess)
- {
-
- /* the operation has only one symbol
- operator then we can pack */
- if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) ||
- (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
- goto pack;
-
- if (!((IC_LEFT (dic) &&
- IC_RESULT (ic)->key == IC_LEFT (dic)->key) ||
- (IC_RIGHT (dic) &&
- IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
- return 0;
- }
+
+ /* the operation has only one symbol
+ operator then we can pack */
+ if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) ||
+ (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
+ goto pack;
+
+ if (!((IC_LEFT (dic) &&
+ IC_RESULT (ic)->key == IC_LEFT (dic)->key) ||
+ (IC_RIGHT (dic) &&
+ IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
+ return 0;
+ }
pack:
- debugLog (" packing. removing %s\n", OP_SYMBOL (IC_RIGHT (ic))->rname);
- /* found the definition */
- /* replace the result with the result of */
- /* this assignment and remove this assignment */
- IC_RESULT (dic) = IC_RESULT (ic);
-
- if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
- {
- OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
- }
- /* delete from liverange table also
- delete from all the points inbetween and the new
- one */
- for (sic = dic; sic != ic; sic = sic->next)
- {
- bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
- if (IS_ITEMP (IC_RESULT (dic)))
- bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
- }
-
- remiCodeFromeBBlock (ebp, ic);
- hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
- OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
- return 1;
-
-
+ debugLog (" packing. removing %s\n", OP_SYMBOL (IC_RIGHT (ic))->rname);
+ debugLog (" replacing with %s\n", OP_SYMBOL (IC_RESULT (dic))->rname);
+ /* found the definition */
+ /* replace the result with the result of */
+ /* this assignment and remove this assignment */
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+ IC_RESULT (dic) = IC_RESULT (ic);
+
+ if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
+ {
+ OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
+ }
+ /* delete from liverange table also
+ delete from all the points inbetween and the new
+ one */
+ for (sic = dic; sic != ic; sic = sic->next)
+ {
+ bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
+ if (IS_ITEMP (IC_RESULT (dic)))
+ bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
+ }
+
+ remiCodeFromeBBlock (ebp, ic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+ hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+ OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+ return 1;
+
+
}
/*-----------------------------------------------------------------*/
static iCode *
findAssignToSym (operand * op, iCode * ic)
{
- iCode *dic;
-
- debugLog ("%s\n", __FUNCTION__);
- for (dic = ic->prev; dic; dic = dic->prev)
- {
-
- /* if definition by assignment */
- if (dic->op == '=' &&
- !POINTER_SET (dic) &&
- IC_RESULT (dic)->key == op->key
-/* && IS_TRUE_SYMOP(IC_RIGHT(dic)) */
- )
+ iCode *dic;
+
+ debugLog ("%s\n", __FUNCTION__);
+ for (dic = ic->prev; dic; dic = dic->prev)
{
-
- /* we are interested only if defined in far space */
- /* or in stack space in case of + & - */
-
- /* if assigned to a non-symbol then return
- true */
- if (!IS_SYMOP (IC_RIGHT (dic)))
- break;
-
- /* if the symbol is in far space then
- we should not */
- if (isOperandInFarSpace (IC_RIGHT (dic)))
- return NULL;
-
- /* for + & - operations make sure that
- if it is on the stack it is the same
- as one of the three operands */
- if ((ic->op == '+' || ic->op == '-') &&
- OP_SYMBOL (IC_RIGHT (dic))->onStack)
- {
-
- if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
- IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
- IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
- return NULL;
- }
-
- break;
-
+
+ /* if definition by assignment */
+ if (dic->op == '=' &&
+ !POINTER_SET (dic) &&
+ IC_RESULT (dic)->key == op->key
+ /* && IS_TRUE_SYMOP(IC_RIGHT(dic)) */
+ )
+ {
+
+ /* we are interested only if defined in far space */
+ /* or in stack space in case of + & - */
+
+ /* if assigned to a non-symbol then return
+ true */
+ if (!IS_SYMOP (IC_RIGHT (dic)))
+ break;
+
+ /* if the symbol is in far space then
+ we should not */
+ if (isOperandInFarSpace (IC_RIGHT (dic)))
+ return NULL;
+
+ /* for + & - operations make sure that
+ if it is on the stack it is the same
+ as one of the three operands */
+ if ((ic->op == '+' || ic->op == '-') &&
+ OP_SYMBOL (IC_RIGHT (dic))->onStack)
+ {
+
+ if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
+ IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
+ IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
+ return NULL;
+ }
+
+ break;
+
+ }
+
+ /* if we find an usage then we cannot delete it */
+ if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
+ return NULL;
+
+ if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
+ return NULL;
+
+ if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
+ return NULL;
}
-
- /* if we find an usage then we cannot delete it */
- if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
- return NULL;
-
- if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
- return NULL;
-
- if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
- return NULL;
- }
-
- /* now make sure that the right side of dic
- is not defined between ic & dic */
- if (dic)
- {
- iCode *sic = dic->next;
-
- for (; sic != ic; sic = sic->next)
- if (IC_RESULT (sic) &&
- IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
- return NULL;
- }
-
- return dic;
-
-
+
+ /* now make sure that the right side of dic
+ is not defined between ic & dic */
+ if (dic)
+ {
+ iCode *sic = dic->next;
+
+ for (; sic != ic; sic = sic->next)
+ if (IC_RESULT (sic) &&
+ IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
+ return NULL;
+ }
+
+ return dic;
+
+
}
/*-----------------------------------------------------------------*/
static int
packRegsForSupport (iCode * ic, eBBlock * ebp)
{
- int change = 0;
-
- debugLog ("%s\n", __FUNCTION__);
- /* for the left & right operand :- look to see if the
- left was assigned a true symbol in far space in that
- case replace them */
- if (IS_ITEMP (IC_LEFT (ic)) &&
- OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
- {
- iCode *dic = findAssignToSym (IC_LEFT (ic), ic);
- iCode *sic;
-
- if (!dic)
- goto right;
-
- debugAopGet ("removing left:", IC_LEFT (ic));
-
- /* found it we need to remove it from the
- block */
- for (sic = dic; sic != ic; sic = sic->next)
- bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
-
- IC_LEFT (ic)->operand.symOperand =
- IC_RIGHT (dic)->operand.symOperand;
- IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
- remiCodeFromeBBlock (ebp, dic);
- hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
- change++;
- }
-
- /* do the same for the right operand */
+ int change = 0;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* for the left & right operand :- look to see if the
+ left was assigned a true symbol in far space in that
+ case replace them */
+ if (IS_ITEMP (IC_LEFT (ic)) &&
+ OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
+ {
+ iCode *dic = findAssignToSym (IC_LEFT (ic), ic);
+ iCode *sic;
+
+ if (!dic)
+ goto right;
+
+ debugAopGet ("removing left:", IC_LEFT (ic));
+
+ /* found it we need to remove it from the
+ block */
+ for (sic = dic; sic != ic; sic = sic->next)
+ bitVectUnSetBit (sic->rlive, IC_LEFT (ic)->key);
+
+ IC_LEFT (ic)->operand.symOperand =
+ IC_RIGHT (dic)->operand.symOperand;
+ IC_LEFT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+ remiCodeFromeBBlock (ebp, dic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+ hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+ change++;
+ }
+
+ /* do the same for the right operand */
right:
- if (!change &&
- IS_ITEMP (IC_RIGHT (ic)) &&
- OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
- {
- iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
- iCode *sic;
-
- if (!dic)
- return change;
-
- /* if this is a subtraction & the result
- is a true symbol in far space then don't pack */
- if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
+ if (!change &&
+ IS_ITEMP (IC_RIGHT (ic)) &&
+ OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
{
- sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
- if (IN_FARSPACE (SPEC_OCLS (etype)))
- return change;
+ iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
+ iCode *sic;
+
+ if (!dic)
+ return change;
+
+ /* if this is a subtraction & the result
+ is a true symbol in far space then don't pack */
+ if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
+ {
+ sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
+ if (IN_FARSPACE (SPEC_OCLS (etype)))
+ return change;
+ }
+
+ debugAopGet ("removing right:", IC_RIGHT (ic));
+
+ /* found it we need to remove it from the
+ block */
+ for (sic = dic; sic != ic; sic = sic->next)
+ bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
+
+ IC_RIGHT (ic)->operand.symOperand =
+ IC_RIGHT (dic)->operand.symOperand;
+ IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
+
+ remiCodeFromeBBlock (ebp, dic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+ hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+ change++;
}
-
- debugAopGet ("removing right:", IC_RIGHT (ic));
-
- /* found it we need to remove it from the
- block */
- for (sic = dic; sic != ic; sic = sic->next)
- bitVectUnSetBit (sic->rlive, IC_RIGHT (ic)->key);
-
- IC_RIGHT (ic)->operand.symOperand =
- IC_RIGHT (dic)->operand.symOperand;
- IC_RIGHT (ic)->key = IC_RIGHT (dic)->operand.symOperand->key;
-
- remiCodeFromeBBlock (ebp, dic);
- hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
- change++;
- }
-
- return change;
+
+ return change;
}
#define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
static iCode *
packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
{
- bitVect *uses;
- iCode *dic, *sic;
-
- debugLog ("%s\n", __FUNCTION__);
- /* if returning a literal then do nothing */
- if (!IS_SYMOP (op))
- return NULL;
-
- /* only upto 2 bytes since we cannot predict
- the usage of b, & acc */
- if (getSize (operandType (op)) > (fReturnSizePic - 2) &&
- ic->op != RETURN &&
- ic->op != SEND)
- return NULL;
-
- /* this routine will mark the a symbol as used in one
- instruction use only && if the definition is local
- (ie. within the basic block) && has only one definition &&
- that definition is either a return value from a
- function or does not contain any variables in
- far space */
- uses = bitVectCopy (OP_USES (op));
- bitVectUnSetBit (uses, ic->key); /* take away this iCode */
- if (!bitVectIsZero (uses)) /* has other uses */
- return NULL;
-
- /* if it has only one defintion */
- if (bitVectnBitsOn (OP_DEFS (op)) > 1)
- return NULL; /* has more than one definition */
-
- /* get that definition */
- if (!(dic =
- hTabItemWithKey (iCodehTab,
- bitVectFirstBit (OP_DEFS (op)))))
- return NULL;
-
- /* found the definition now check if it is local */
- if (dic->seq < ebp->fSeq ||
- dic->seq > ebp->lSeq)
- return NULL; /* non-local */
-
- /* now check if it is the return from
- a function call */
- if (dic->op == CALL || dic->op == PCALL)
- {
- if (ic->op != SEND && ic->op != RETURN)
+ bitVect *uses;
+ iCode *dic, *sic;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* if returning a literal then do nothing */
+ if (!IS_SYMOP (op))
+ return NULL;
+
+ /* only upto 2 bytes since we cannot predict
+ the usage of b, & acc */
+ if (getSize (operandType (op)) > (fReturnSizePic - 2) &&
+ ic->op != RETURN &&
+ ic->op != SEND)
+ return NULL;
+
+ /* this routine will mark the a symbol as used in one
+ instruction use only && if the definition is local
+ (ie. within the basic block) && has only one definition &&
+ that definition is either a return value from a
+ function or does not contain any variables in
+ far space */
+ uses = bitVectCopy (OP_USES (op));
+ bitVectUnSetBit (uses, ic->key); /* take away this iCode */
+ if (!bitVectIsZero (uses)) /* has other uses */
+ return NULL;
+
+ /* if it has only one defintion */
+ if (bitVectnBitsOn (OP_DEFS (op)) > 1)
+ return NULL; /* has more than one definition */
+
+ /* get that definition */
+ if (!(dic =
+ hTabItemWithKey (iCodehTab,
+ bitVectFirstBit (OP_DEFS (op)))))
+ return NULL;
+
+ /* found the definition now check if it is local */
+ if (dic->seq < ebp->fSeq ||
+ dic->seq > ebp->lSeq)
+ return NULL; /* non-local */
+
+ /* now check if it is the return from
+ a function call */
+ if (dic->op == CALL || dic->op == PCALL)
{
- OP_SYMBOL (op)->ruonly = 1;
- return dic;
- }
- dic = dic->next;
- }
-
-
- /* otherwise check that the definition does
- not contain any symbols in far space */
- if (isOperandInFarSpace (IC_LEFT (dic)) ||
- isOperandInFarSpace (IC_RIGHT (dic)) ||
- IS_OP_RUONLY (IC_LEFT (ic)) ||
- IS_OP_RUONLY (IC_RIGHT (ic)))
- {
- return NULL;
- }
-
- /* if pointer set then make sure the pointer
- is one byte */
- if (POINTER_SET (dic) &&
- !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
- return NULL;
-
- if (POINTER_GET (dic) &&
- !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
- return NULL;
-
- sic = dic;
-
- /* also make sure the intervenening instructions
- don't have any thing in far space */
- for (dic = dic->next; dic && dic != ic; dic = dic->next)
- {
-
- /* if there is an intervening function call then no */
- if (dic->op == CALL || dic->op == PCALL)
- return NULL;
- /* if pointer set then make sure the pointer
- is one byte */
- if (POINTER_SET (dic) &&
- !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
- return NULL;
-
- if (POINTER_GET (dic) &&
- !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
- return NULL;
-
- /* if address of & the result is remat then okay */
- if (dic->op == ADDRESS_OF &&
- OP_SYMBOL (IC_RESULT (dic))->remat)
- continue;
-
- /* if operand has size of three or more & this
- operation is a '*','/' or '%' then 'b' may
- cause a problem */
- if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
- getSize (operandType (op)) >= 3)
- return NULL;
-
- /* if left or right or result is in far space */
- if (isOperandInFarSpace (IC_LEFT (dic)) ||
- isOperandInFarSpace (IC_RIGHT (dic)) ||
- isOperandInFarSpace (IC_RESULT (dic)) ||
- IS_OP_RUONLY (IC_LEFT (dic)) ||
- IS_OP_RUONLY (IC_RIGHT (dic)) ||
- IS_OP_RUONLY (IC_RESULT (dic)))
+ if (ic->op != SEND && ic->op != RETURN &&
+ !POINTER_SET(ic) && !POINTER_GET(ic))
+ {
+ OP_SYMBOL (op)->ruonly = 1;
+ return dic;
+ }
+ dic = dic->next;
+ }
+
+
+ /* otherwise check that the definition does
+ not contain any symbols in far space */
+ if (isOperandInFarSpace (IC_LEFT (dic)) ||
+ isOperandInFarSpace (IC_RIGHT (dic)) ||
+ IS_OP_RUONLY (IC_LEFT (ic)) ||
+ IS_OP_RUONLY (IC_RIGHT (ic)))
{
- return NULL;
+ return NULL;
}
- }
-
- OP_SYMBOL (op)->ruonly = 1;
- return sic;
-
+
+ /* if pointer set then make sure the pointer
+ is one byte */
+ if (POINTER_SET (dic) &&
+ !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
+ return NULL;
+
+ if (POINTER_GET (dic) &&
+ !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
+ return NULL;
+
+ sic = dic;
+
+ /* also make sure the intervenening instructions
+ don't have any thing in far space */
+ for (dic = dic->next; dic && dic != ic; dic = dic->next)
+ {
+
+ /* if there is an intervening function call then no */
+ if (dic->op == CALL || dic->op == PCALL)
+ return NULL;
+ /* if pointer set then make sure the pointer
+ is one byte */
+ if (POINTER_SET (dic) &&
+ !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
+ return NULL;
+
+ if (POINTER_GET (dic) &&
+ !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
+ return NULL;
+
+ /* if address of & the result is remat then okay */
+ if (dic->op == ADDRESS_OF &&
+ OP_SYMBOL (IC_RESULT (dic))->remat)
+ continue;
+
+ /* if operand has size of three or more & this
+ operation is a '*','/' or '%' then 'b' may
+ cause a problem */
+ if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
+ getSize (operandType (op)) >= 3)
+ return NULL;
+
+ /* if left or right or result is in far space */
+ if (isOperandInFarSpace (IC_LEFT (dic)) ||
+ isOperandInFarSpace (IC_RIGHT (dic)) ||
+ isOperandInFarSpace (IC_RESULT (dic)) ||
+ IS_OP_RUONLY (IC_LEFT (dic)) ||
+ IS_OP_RUONLY (IC_RIGHT (dic)) ||
+ IS_OP_RUONLY (IC_RESULT (dic)))
+ {
+ return NULL;
+ }
+ }
+
+ OP_SYMBOL (op)->ruonly = 1;
+ return sic;
+
}
/*-----------------------------------------------------------------*/
static bool
isBitwiseOptimizable (iCode * ic)
{
- sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
- sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
-
- debugLog ("%s\n", __FUNCTION__);
- /* bitwise operations are considered optimizable
- under the following conditions (Jean-Louis VERN)
-
- x & lit
- bit & bit
- bit & x
- bit ^ bit
- bit ^ x
- x ^ lit
- x | lit
- bit | bit
- bit | x
- */
- if (IS_LITERAL (rtype) ||
- (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
- return TRUE;
- else
- return FALSE;
+ sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
+ sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* bitwise operations are considered optimizable
+ under the following conditions (Jean-Louis VERN)
+
+ x & lit
+ bit & bit
+ bit & x
+ bit ^ bit
+ bit ^ x
+ x ^ lit
+ x | lit
+ bit | bit
+ bit | x
+ */
+ if (IS_LITERAL (rtype) ||
+ (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
+ return TRUE;
+ else
+ return FALSE;
}
/*-----------------------------------------------------------------*/
static void
packRegsForAccUse (iCode * ic)
{
- iCode *uic;
-
- debugLog ("%s\n", __FUNCTION__);
- /* if + or - then it has to be one byte result */
- if ((ic->op == '+' || ic->op == '-')
- && getSize (operandType (IC_RESULT (ic))) > 1)
- return;
-
- /* if shift operation make sure right side is not a literal */
- if (ic->op == RIGHT_OP &&
- (isOperandLiteral (IC_RIGHT (ic)) ||
- getSize (operandType (IC_RESULT (ic))) > 1))
- return;
-
- if (ic->op == LEFT_OP &&
- (isOperandLiteral (IC_RIGHT (ic)) ||
- getSize (operandType (IC_RESULT (ic))) > 1))
- return;
-
- if (IS_BITWISE_OP (ic) &&
- getSize (operandType (IC_RESULT (ic))) > 1)
- return;
-
-
- /* has only one definition */
- if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
- return;
-
- /* has only one use */
- if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
- return;
-
- /* and the usage immediately follows this iCode */
- if (!(uic = hTabItemWithKey (iCodehTab,
- bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
- return;
-
- if (ic->next != uic)
- return;
-
- /* if it is a conditional branch then we definitely can */
- if (uic->op == IFX)
- goto accuse;
-
- if (uic->op == JUMPTABLE)
- return;
-
- /* if the usage is not is an assignment
- or an arithmetic / bitwise / shift operation then not */
- if (POINTER_SET (uic) &&
- getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
- return;
-
- if (uic->op != '=' &&
- !IS_ARITHMETIC_OP (uic) &&
- !IS_BITWISE_OP (uic) &&
- uic->op != LEFT_OP &&
- uic->op != RIGHT_OP)
- return;
-
- /* if used in ^ operation then make sure right is not a
- literl */
- if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
- return;
-
- /* if shift operation make sure right side is not a literal */
- if (uic->op == RIGHT_OP &&
- (isOperandLiteral (IC_RIGHT (uic)) ||
- getSize (operandType (IC_RESULT (uic))) > 1))
- return;
-
- if (uic->op == LEFT_OP &&
- (isOperandLiteral (IC_RIGHT (uic)) ||
- getSize (operandType (IC_RESULT (uic))) > 1))
- return;
-
- /* make sure that the result of this icode is not on the
- stack, since acc is used to compute stack offset */
- if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
- OP_SYMBOL (IC_RESULT (uic))->onStack)
- return;
-
- /* if either one of them in far space then we cannot */
- if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
- isOperandInFarSpace (IC_LEFT (uic))) ||
- (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
- isOperandInFarSpace (IC_RIGHT (uic))))
- return;
-
- /* if the usage has only one operand then we can */
- if (IC_LEFT (uic) == NULL ||
- IC_RIGHT (uic) == NULL)
- goto accuse;
-
- /* make sure this is on the left side if not
- a '+' since '+' is commutative */
- if (ic->op != '+' &&
- IC_LEFT (uic)->key != IC_RESULT (ic)->key)
- return;
-
- /* if one of them is a literal then we can */
- if ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
- (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic))))
- {
- OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
- return;
- }
-
- /* if the other one is not on stack then we can */
- if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
- (IS_ITEMP (IC_RIGHT (uic)) ||
- (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
- !OP_SYMBOL (IC_RIGHT (uic))->onStack)))
- goto accuse;
-
- if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
- (IS_ITEMP (IC_LEFT (uic)) ||
- (IS_TRUE_SYMOP (IC_LEFT (uic)) &&
- !OP_SYMBOL (IC_LEFT (uic))->onStack)))
- goto accuse;
-
- return;
-
-accuse:
- OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
+ //iCode *uic;
+
+ debugLog ("%s\n", __FUNCTION__);
+ /* result too large for WREG? */
+ if (getSize (operandType (IC_RESULT (ic))) > 1)
+ return;
+
+ /* We have to make sure that OP_SYMBOL(IC_RESULT(ic))
+ * is never used as an operand to an instruction that
+ * cannot have WREG as an operand (e.g. BTFSx cannot
+ * operate on WREG...
+ * For now, store all results into proper registers. */
+ return;
+#if 0
+ /* if this is an aggregate, e.g. a one byte char array */
+ if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
+ return;
+ }
+ debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
+
+ /* if + or - then it has to be one byte result */
+ if ((ic->op == '+' || ic->op == '-')
+ && getSize (operandType (IC_RESULT (ic))) > 1)
+ return;
+
+ debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
+ /* if shift operation make sure right side is not a literal */
+ if (ic->op == RIGHT_OP &&
+ (isOperandLiteral (IC_RIGHT (ic)) ||
+ getSize (operandType (IC_RESULT (ic))) > 1))
+ return;
+
+ if (ic->op == LEFT_OP &&
+ (isOperandLiteral (IC_RIGHT (ic)) ||
+ getSize (operandType (IC_RESULT (ic))) > 1))
+ return;
+
+ if (IS_BITWISE_OP (ic) &&
+ getSize (operandType (IC_RESULT (ic))) > 1)
+ return;
+
+
+ /* has only one definition */
+ if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
+ return;
+
+ /* has only one use */
+ if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
+ return;
+
+ /* and the usage immediately follows this iCode */
+ if (!(uic = hTabItemWithKey (iCodehTab,
+ bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
+ return;
+
+ debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
+ if (ic->next != uic)
+ return;
+
+ /* if it is a conditional branch then we definitely can */
+ if (uic->op == IFX)
+ goto accuse;
+
+ if (uic->op == JUMPTABLE)
+ return;
+
+ /* if the usage is not is an assignment
+ or an arithmetic / bitwise / shift operation then not */
+ if (POINTER_SET (uic) &&
+ getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
+ return;
+
+ debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
+ if (uic->op != '=' &&
+ !IS_ARITHMETIC_OP (uic) &&
+ !IS_BITWISE_OP (uic) &&
+ uic->op != LEFT_OP &&
+ uic->op != RIGHT_OP)
+ return;
+
+ debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
+ /* if used in ^ operation then make sure right is not a
+ literl */
+ if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
+ return;
+
+ /* if shift operation make sure right side is not a literal */
+ if (uic->op == RIGHT_OP &&
+ (isOperandLiteral (IC_RIGHT (uic)) ||
+ getSize (operandType (IC_RESULT (uic))) > 1))
+ return;
+
+ if (uic->op == LEFT_OP &&
+ (isOperandLiteral (IC_RIGHT (uic)) ||
+ getSize (operandType (IC_RESULT (uic))) > 1))
+ return;
+
+ /* make sure that the result of this icode is not on the
+ stack, since acc is used to compute stack offset */
+ if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
+ OP_SYMBOL (IC_RESULT (uic))->onStack)
+ return;
+
+ /* if either one of them in far space then we cannot */
+ if ((IS_TRUE_SYMOP (IC_LEFT (uic)) &&
+ isOperandInFarSpace (IC_LEFT (uic))) ||
+ (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
+ isOperandInFarSpace (IC_RIGHT (uic))))
+ return;
+
+ /* if the usage has only one operand then we can */
+ if (IC_LEFT (uic) == NULL ||
+ IC_RIGHT (uic) == NULL)
+ goto accuse;
+
+ /* make sure this is on the left side if not
+ a '+' since '+' is commutative */
+ if (ic->op != '+' &&
+ IC_LEFT (uic)->key != IC_RESULT (ic)->key)
+ return;
+
+ debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
+ /* if one of them is a literal then we can */
+ if ( ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
+ (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic)))) &&
+ (getSize (operandType (IC_RESULT (uic))) <= 1))
+ {
+ OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
+ return;
+ }
+
+ debugLog (" %s:%d\n", __FUNCTION__,__LINE__);
+ /* if the other one is not on stack then we can */
+ if (IC_LEFT (uic)->key == IC_RESULT (ic)->key &&
+ (IS_ITEMP (IC_RIGHT (uic)) ||
+ (IS_TRUE_SYMOP (IC_RIGHT (uic)) &&
+ !OP_SYMBOL (IC_RIGHT (uic))->onStack)))
+ goto accuse;
+
+ if (IC_RIGHT (uic)->key == IC_RESULT (ic)->key &&
+ (IS_ITEMP (IC_LEFT (uic)) ||
+ (IS_TRUE_SYMOP (IC_LEFT (uic)) &&
+ !OP_SYMBOL (IC_LEFT (uic))->onStack)))
+ goto accuse;
+
+ return;
+
+accuse:
+ debugLog ("%s - Yes we are using the accumulator\n", __FUNCTION__);
+ OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
+#endif
}
/*-----------------------------------------------------------------*/
static void
packForReceive (iCode * ic, eBBlock * ebp)
{
- iCode *dic;
-
- debugLog ("%s\n", __FUNCTION__);
- debugAopGet (" result:", IC_RESULT (ic));
- debugAopGet (" left:", IC_LEFT (ic));
- debugAopGet (" right:", IC_RIGHT (ic));
-
- if (!ic->next)
- return;
-
- for (dic = ic->next; dic; dic = dic->next)
- {
-
-
-
- if (IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key))
- debugLog (" used on left\n");
- if (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key)
- debugLog (" used on right\n");
- if (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key)
- debugLog (" used on result\n");
-
- if ((IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key)) ||
- (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key))
- return;
-
- }
-
- debugLog (" hey we can remove this unnecessary assign\n");
+ iCode *dic;
+
+ debugLog ("%s\n", __FUNCTION__);
+ debugAopGet (" result:", IC_RESULT (ic));
+ debugAopGet (" left:", IC_LEFT (ic));
+ debugAopGet (" right:", IC_RIGHT (ic));
+
+ if (!ic->next)
+ return;
+
+ for (dic = ic->next; dic; dic = dic->next)
+ {
+
+
+
+ if (IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key))
+ debugLog (" used on left\n");
+ if (IC_RIGHT (dic) && IC_RESULT (ic)->key == IC_RIGHT (dic)->key)
+ debugLog (" used on right\n");
+ if (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key)
+ debugLog (" used on result\n");
+
+ if ((IC_LEFT (dic) && (IC_RESULT (ic)->key == IC_LEFT (dic)->key)) ||
+ (IC_RESULT (dic) && IC_RESULT (ic)->key == IC_RESULT (dic)->key))
+ return;
+
+ }
+
+ debugLog (" hey we can remove this unnecessary assign\n");
}
/*-----------------------------------------------------------------*/
/* packForPush - hueristics to reduce iCode for pushing */
static void
packForPush (iCode * ic, eBBlock * ebp)
{
- iCode *dic;
-
- debugLog ("%s\n", __FUNCTION__);
- if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
- return;
-
- /* must have only definition & one usage */
- if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
- bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
- return;
-
- /* find the definition */
- if (!(dic = hTabItemWithKey (iCodehTab,
- bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
- return;
-
- if (dic->op != '=' || POINTER_SET (dic))
- return;
+ iCode *dic;
+
+ debugLog ("%s\n", __FUNCTION__);
+ if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
+ return;
+
+ /* must have only definition & one usage */
+ if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
+ bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
+ return;
+
+ /* find the definition */
+ if (!(dic = hTabItemWithKey (iCodehTab,
+ bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
+ return;
+
+ if (dic->op != '=' || POINTER_SET (dic))
+ return;
+
+ /* we now we know that it has one & only one def & use
+ and the that the definition is an assignment */
+ IC_LEFT (ic) = IC_RIGHT (dic);
+
+ remiCodeFromeBBlock (ebp, dic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+ hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+}
- /* we now we know that it has one & only one def & use
- and the that the definition is an assignment */
- IC_LEFT (ic) = IC_RIGHT (dic);
+void printSymType(char * str, sym_link *sl)
+{
+ debugLog (" %s Symbol type: ",str);
+ printTypeChain( sl, debugF);
+ debugLog ("\n");
+
+}
- remiCodeFromeBBlock (ebp, dic);
- hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+/*-----------------------------------------------------------------*/
+/* some debug code to print the symbol S_TYPE. Note that
+* the function checkSClass in src/SDCCsymt.c dinks with
+* the S_TYPE in ways the PIC port doesn't fully like...*/
+/*-----------------------------------------------------------------*/
+void isData(sym_link *sl)
+{
+ FILE *of = stderr;
+
+ if(!sl)
+ return;
+
+ if(debugF)
+ of = debugF;
+
+ for ( ; sl; sl=sl->next) {
+ if(!IS_DECL(sl) ) {
+ switch (SPEC_SCLS(sl)) {
+
+ case S_DATA: fprintf (of, "data "); break;
+ case S_XDATA: fprintf (of, "xdata "); break;
+ case S_SFR: fprintf (of, "sfr "); break;
+ case S_SBIT: fprintf (of, "sbit "); break;
+ case S_CODE: fprintf (of, "code "); break;
+ case S_IDATA: fprintf (of, "idata "); break;
+ case S_PDATA: fprintf (of, "pdata "); break;
+ case S_LITERAL: fprintf (of, "literal "); break;
+ case S_STACK: fprintf (of, "stack "); break;
+ case S_XSTACK: fprintf (of, "xstack "); break;
+ case S_BIT: fprintf (of, "bit "); break;
+ case S_EEPROM: fprintf (of, "eeprom "); break;
+ default: break;
+ }
+
+ }
+
+ }
+
}
/*-----------------------------------------------------------------*/
static void
packRegisters (eBBlock * ebp)
{
- iCode *ic;
- int change = 0;
-
- debugLog ("%s\n", __FUNCTION__);
-
- while (1)
- {
-
- change = 0;
-
- /* look for assignments of the form */
- /* iTempNN = TRueSym (someoperation) SomeOperand */
- /* .... */
- /* TrueSym := iTempNN:1 */
- for (ic = ebp->sch; ic; ic = ic->next)
- {
-
- /* find assignment of the form TrueSym := iTempNN:1 */
- if (ic->op == '=' && !POINTER_SET (ic))
- change += packRegsForAssign (ic, ebp);
- /* debug stuff */
- if (ic->op == '=')
- {
- if (POINTER_SET (ic))
- debugLog ("pointer is set\n");
- debugAopGet (" result:", IC_RESULT (ic));
- debugAopGet (" left:", IC_LEFT (ic));
- debugAopGet (" right:", IC_RIGHT (ic));
- }
-
- }
-
- if (!change)
- break;
- }
-
- for (ic = ebp->sch; ic; ic = ic->next)
- {
-
- /* if this is an itemp & result of a address of a true sym
- then mark this as rematerialisable */
- if (ic->op == ADDRESS_OF &&
- IS_ITEMP (IC_RESULT (ic)) &&
- IS_TRUE_SYMOP (IC_LEFT (ic)) &&
- bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
- !OP_SYMBOL (IC_LEFT (ic))->onStack)
- {
-
- debugLog (" %d - %s. result is rematerializable\n", __LINE__,__FUNCTION__);
-
- OP_SYMBOL (IC_RESULT (ic))->remat = 1;
- OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
- OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
-
- }
-
- /* if straight assignment then carry remat flag if
- this is the only definition */
- if (ic->op == '=' &&
- !POINTER_SET (ic) &&
- IS_SYMOP (IC_RIGHT (ic)) &&
- OP_SYMBOL (IC_RIGHT (ic))->remat &&
- bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
- {
- debugLog (" %d - %s. straight rematerializable\n", __LINE__,__FUNCTION__);
-
- OP_SYMBOL (IC_RESULT (ic))->remat =
- OP_SYMBOL (IC_RIGHT (ic))->remat;
- OP_SYMBOL (IC_RESULT (ic))->rematiCode =
- OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
- }
-
- /* if this is a +/- operation with a rematerizable
- then mark this as rematerializable as well */
- if ((ic->op == '+' || ic->op == '-') &&
- (IS_SYMOP (IC_LEFT (ic)) &&
- IS_ITEMP (IC_RESULT (ic)) &&
- OP_SYMBOL (IC_LEFT (ic))->remat &&
- bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
- IS_OP_LITERAL (IC_RIGHT (ic))))
- {
- debugLog (" %d - %s. rematerializable because op is +/-\n", __LINE__,__FUNCTION__);
- //int i =
- operandLitValue (IC_RIGHT (ic));
- OP_SYMBOL (IC_RESULT (ic))->remat = 1;
- OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
- OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
- }
-
- /* mark the pointer usages */
- if (POINTER_SET (ic))
- {
- OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
- debugLog (" marking as a pointer (set) =>");
- debugAopGet (" result:", IC_RESULT (ic));
- }
- if (POINTER_GET (ic))
- {
- OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
- debugLog (" marking as a pointer (get) =>");
- debugAopGet (" left:", IC_LEFT (ic));
- }
-
- if (!SKIP_IC2 (ic))
- {
- /* if we are using a symbol on the stack
- then we should say pic14_ptrRegReq */
- if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
- pic14_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ||
- OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0);
- else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
- pic14_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ||
- OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0);
- else
- {
- if (IS_SYMOP (IC_LEFT (ic)))
- pic14_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ||
- OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0);
- if (IS_SYMOP (IC_RIGHT (ic)))
- pic14_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ||
- OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0);
- if (IS_SYMOP (IC_RESULT (ic)))
- pic14_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ||
- OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0);
- }
- }
-
- /* if the condition of an if instruction
- is defined in the previous instruction then
- mark the itemp as a conditional */
- if ((IS_CONDITIONAL (ic) ||
- ((ic->op == BITWISEAND ||
- ic->op == '|' ||
- ic->op == '^') &&
- isBitwiseOptimizable (ic))) &&
- ic->next && ic->next->op == IFX &&
- isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
- OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
- {
+ iCode *ic;
+ int change = 0;
+
+ debugLog ("%s\n", __FUNCTION__);
+
+ while (1) {
+
+ change = 0;
+
+ /* look for assignments of the form */
+ /* iTempNN = TRueSym (someoperation) SomeOperand */
+ /* .... */
+ /* TrueSym := iTempNN:1 */
+ for (ic = ebp->sch; ic; ic = ic->next)
+ {
- OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
- continue;
+ /* find assignment of the form TrueSym := iTempNN:1 */
+ if (ic->op == '=' && !POINTER_SET (ic))
+ change += packRegsForAssign (ic, ebp);
+ /* debug stuff */
+ if (ic->op == '=')
+ {
+ if (POINTER_SET (ic))
+ debugLog ("pointer is set\n");
+ debugAopGet (" result:", IC_RESULT (ic));
+ debugAopGet (" left:", IC_LEFT (ic));
+ debugAopGet (" right:", IC_RIGHT (ic));
+ }
+
+ }
+
+ if (!change)
+ break;
}
-
- /* reduce for support function calls */
- if (ic->supportRtn || ic->op == '+' || ic->op == '-')
- packRegsForSupport (ic, ebp);
-
- /* if a parameter is passed, it's in W, so we may not
- need to place a copy in a register */
- if (ic->op == RECEIVE)
- packForReceive (ic, ebp);
-
- /* some cases the redundant moves can
- can be eliminated for return statements */
- if ((ic->op == RETURN || ic->op == SEND) &&
- !isOperandInFarSpace (IC_LEFT (ic)) &&
- !options.model)
- packRegsForOneuse (ic, IC_LEFT (ic), ebp);
-
- /* if pointer set & left has a size more than
- one and right is not in far space */
- if (POINTER_SET (ic) &&
- !isOperandInFarSpace (IC_RIGHT (ic)) &&
- !OP_SYMBOL (IC_RESULT (ic))->remat &&
- !IS_OP_RUONLY (IC_RIGHT (ic)) &&
- getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
-
- packRegsForOneuse (ic, IC_RESULT (ic), ebp);
-
- /* if pointer get */
- if (POINTER_GET (ic) &&
- !isOperandInFarSpace (IC_RESULT (ic)) &&
- !OP_SYMBOL (IC_LEFT (ic))->remat &&
- !IS_OP_RUONLY (IC_RESULT (ic)) &&
- getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
-
- packRegsForOneuse (ic, IC_LEFT (ic), ebp);
-
-
- /* if this is cast for intergral promotion then
- check if only use of the definition of the
- operand being casted/ if yes then replace
- the result of that arithmetic operation with
- this result and get rid of the cast */
- if (ic->op == CAST)
- {
- sym_link *fromType = operandType (IC_RIGHT (ic));
- sym_link *toType = operandType (IC_LEFT (ic));
-
- if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
- getSize (fromType) != getSize (toType))
- {
-
- iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
- if (dic)
+
+ for (ic = ebp->sch; ic; ic = ic->next) {
+
+ if(IS_SYMOP ( IC_LEFT(ic))) {
+ sym_link *etype = getSpec (operandType (IC_LEFT (ic)));
+
+ debugAopGet (" left:", IC_LEFT (ic));
+ if(IS_PTR_CONST(OP_SYMBOL(IC_LEFT(ic))->type))
+ debugLog (" is a pointer\n");
+
+ if(IS_OP_VOLATILE(IC_LEFT(ic)))
+ debugLog (" is volatile\n");
+
+ isData(etype);
+
+ printSymType(" ", OP_SYMBOL(IC_LEFT(ic))->type);
+ }
+
+ if(IS_SYMOP ( IC_RIGHT(ic))) {
+ debugAopGet (" right:", IC_RIGHT (ic));
+ printSymType(" ", OP_SYMBOL(IC_RIGHT(ic))->type);
+ }
+
+ if(IS_SYMOP ( IC_RESULT(ic))) {
+ debugAopGet (" result:", IC_RESULT (ic));
+ printSymType(" ", OP_SYMBOL(IC_RESULT(ic))->type);
+ }
+
+ if (POINTER_SET (ic))
+ debugLog (" %d - Pointer set\n", __LINE__);
+
+
+ /* Look for two subsequent iCodes with */
+ /* iTemp := _c; */
+ /* _c = iTemp & op; */
+ /* and replace them by */
+ /* iTemp := _c; */
+ /* _c = _c & op; */
+ if ((ic->op == BITWISEAND || ic->op == '|' || ic->op == '^') &&
+ ic->prev &&
+ ic->prev->op == '=' &&
+ IS_ITEMP (IC_LEFT (ic)) &&
+ IC_LEFT (ic) == IC_RESULT (ic->prev) &&
+ isOperandEqual (IC_RESULT(ic), IC_RIGHT(ic->prev)))
+ {
+ iCode* ic_prev = ic->prev;
+ symbol* prev_result_sym = OP_SYMBOL (IC_RESULT (ic_prev));
+
+ ReplaceOpWithCheaperOp (&IC_LEFT (ic), IC_RESULT (ic));
+ if (IC_RESULT (ic_prev) != IC_RIGHT (ic))
+ {
+ bitVectUnSetBit (OP_USES (IC_RESULT (ic_prev)), ic->key);
+ if (/*IS_ITEMP (IC_RESULT (ic_prev)) && */
+ prev_result_sym->liveTo == ic->seq)
+ {
+ prev_result_sym->liveTo = ic_prev->seq;
+ }
+ }
+ bitVectSetBit (OP_USES (IC_RESULT (ic)), ic->key);
+
+ bitVectSetBit (ic->rlive, IC_RESULT (ic)->key);
+
+ if (bitVectIsZero (OP_USES (IC_RESULT (ic_prev))))
+ {
+ bitVectUnSetBit (ic->rlive, IC_RESULT (ic)->key);
+ bitVectUnSetBit (OP_DEFS (IC_RESULT (ic_prev)), ic_prev->key);
+ remiCodeFromeBBlock (ebp, ic_prev);
+ hTabDeleteItem (&iCodehTab, ic_prev->key, ic_prev, DELETE_ITEM, NULL);
+ }
+ }
+
+ /* if this is an itemp & result of a address of a true sym
+ then mark this as rematerialisable */
+ if (ic->op == ADDRESS_OF &&
+ IS_ITEMP (IC_RESULT (ic)) &&
+ IS_TRUE_SYMOP (IC_LEFT (ic)) &&
+ bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+ !OP_SYMBOL (IC_LEFT (ic))->onStack)
{
- if (IS_ARITHMETIC_OP (dic))
- {
- IC_RESULT (dic) = IC_RESULT (ic);
- remiCodeFromeBBlock (ebp, ic);
- hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
- OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
- ic = ic->prev;
- }
- else
- OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
- }
- }
- else
- {
-
- /* if the type from and type to are the same
- then if this is the only use then packit */
- if (compareType (operandType (IC_RIGHT (ic)),
- operandType (IC_LEFT (ic))) == 1)
+
+ debugLog (" %d - %s. result is rematerializable\n", __LINE__,__FUNCTION__);
+
+ OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+ OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+ OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+
+ }
+
+ /* if straight assignment then carry remat flag if
+ this is the only definition */
+ if (ic->op == '=' &&
+ !POINTER_SET (ic) &&
+ IS_SYMOP (IC_RIGHT (ic)) &&
+ OP_SYMBOL (IC_RIGHT (ic))->remat &&
+ bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
{
- iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
- if (dic)
- {
- IC_RESULT (dic) = IC_RESULT (ic);
- remiCodeFromeBBlock (ebp, ic);
- hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
- OP_DEFS (IC_RESULT (dic)) = bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
- ic = ic->prev;
- }
- }
- }
- }
-
- /* pack for PUSH
- iTempNN := (some variable in farspace) V1
- push iTempNN ;
- -------------
- push V1
- */
- if (ic->op == IPUSH)
- {
- packForPush (ic, ebp);
+ debugLog (" %d - %s. straight rematerializable\n", __LINE__,__FUNCTION__);
+
+ OP_SYMBOL (IC_RESULT (ic))->remat =
+ OP_SYMBOL (IC_RIGHT (ic))->remat;
+ OP_SYMBOL (IC_RESULT (ic))->rematiCode =
+ OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+ }
+
+ /* if this is a +/- operation with a rematerizable
+ then mark this as rematerializable as well */
+ if ((ic->op == '+' || ic->op == '-') &&
+ (IS_SYMOP (IC_LEFT (ic)) &&
+ IS_ITEMP (IC_RESULT (ic)) &&
+ OP_SYMBOL (IC_LEFT (ic))->remat &&
+ bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+ IS_OP_LITERAL (IC_RIGHT (ic))))
+ {
+ debugLog (" %d - %s. rematerializable because op is +/-\n", __LINE__,__FUNCTION__);
+ //int i =
+ operandLitValue (IC_RIGHT (ic));
+ OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+ OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+ OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+ }
+
+ /* mark the pointer usages */
+ if (POINTER_SET (ic) && IS_SYMOP(IC_RESULT(ic)))
+ {
+ OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
+ debugLog (" marking as a pointer (set) =>");
+ debugAopGet (" result:", IC_RESULT (ic));
+ }
+ if (POINTER_GET (ic) && IS_SYMOP(IC_LEFT(ic)))
+ {
+ OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
+ debugLog (" marking as a pointer (get) =>");
+ debugAopGet (" left:", IC_LEFT (ic));
+ }
+
+ if (!SKIP_IC2 (ic))
+ {
+ /* if we are using a symbol on the stack
+ then we should say pic14_ptrRegReq */
+ if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
+ pic14_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ||
+ OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0);
+ else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
+ pic14_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ||
+ OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0);
+ else
+ {
+ if (IS_SYMOP (IC_LEFT (ic)))
+ pic14_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ||
+ OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0);
+ if (IS_SYMOP (IC_RIGHT (ic)))
+ pic14_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ||
+ OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0);
+ if (IS_SYMOP (IC_RESULT (ic)))
+ pic14_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ||
+ OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0);
+ }
+
+ debugLog (" %d - pointer reg req = %d\n", __LINE__,pic14_ptrRegReq);
+
+ }
+
+ /* if the condition of an if instruction
+ is defined in the previous instruction then
+ mark the itemp as a conditional */
+ if ((IS_CONDITIONAL (ic) ||
+ ((ic->op == BITWISEAND ||
+ ic->op == '|' ||
+ ic->op == '^') &&
+ isBitwiseOptimizable (ic))) &&
+ ic->next && ic->next->op == IFX &&
+ isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
+ OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
+ {
+
+ debugLog (" %d\n", __LINE__);
+ OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
+ continue;
+ }
+
+ /* reduce for support function calls */
+ if (ic->supportRtn || ic->op == '+' || ic->op == '-')
+ packRegsForSupport (ic, ebp);
+
+ /* if a parameter is passed, it's in W, so we may not
+ need to place a copy in a register */
+ if (ic->op == RECEIVE)
+ packForReceive (ic, ebp);
+
+ /* some cases the redundant moves can
+ can be eliminated for return statements */
+ if ((ic->op == RETURN || ic->op == SEND) &&
+ !isOperandInFarSpace (IC_LEFT (ic)) &&
+ !options.model)
+ packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+
+ /* if pointer set & left has a size more than
+ one and right is not in far space */
+ if (POINTER_SET (ic) &&
+ !isOperandInFarSpace (IC_RIGHT (ic)) &&
+ IS_SYMOP(IC_RESULT(ic)) &&
+ !OP_SYMBOL (IC_RESULT (ic))->remat &&
+ !IS_OP_RUONLY (IC_RIGHT (ic)) &&
+ getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1)
+
+ packRegsForOneuse (ic, IC_RESULT (ic), ebp);
+
+ /* if pointer get */
+ if (POINTER_GET (ic) &&
+ !isOperandInFarSpace (IC_RESULT (ic)) &&
+ IS_SYMOP(IC_LEFT(ic)) &&
+ !OP_SYMBOL (IC_LEFT (ic))->remat &&
+ !IS_OP_RUONLY (IC_RESULT (ic)) &&
+ getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1)
+
+ packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+
+
+ /* if this is cast for intergral promotion then
+ check if only use of the definition of the
+ operand being casted/ if yes then replace
+ the result of that arithmetic operation with
+ this result and get rid of the cast */
+ if (ic->op == CAST) {
+
+ sym_link *fromType = operandType (IC_RIGHT (ic));
+ sym_link *toType = operandType (IC_LEFT (ic));
+
+ debugLog (" %d - casting\n", __LINE__);
+
+ if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
+ getSize (fromType) != getSize (toType)) {
+
+
+ iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
+ if (dic) {
+
+ if (IS_ARITHMETIC_OP (dic)) {
+
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+ IC_RESULT (dic) = IC_RESULT (ic);
+ remiCodeFromeBBlock (ebp, ic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+ hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+ OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+ ic = ic->prev;
+ } else
+
+ OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
+ }
+ } else {
+
+ /* if the type from and type to are the same
+ then if this is the only use then packit */
+ if (compareType (operandType (IC_RIGHT (ic)),
+ operandType (IC_LEFT (ic))) == 1) {
+
+ iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
+ if (dic) {
+
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+ IC_RESULT (dic) = IC_RESULT (ic);
+ bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+ remiCodeFromeBBlock (ebp, ic);
+ hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+ OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+ ic = ic->prev;
+ }
+ }
+ }
+ }
+
+ /* pack for PUSH
+ iTempNN := (some variable in farspace) V1
+ push iTempNN ;
+ -------------
+ push V1
+ */
+ if (ic->op == IPUSH)
+ {
+ packForPush (ic, ebp);
+ }
+
+
+ /* pack registers for accumulator use, when the
+ result of an arithmetic or bit wise operation
+ has only one use, that use is immediately following
+ the defintion and the using iCode has only one
+ operand or has two operands but one is literal &
+ the result of that operation is not on stack then
+ we can leave the result of this operation in acc:b
+ combination */
+ if ((IS_ARITHMETIC_OP (ic)
+
+ || IS_BITWISE_OP (ic)
+
+ || ic->op == LEFT_OP || ic->op == RIGHT_OP
+
+ ) &&
+ IS_ITEMP (IC_RESULT (ic)) &&
+ getSize (operandType (IC_RESULT (ic))) <= 2)
+
+ packRegsForAccUse (ic);
+
}
-
-
- /* pack registers for accumulator use, when the
- result of an arithmetic or bit wise operation
- has only one use, that use is immediately following
- the defintion and the using iCode has only one
- operand or has two operands but one is literal &
- the result of that operation is not on stack then
- we can leave the result of this operation in acc:b
- combination */
- if ((IS_ARITHMETIC_OP (ic)
-
- || IS_BITWISE_OP (ic)
-
- || ic->op == LEFT_OP || ic->op == RIGHT_OP
-
- ) &&
- IS_ITEMP (IC_RESULT (ic)) &&
- getSize (operandType (IC_RESULT (ic))) <= 2)
-
- packRegsForAccUse (ic);
-
- }
}
static void
dumpEbbsToDebug (eBBlock ** ebbs, int count)
{
- int i;
-
- if (!debug || !debugF)
- return;
-
- for (i = 0; i < count; i++)
- {
- fprintf (debugF, "\n----------------------------------------------------------------\n");
- fprintf (debugF, "Basic Block %s : loop Depth = %d noPath = %d , lastinLoop = %d\n",
- ebbs[i]->entryLabel->name,
- ebbs[i]->depth,
- ebbs[i]->noPath,
- ebbs[i]->isLastInLoop);
- fprintf (debugF, "depth 1st num %d : bbnum = %d 1st iCode = %d , last iCode = %d\n",
- ebbs[i]->dfnum,
- ebbs[i]->bbnum,
- ebbs[i]->fSeq,
- ebbs[i]->lSeq);
- fprintf (debugF, "visited %d : hasFcall = %d\n",
- ebbs[i]->visited,
- ebbs[i]->hasFcall);
-
- fprintf (debugF, "\ndefines bitVector :");
- bitVectDebugOn (ebbs[i]->defSet, debugF);
- fprintf (debugF, "\nlocal defines bitVector :");
- bitVectDebugOn (ebbs[i]->ldefs, debugF);
- fprintf (debugF, "\npointers Set bitvector :");
- bitVectDebugOn (ebbs[i]->ptrsSet, debugF);
- fprintf (debugF, "\nin pointers Set bitvector :");
- bitVectDebugOn (ebbs[i]->inPtrsSet, debugF);
- fprintf (debugF, "\ninDefs Set bitvector :");
- bitVectDebugOn (ebbs[i]->inDefs, debugF);
- fprintf (debugF, "\noutDefs Set bitvector :");
- bitVectDebugOn (ebbs[i]->outDefs, debugF);
- fprintf (debugF, "\nusesDefs Set bitvector :");
- bitVectDebugOn (ebbs[i]->usesDefs, debugF);
- fprintf (debugF, "\n----------------------------------------------------------------\n");
- printiCChain (ebbs[i]->sch, debugF);
- }
+ int i;
+
+ if (!debug || !debugF)
+ return;
+
+ for (i = 0; i < count; i++)
+ {
+ fprintf (debugF, "\n----------------------------------------------------------------\n");
+ fprintf (debugF, "Basic Block %s : loop Depth = %d noPath = %d , lastinLoop = %d\n",
+ ebbs[i]->entryLabel->name,
+ ebbs[i]->depth,
+ ebbs[i]->noPath,
+ ebbs[i]->isLastInLoop);
+ fprintf (debugF, "depth 1st num %d : bbnum = %d 1st iCode = %d , last iCode = %d\n",
+ ebbs[i]->dfnum,
+ ebbs[i]->bbnum,
+ ebbs[i]->fSeq,
+ ebbs[i]->lSeq);
+ fprintf (debugF, "visited %d : hasFcall = %d\n",
+ ebbs[i]->visited,
+ ebbs[i]->hasFcall);
+
+ fprintf (debugF, "\ndefines bitVector :");
+ bitVectDebugOn (ebbs[i]->defSet, debugF);
+ fprintf (debugF, "\nlocal defines bitVector :");
+ bitVectDebugOn (ebbs[i]->ldefs, debugF);
+ fprintf (debugF, "\npointers Set bitvector :");
+ bitVectDebugOn (ebbs[i]->ptrsSet, debugF);
+ fprintf (debugF, "\nin pointers Set bitvector :");
+ bitVectDebugOn (ebbs[i]->inPtrsSet, debugF);
+ fprintf (debugF, "\ninDefs Set bitvector :");
+ bitVectDebugOn (ebbs[i]->inDefs, debugF);
+ fprintf (debugF, "\noutDefs Set bitvector :");
+ bitVectDebugOn (ebbs[i]->outDefs, debugF);
+ fprintf (debugF, "\nusesDefs Set bitvector :");
+ bitVectDebugOn (ebbs[i]->usesDefs, debugF);
+ fprintf (debugF, "\n----------------------------------------------------------------\n");
+ printiCChain (ebbs[i]->sch, debugF);
+ }
}
/*-----------------------------------------------------------------*/
/* assignRegisters - assigns registers to each live range as need */
/*-----------------------------------------------------------------*/
void
-pic14_assignRegisters (eBBlock ** ebbs, int count)
+pic14_assignRegisters (ebbIndex * ebbi)
{
- iCode *ic;
- int i;
-
- debugLog ("<><><><><><><><><><><><><><><><><>\nstarting\t%s:%s", __FILE__, __FUNCTION__);
- debugLog ("ebbs before optimizing:\n");
- dumpEbbsToDebug (ebbs, count);
-
- setToNull ((void *) &_G.funcrUsed);
- pic14_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
-
-
- /* change assignments this will remove some
- live ranges reducing some register pressure */
- for (i = 0; i < count; i++)
- packRegisters (ebbs[i]);
-
- if (options.dump_pack)
- dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
-
- /* first determine for each live range the number of
- registers & the type of registers required for each */
- regTypeNum ();
-
- /* and serially allocate registers */
- serialRegAssign (ebbs, count);
-
- /* if stack was extended then tell the user */
- if (_G.stackExtend)
- {
-/* werror(W_TOOMANY_SPILS,"stack", */
-/* _G.stackExtend,currFunc->name,""); */
- _G.stackExtend = 0;
- }
-
- if (_G.dataExtend)
- {
-/* werror(W_TOOMANY_SPILS,"data space", */
-/* _G.dataExtend,currFunc->name,""); */
- _G.dataExtend = 0;
- }
-
- /* after that create the register mask
- for each of the instruction */
- createRegMask (ebbs, count);
-
- /* redo that offsets for stacked automatic variables */
- redoStackOffsets ();
-
- if (options.dump_rassgn)
- dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
-
- /* now get back the chain */
- ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
-
- debugLog ("ebbs after optimizing:\n");
- dumpEbbsToDebug (ebbs, count);
-
-
- genpic14Code (ic);
-
- /* free up any _G.stackSpil locations allocated */
- applyToSet (_G.stackSpil, deallocStackSpil);
- _G.slocNum = 0;
- setToNull ((void **) &_G.stackSpil);
- setToNull ((void **) &_G.spiltSet);
- /* mark all registers as free */
- pic14_freeAllRegs ();
-
- debugLog ("leaving\n<><><><><><><><><><><><><><><><><>\n");
- debugLogClose ();
- return;
+ eBBlock ** ebbs = ebbi->bbOrder;
+ int count = ebbi->count;
+ iCode *ic;
+ int i;
+
+ debugLog ("<><><><><><><><><><><><><><><><><>\nstarting\t%s:%s\n", __FILE__, __FUNCTION__);
+ debugLog ("ebbs before optimizing:\n");
+ dumpEbbsToDebug (ebbs, count);
+
+ setToNull ((void *) &_G.funcrUsed);
+ pic14_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
+
+
+ /* change assignments this will remove some
+ live ranges reducing some register pressure */
+ for (i = 0; i < count; i++)
+ packRegisters (ebbs[i]);
+
+ {
+ regs *reg;
+ int hkey;
+ int i=0;
+
+ debugLog("dir registers allocated so far:\n");
+ reg = hTabFirstItem(dynDirectRegNames, &hkey);
+
+ while(reg) {
+ debugLog(" -- #%d reg = %s key %d, rIdx = %d, size %d\n",i++,reg->name,hkey, reg->rIdx,reg->size);
+ reg = hTabNextItem(dynDirectRegNames, &hkey);
+ }
+
+ }
+
+ if (options.dump_pack)
+ dumpEbbsToFileExt (DUMP_PACK, ebbi);
+
+ /* first determine for each live range the number of
+ registers & the type of registers required for each */
+ regTypeNum ();
+
+ /* and serially allocate registers */
+ serialRegAssign (ebbs, count);
+
+ /* if stack was extended then tell the user */
+ if (_G.stackExtend)
+ {
+ /* werror(W_TOOMANY_SPILS,"stack", */
+ /* _G.stackExtend,currFunc->name,""); */
+ _G.stackExtend = 0;
+ }
+
+ if (_G.dataExtend)
+ {
+ /* werror(W_TOOMANY_SPILS,"data space", */
+ /* _G.dataExtend,currFunc->name,""); */
+ _G.dataExtend = 0;
+ }
+
+ /* after that create the register mask
+ for each of the instruction */
+ createRegMask (ebbs, count);
+
+ /* redo that offsets for stacked automatic variables */
+ redoStackOffsets ();
+
+ if (options.dump_rassgn)
+ dumpEbbsToFileExt (DUMP_RASSGN, ebbi);
+
+ /* now get back the chain */
+ ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
+
+ debugLog ("ebbs after optimizing:\n");
+ dumpEbbsToDebug (ebbs, count);
+
+
+ genpic14Code (ic);
+
+ /* free up any _G.stackSpil locations allocated */
+ applyToSet (_G.stackSpil, deallocStackSpil);
+ _G.slocNum = 0;
+ setToNull ((void *) &_G.stackSpil);
+ setToNull ((void *) &_G.spiltSet);
+ /* mark all registers as free */
+ //pic14_freeAllRegs ();
+
+ debugLog ("leaving\n<><><><><><><><><><><><><><><><><>\n");
+ debugLogClose ();
+ return;
}