case S_EEPROM:
DCL_TYPE($3) = EEPPOINTER;
break;
+ default:
+ werror(W_PTR_TYPE_INVALID);
}
}
else
case PPOINTER:
SPEC_OCLS(spec) = xstack;
break;
+
+ case EEPPOINTER:
+ SPEC_OCLS(spec) = eeprom;
+ break;
+
+ default:
+ break;
+
}
}
-------------------------------------------------------------------------*/
#include "common.h"
+#include "limits.h"
int iCodeSeq = 0 ;
hTab *liveRanges = NULL;
OP_LIVETO(op) = to;
}
+/*-----------------------------------------------------------------*/
+/* firstDeOf - finds the first definition in seq for op */
+/*-----------------------------------------------------------------*/
+static iCode *firstDefOf (operand *op)
+{
+ int i;
+ iCode *ric=NULL,*lic=NULL;
+ int fSeq = INT_MAX;
+
+ if (!OP_DEFS(op))
+ return NULL;
+
+ for (i=0; i < OP_DEFS(op)->size ;i++) {
+ if (bitVectBitValue(OP_DEFS(op),i) &&
+ (lic = hTabItemWithKey(iCodehTab,i)) &&
+ lic->seq < fSeq) {
+
+ fSeq = lic->seq ;
+ ric = lic;
+ }
+ }
+ return ric;
+}
+/*-----------------------------------------------------------------*/
+/* useDefLoopCheck - check for uses before init inside loops */
+/*-----------------------------------------------------------------*/
+static void useDefLoopCheck(operand *op,iCode *ic)
+{
+ /* this is for situations like the following
+ int a,b;
+
+ while (...) {
+ a = ... ;
+ ...
+ _some_usage_of_b_;
+ ...
+ b = ... ;
+ }
+ in this case the definition of 'b' will flow to the usages
+ but register allocator cannot handle these situations.so
+ will mark as spilt */
+
+ int i =0, fdSeq ;
+ int er=0;
+ iCode *tic ;
+
+ /* get the first definition */
+ if (!(tic = firstDefOf(op)))
+ return ;
+
+ fdSeq = tic->seq;
+ /* now go thru the usages & make sure they follow
+ the first definition */
+ for (i=0; i <= OP_USES(op)->size;i++ ) {
+ if (bitVectBitValue(OP_USES(op),i) &&
+ (tic = hTabItemWithKey(iCodehTab,i)) &&
+ tic->seq < fdSeq){
+ er = 1;
+ break;
+ }
+ }
+
+ /* found a usage without definition */
+ if (er) {
+ if (OP_SYMBOL(op)->isreqv && SPIL_LOC(op) ) {
+
+ werror(W_LOCAL_NOINIT,
+ SPIL_LOC(op)->name,
+ ic->filename,ic->lineno);
+ } else {
+
+ werror(W_LOCAL_NOINIT,
+ OP_SYMBOL(op)->name,
+ ic->filename,ic->lineno);
+ }
+ OP_SYMBOL(op)->isspilt = 1;
+ }
+}
+
/*-----------------------------------------------------------------*/
/* operandLUse - check and set the last use for a given operand */
}
ic->uses = bitVectSetBit(ic->uses,op->key);
+ if (!OP_SYMBOL(op)->udChked)
{
link *type = operandType(op);
link *etype = getSpec(type);
-
+
+ OP_SYMBOL(op)->udChked = 1;
/* good place to check if unintialised */
if ((IS_TRUE_SYMOP(op) || OP_SYMBOL(op)->isreqv) &&
OP_SYMBOL(op)->islocal &&
OP_SYMBOL(op)->name,
ic->filename,ic->lineno);
}
- }
- }
+ } else {
+ if (ebp->depth && op->usesDefs &&
+ !OP_SYMBOL(op)->_isparm) {
+ /* check non-inits inside loops */
+ useDefLoopCheck(op,ic);
+ }
+ }
+ }
}
return op;
}
-/*-----------------------------------------------------------------*/
-/* compLastUse - computes the last usage with certainty */
-/*-----------------------------------------------------------------*/
-void compLastUse ()
-{
- symbol *sym;
- int key;
- /* the strategy here is to look for live ranges that are not
- induction variables, and find out the usage icode with the
- highest sequence number then set the to range to that icode
- sequence */
- /* once fully tested we can use only this routine to mark the
- to range that will reduce a lot of computations in the
- markLiveRanges routine */
- for (sym = hTabFirstItem(liveRanges,&key) ; sym;
- sym = hTabNextItem(liveRanges,&key)) {
-
- int i ;
- int maxKey = 0 ;
-
- if (sym->isind)
- continue ;
-
- if (!sym->uses)
- continue ;
-
- /* go thru all the usages of this live range and find out
- the maximum sequence number of the icode that used it */
- for (i = 0 ; i < sym->uses->size ; i++ ) {
- iCode *uic ;
-
- if (!bitVectBitValue(sym->uses,i))
- continue ;
-
- if ((uic = hTabItemWithKey(iCodehTab,i)))
- maxKey = ( uic->seq > maxKey ? uic->seq : maxKey );
- }
-
- /* got it */
- if (maxKey)
- sym->liveTo = maxKey;
- }
-}
-
/*-----------------------------------------------------------------*/
/* killAllAlive - mark all the definitions living with this seq */
/*-----------------------------------------------------------------*/
for ( i = 0 ; i < count; i++ )
markLiveRanges (ebbs[i],ebbs,count);
-/* compLastUse(); */
/* mark the ranges live for each point */
rlivePoint (ebbs,count);
}
glue();
if (!options.c1mode)
assemble(envp);
- }
+ } else {
+ exit(-1);
+ }
}
case V_BIT:
fprintf(of,"bit {%d,%d}",SPEC_BSTR(type),SPEC_BLEN(type));
break;
+
+ default:
+ break;
}
}
type = type->next;
case ARRAY :
fprintf (of,"DA%d,",DCL_ELEM(type));
break;
+ default:
+ break;
}
} else {
switch (SPEC_NOUN(type)) {
case V_BIT:
fprintf(of,"SB%d$%d",SPEC_BSTR(type),SPEC_BLEN(type));
break;
+
+ default:
+ break;
}
fputs(":",of);
if (SPEC_USIGN(type))
unsigned isreqv :1 ; /* is the register quivalent of a symbol */
unsigned hasFcall :1 ; /* for functions does it call other functions */
unsigned calleeSave :1 ; /* for functions uses callee save paradigm */
+ unsigned udChked :1 ; /* use def checking has been already done */
/* following flags are used by the backend
for code generation and can be changed
/** @file main.c
- mcs51 specific general functions.
+ avr specific general functions.
- Note that mlh prepended _mcs51_ on the static functions. Makes
+ Note that mlh prepended _avr_ on the static functions. Makes
it easier to set a breakpoint using the debugger.
*/
#include "common.h"
};
/* list of key words used by msc51 */
-static char *_mcs51_keywords[] = {
+static char *_avr_keywords[] = {
"at",
- "bit",
"code",
"critical",
- "data",
- "far",
- "idata",
+ "eeprom"
"interrupt",
- "near",
- "pdata",
- "reentrant",
"sfr",
"sbit",
- "using",
"xdata",
- "_data",
"_code",
+ "_eeprom"
"_generic",
- "_near",
"_xdata",
- "_pdata",
- "_idata",
NULL
};
-void mcs51_assignRegisters (eBBlock **ebbs, int count);
+void avr_assignRegisters (eBBlock **ebbs, int count);
-static bool _mcs51_parseOptions(int *pargc, char **argv, int *i)
+static bool _avr_parseOptions(int *pargc, char **argv, int *i)
{
/* TODO: allow port-specific command line options to specify
* segment names here.
return FALSE;
}
-static void _mcs51_finaliseOptions(void)
+static void _avr_finaliseOptions(void)
{
- /* Hack-o-matic: if we are using the flat24 model,
- * adjust pointer sizes.
- */
- if (options.model == MODEL_FLAT24)
- {
- port->s.fptr_size = 3;
- port->s.gptr_size = 4;
- port->stack.isr_overhead++; /* Will save dpx on ISR entry. */
- #if 1
- port->stack.call_overhead++; /* This acounts for the extra byte
- * of return addres on the stack.
- * but is ugly. There must be a
- * better way.
- */
- #endif
- fReturn = fReturn390;
- fReturnSize = 5;
- }
+ port->default_local_map =
+ port->default_globl_map = xdata;
}
-static void _mcs51_setDefaultOptions(void)
+static void _avr_setDefaultOptions(void)
{
}
-static const char *_mcs51_getRegName(struct regs *reg)
+static const char *_avr_getRegName(struct regs *reg)
{
if (reg)
return reg->name;
return "err";
}
-static void _mcs51_genAssemblerPreamble(FILE *of)
+static void _avr_genAssemblerPreamble(FILE *of)
{
- if (options.model == MODEL_FLAT24)
- {
- fputs(".flat24 on\t\t; 24 bit flat addressing\n", of);
- fputs("dpx = 0x93\t\t; dpx register unknown to assembler\n", of);
- }
}
/* Generate interrupt vector table. */
-static int _mcs51_genIVT(FILE *of, symbol **interrupts, int maxInterrupts)
+static int _avr_genIVT(FILE *of, symbol **interrupts, int maxInterrupts)
{
- int i;
-
- if (options.model != MODEL_FLAT24)
- {
- /* Let the default code handle it. */
- return FALSE;
- }
-
- fprintf (of, "\tajmp\t__sdcc_gsinit_startup\n");
-
- /* now for the other interrupts */
- for (i = 0; i < maxInterrupts; i++)
- {
- if (interrupts[i])
- {
- fprintf(of, "\tljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
- }
- else
- {
- fprintf(of, "\treti\n\t.ds\t7\n");
- }
- }
-
return TRUE;
}
};
/* Globals */
-PORT mcs51_port = {
- "mcs51",
- "MCU 8051", /* Target name */
+PORT avr_port = {
+ "avr",
+ "ATMEL AVR", /* Target name */
{
TRUE, /* Emit glue around main */
},
"RSEG (DATA)",
"GSINIT (CODE)",
"OSEG (OVR,DATA)",
- "GSFINAL (CODE)"
+ "GSFINAL (CODE)",
+ NULL,
+ NULL,
},
{
+1, 1, 4, 1, 1
},
- /* mcs51 has an 8 bit mul */
+ /* avr has an 8 bit mul */
{
1
},
NULL,
- _mcs51_parseOptions,
- _mcs51_finaliseOptions,
- _mcs51_setDefaultOptions,
- mcs51_assignRegisters,
- _mcs51_getRegName ,
- _mcs51_keywords,
- _mcs51_genAssemblerPreamble,
- _mcs51_genIVT
+ _avr_parseOptions,
+ _avr_finaliseOptions,
+ _avr_setDefaultOptions,
+ avr_assignRegisters,
+ _avr_getRegName ,
+ _avr_keywords,
+ _avr_genAssemblerPreamble,
+ _avr_genIVT
};
/*-----------------------------------------------------------------*/
static int pointerCode (link *etype)
{
- int p_type;
return PTR_TYPE(SPEC_OCLS(etype));
-/* if (SPEC_OCLS(etype)->codesp ) { */
-/* p_type = CPOINTER ; */
-/* } */
-/* else */
-/* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
-/* p_type = FPOINTER ; */
-/* else */
-/* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
-/* p_type = PPOINTER; */
-/* else */
-/* if (SPEC_OCLS(etype) == idata ) */
-/* p_type = IPOINTER; */
-/* else */
-/* p_type = POINTER ; */
-/* return p_type; */
}
/*-----------------------------------------------------------------*/
}
/* if debug then send end of function */
-/* if (options.debug && currFunc) { */
if (currFunc) {
_G.debugLine = 1;
emitcode("","C$%s$%d$%d$%d ==.",
}
}
- /* printf("findLabelBackwards: not found.\n"); */
-
return 0;
}
rumask = newBitVect(mcs51_nRegs);
- for (j = 0; j < sym->nRegs; j++) {
+ for (j = 0; j < sym->nRegs; j++) {
rumask = bitVectSetBit(rumask,
sym->regs[j]->rIdx);
}