-static struct {
- 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 */
-regs regspic14[] =
-{
-
- {PIC_INDF, 0, "INDF", "INDR", "0", 0, 1},
- {PIC_GPR, 0, "r0x0C", "r0x0C", "0x0C", 0x0C, 1},
- {PIC_GPR, 0, "r0x0D", "r0x0C", "0x0D", 0x0D, 1},
- {PIC_GPR, 0, "r0x0E", "r0x0C", "0x0E", 0x0E, 1},
- {PIC_GPR, 0, "r0x0F", "r0x0C", "0x0F", 0x0F, 1},
- {PIC_GPR, 0, "r0x10", "r0x10", "0x10", 0x10, 1},
- {PIC_GPR, 0, "r0x11", "r0x11", "0x11", 0x11, 1},
- {PIC_GPR, 0, "r0x12", "r0x12", "0x12", 0x12, 1},
- {PIC_GPR, 0, "r0x13", "r0x13", "0x13", 0x13, 1},
- {PIC_GPR, 0, "r0x14", "r0x14", "0x14", 0x14, 1},
- {PIC_GPR, 0, "r0x15", "r0x15", "0x15", 0x15, 1},
- {PIC_GPR, 0, "r0x16", "r0x16", "0x16", 0x16, 1},
- {PIC_GPR, 0, "r0x17", "r0x17", "0x17", 0x17, 1},
- {PIC_GPR, 0, "r0x18", "r0x18", "0x18", 0x18, 1},
- {PIC_GPR, 0, "r0x19", "r0x19", "0x19", 0x19, 1},
- {PIC_GPR, 0, "r0x1A", "r0x1A", "0x1A", 0x1A, 1},
- {PIC_GPR, 0, "r0x1B", "r0x1B", "0x1B", 0x1B, 1},
- {PIC_GPR, 0, "r0x1C", "r0x1C", "0x1C", 0x1C, 1},
- {PIC_GPR, 0, "r0x1D", "r0x1D", "0x1D", 0x1D, 1},
- {PIC_GPR, 0, "r0x1E", "r0x1E", "0x1E", 0x1E, 1},
- {PIC_GPR, 0, "r0x1F", "r0x1F", "0x1F", 0x1F, 1},
-
-};
-
-int pic14_nRegs = sizeof(regspic14) / sizeof(regs);
-static void spillThis (symbol *);
+static struct
+{
+ bitVect *spiltSet;
+ set *stackSpil;
+ bitVect *regAssigned;
+ short blockSpil;
+ int slocNum;
+ bitVect *funcrUsed; /* registers used in a function */
+ int stackExtend;
+ int dataExtend;
+}
+_G;
+
+static int pic14_ptrRegReq; /* one byte pointer register required */
+
+static hTab *dynDirectRegNames= NULL;
+// static hTab *regHash = NULL; /* a hash table containing ALL registers */
+
+static int dynrIdx = 0x1000;
+
+int Gstack_base_addr=0; /* The starting address of registers that
+ * are used to pass and return parameters */
+static int Gstack_size = 0;
+
+static int debug = 0; // should be 0 when committed, creates .d files
+static FILE *debugF = NULL;
+
+/*-----------------------------------------------------------------*/
+/* debugLog - open a file for debugging information */
+/*-----------------------------------------------------------------*/
+static void
+debugLog (char *fmt,...)
+{
+ static int append = 0; // First time through, open the file without append.
+
+ char buffer[256];
+ //char *bufferP=buffer;
+ va_list ap;
+
+ if (!debug || !dstFileName)
+ return;
+
+
+ if (!debugF)
+ {
+ /* 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 debugLog is called, we'll append the debug info
+
+ }
+
+ va_start (ap, fmt);
+ vsprintf (buffer, fmt, ap);
+ va_end (ap);
+
+ fprintf (debugF, "%s", buffer);
+ //if (options.verbose) fprintf (stderr, "%s: %s", __FUNCTION__, buffer);
+}
+
+static void
+debugNewLine (void)
+{
+ if (debugF)
+ fputc ('\n', debugF);
+}
+ /*-----------------------------------------------------------------*/
+ /* pic14_debugLogClose - closes the debug log file (if opened) */
+ /*-----------------------------------------------------------------*/
+void
+pic14_debugLogClose (void)
+{
+ if (debugF)
+ {
+ fclose (debugF);
+ debugF = NULL;
+ }
+}
+
+static char *
+debugAopGet (char *str, operand * op)
+{
+ if (!debug) return NULL;
+
+ if (str) debugLog (str);
+
+ printOperand (op, debugF);
+ debugNewLine ();
+
+ 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 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, "unknown reg type %d", type);
+ return buffer;
+}
+
+/*-----------------------------------------------------------------*/
+/*-----------------------------------------------------------------*/
+static int regname2key(char const *name)
+{
+ int key = 0;
+
+ if(!name)
+ return 0;
+
+ while(*name) {
+
+ key += (*name++) + 1;
+
+ }
+
+ return ( (key + (key >> 4) + (key>>8)) & 0x3f);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* regWithIdx - Search through a set of registers that matches idx */
+/*-----------------------------------------------------------------*/
+static regs *
+regWithIdx (set *dRegs, int idx, int fixed)
+{
+ 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;
+}
+
+/*-----------------------------------------------------------------*/
+/* newReg - allocate and init memory for a new register */
+/*-----------------------------------------------------------------*/
+static regs* newReg(short type, PIC_OPTYPE pc_type, int rIdx, char *name, int size, int alias)
+{
+
+ regs *dReg, *reg_alias;
+
+ /* 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;
+}
+
+/*-----------------------------------------------------------------*/
+/* regWithName - Search through a set of registers that matches name */
+/*-----------------------------------------------------------------*/
+static regs *
+regWithName (set *dRegs, const char *name)
+{
+ regs *dReg;
+
+ for (dReg = setFirstItem(dRegs) ; dReg ;
+ dReg = setNextItem(dRegs)) {
+
+ if((strcmp(name,dReg->name)==0)) {
+ return dReg;
+ }
+ }
+
+ return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* regWithName - Search for a registers that matches name */
+/*-----------------------------------------------------------------*/
+regs *
+regFindWithName (const char *name)
+{
+ 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;
+}
+
+/*-----------------------------------------------------------------*/
+/* regFindFree - Search for a free register in a set of registers */
+/*-----------------------------------------------------------------*/
+static regs *
+regFindFree (set *dRegs)
+{
+ regs *dReg;
+
+ for (dReg = setFirstItem(dRegs) ; dReg ;
+ dReg = setNextItem(dRegs)) {
+
+ if(dReg->isFree)
+ return dReg;
+ }
+
+ return NULL;
+}
+/*-----------------------------------------------------------------*/
+/* initStack - allocate registers for a pseudo stack */
+/*-----------------------------------------------------------------*/
+void initStack(int base_address, int size, int shared)
+{
+
+ int i;
+ PIC_device *pic;
+
+ 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);
+ }
+}
+
+/*-----------------------------------------------------------------*
+*-----------------------------------------------------------------*/
+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));
+}
+
+/*-----------------------------------------------------------------*
+*-----------------------------------------------------------------*/
+
+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);
+ }