+2004-11-18 Maarten Brock <sourceforge.brock AT dse.nl>
+
+ * .version: bumped version to 2.4.7
+ * device/lib/_gptrget.c (_gptrget): is now _naked
+ * device/lib/_gptrgetc.c (_gptrgetc): is now _naked
+ * device/lib/_gptrput.c (_gptrput): is now _naked
+ * src/SDCCast.c (createBlock): removed ridiculous self-assignment,
+ (createFunction): fixed xstack
+ * src/SDCCglue.c (emitMaps): set allocation required for bit area
+ * src/SDCCicode.c (geniCodeCast): don't change SPEC_OCLS for literal
+ or bit either,
+ (geniCodeCritical): store original interrupt state in an iTemp bit
+ var unless stack-auto
+ * src/SDCCicode.h: added CRITICAL and ENDCRITICAL to SKIP_IC2
+ * src/SDCCmain.c (setIncludePath): added include/target to search path
+ * src/SDCCmem.c (allocParms): store bit vars in bit space, not overlay
+ * src/SDCCsymt.c (checkFunction): don't check regbank for isr's against
+ prototype,
+ (processFuncArgs): put bit vars in bit area
+ * src/mcs51/gen.c (saveRegisters, unsaveRegisters, genXpush, saveRBank,
+ unsaveRBank): fixed xstack,
+ (genFunction): bugfix: replaced (global!) reentrant with fReentrant,
+ (genFunction, genEndFunction): fixed xstack,
+ (genAssign): optimization don't walk backwards through mem
+ * src/mcs51/main.c (_mcs51_regparm): don't pass bit params in registers
+ * src/mcs51/ralloc.c (createStackSpil): spill bits to bit area
+ * support/regression/Makefile: also make library (for stack-auto) when
+ making "all" and added "test-mcs51-xstack-auto"
+ * support/regression/fwk/lib/testfwk.c: added T2_isr prototype for mcs51
+ * support/regression/ports/mcs51/T2_isr.c: added this file as a stub
+ * support/regression/ports/mcs51/fwk.lib: added to link T2_isr stub
+ * support/regression/ports/mcs51/spec.mk: added rules for fwk.lib
+ * support/regression/ports/mcs51-stack-auto/spec.mk: replaced
+ make-library by MAKE_LIBRARY
+ * support/regression/ports/mcs51-xstack-auto/spec.mk: file added to run
+ regression tests for xstack
+ * support/regression/tests/bitvars.c: test for bit vars (bug 938782)
+ * support/regression/tests/critical.c: test for critical on mcs51
+
2004-11-18 Erik Petrich <epetrich AT ivorytower.norman.ok.us>
* support/regression/ports/ucz80/spec.mk: use include and lib files from
/* the return value is expected to be in acc, and not in the standard
* location dpl. Therefore we choose return type void here: */
void
-_gptrget (char *gptr)
+_gptrget (char *gptr) _naked
{
gptr; /* hush the compiler */
_asm
+ ar0 = 0x00
; save values passed
;
; depending on the pointer type acc. to SDCCsymt.h
; return
;
00005$:
+ ret
_endasm ;
}
/* the return value is expected to be in acc, and not in the standard
* location dpl. Therefore we choose return type void here: */
void
-_gptrgetc (char *gptr)
+_gptrgetc (char *gptr) _naked
{
gptr; /* hush the compiler */
dec a
jz 00003$ ; 2 code
dec a
- jz 00004$
+ jz 00004$ ; 3 pdata
dec a ; 4 skip generic pointer
dec a
jz 00001$ ; 5 idata
00005$:
mov r0,a
pop acc
- xch a,r0
+ xch a,r0
+ ret
_endasm ;
}
#define USE_PDATA_PAGING_REGISTER 0
void
-_gptrput (char *gptr, char c)
+_gptrput (char *gptr, char c) _naked
{
gptr; c; /* hush the compiler */
_asm
+ ar0 = 0x00
push acc
;
; depending on the pointer type acc. to SDCCsymt.h
#endif
00005$:
+ ret
_endasm;
}
ex = newNode (BLOCK, NULL, body);
ex->values.sym = decl;
- ex->right = ex->right;///?????
ex->level++;
ex->lineno = 0;
return ex;
currFunc = name;
/* set the stack pointer */
- /* PENDING: check this for the mcs51 */
- stackPtr = -port->stack.direction * port->stack.call_overhead;
+ stackPtr = -port->stack.direction * port->stack.call_overhead;
+ xstackPtr = -port->stack.direction * port->stack.call_overhead;
+
if (IFFUNC_ISISR (name->type))
stackPtr -= port->stack.direction * port->stack.isr_overhead;
- if (IFFUNC_ISREENT (name->type) || options.stackAuto)
- stackPtr -= port->stack.direction * port->stack.reent_overhead;
- xstackPtr = -port->stack.direction * port->stack.call_overhead;
+ if (IFFUNC_ISREENT (name->type) || options.stackAuto)
+ {
+ if (options.useXstack)
+ xstackPtr -= port->stack.direction * port->stack.reent_overhead;
+ else
+ stackPtr -= port->stack.direction * port->stack.reent_overhead;
+ }
fetype = getSpec (name->type); /* get the specifier for the function */
/* if this is a reentrant function then */
data, idata & bit & xdata */
emitRegularMap (data, TRUE, TRUE);
emitRegularMap (idata, TRUE, TRUE);
- emitRegularMap (bit, TRUE, FALSE);
+ emitRegularMap (bit, TRUE, TRUE);
emitRegularMap (pdata, TRUE, TRUE);
emitRegularMap (xdata, TRUE, TRUE);
if (port->genXINIT) {
cdbStructBlock (0);
vFile = tempfile ();
- /* PENDING: this isnt the best place but it will do */
+ /* PENDING: this isn't the best place but it will do */
if (port->general.glue_up_main)
{
/* create the interrupt vector table */
{
symbol *itmplbl;
- /* check if this alredy exists */
+ /* check if this already exists */
if (s && (itmplbl = findSym (LabelTab, NULL, s)))
return itmplbl;
restype = getSpec (operandType (IC_RESULT (ic)));
if (!IS_LITERAL(opetype) &&
!IS_BIT(opetype))
+ {
SPEC_SCLS (restype) = SPEC_SCLS (opetype);
- SPEC_OCLS (restype) = SPEC_OCLS (opetype);
-
+ SPEC_OCLS (restype) = SPEC_OCLS (opetype);
+ }
ADDTOCHAIN (ic);
return IC_RESULT (ic);
}
/* hack don't like this but too lazy to think of
something better */
if (IS_ADDRESS_OF_OP (parms))
- parms->left->lvalue = 1;
+ parms->left->lvalue = 1;
if (IS_CAST_OP (parms) &&
- IS_PTR (parms->ftype) &&
- IS_ADDRESS_OF_OP (parms->right))
- parms->right->left->lvalue = 1;
+ IS_PTR (parms->ftype) &&
+ IS_ADDRESS_OF_OP (parms->right))
+ parms->right->left->lvalue = 1;
pval = geniCodeRValue (ast2iCode (parms,lvl+1), FALSE);
}
{
/* now decide whether to push or assign */
if (!(options.stackAuto || IFFUNC_ISREENT (ftype)))
- {
+ {
- /* assign */
- operand *top = operandFromSymbol (argVals->sym);
- /* clear useDef and other bitVectors */
- OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
- geniCodeAssign (top, pval, 1, 0);
- }
+ /* assign */
+ operand *top = operandFromSymbol (argVals->sym);
+ /* clear useDef and other bitVectors */
+ OP_USES(top)=OP_DEFS(top)=OP_SYMBOL(top)->clashes = NULL;
+ geniCodeAssign (top, pval, 1, 0);
+ }
else
- {
- sym_link *p = operandType (pval);
- /* push */
- ic = newiCode (IPUSH, pval, NULL);
- ic->parmPush = 1;
- /* update the stack adjustment */
- *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
- ADDTOCHAIN (ic);
- }
+ {
+ sym_link *p = operandType (pval);
+ /* push */
+ ic = newiCode (IPUSH, pval, NULL);
+ ic->parmPush = 1;
+ /* update the stack adjustment */
+ *stack += getSize (IS_AGGREGATE (p) ? aggrToPtr (p, FALSE) : p);
+ ADDTOCHAIN (ic);
+ }
}
argVals=argVals->next;
{
iCode *ic;
operand *op = NULL;
+ sym_link *type;
+
+ if (!options.stackAuto)
+ {
+ type = newLink(SPECIFIER);
+ SPEC_VOLATILE(type) = 1;
+ SPEC_NOUN(type) = V_BIT;
+ SPEC_SCLS(type) = S_BIT;
+ SPEC_BLEN(type) = 1;
+ SPEC_BSTR(type) = 0;
+ op = newiTempOperand(type, 1);
+ }
/* If op is NULL, the original interrupt state will saved on */
/* the stack. Otherwise, it will be saved in op. */
- /* Generate a save of the current interrupt state & disabled */
+ /* Generate a save of the current interrupt state & disable */
ic = newiCode (CRITICAL, NULL, NULL);
IC_RESULT (ic) = op;
ADDTOCHAIN (ic);
iCodeTable;
/* useful macros */
-#define SKIP_IC2(x) (x->op == GOTO || \
- x->op == LABEL || \
- x->op == FUNCTION || \
- x->op == INLINEASM || \
- x->op == ENDFUNCTION )
-
-#define SKIP_IC1(x) (x->op == CALL || \
+#define SKIP_IC2(x) (x->op == GOTO || \
+ x->op == LABEL || \
+ x->op == FUNCTION || \
+ x->op == INLINEASM || \
+ x->op == ENDFUNCTION || \
+ x->op == CRITICAL || \
+ x->op == ENDCRITICAL )
+
+#define SKIP_IC1(x) (x->op == CALL || \
SKIP_IC2(x) )
-#define SKIP_IC(x) (x->op == PCALL || \
- x->op == IPUSH || \
- x->op == IPOP || \
- x->op == JUMPTABLE || \
- x->op == RECEIVE || \
- x->op == ARRAYINIT || \
- SKIP_IC1(x)|| \
+#define SKIP_IC(x) (x->op == PCALL || \
+ x->op == IPUSH || \
+ x->op == IPOP || \
+ x->op == JUMPTABLE || \
+ x->op == RECEIVE || \
+ x->op == ARRAYINIT || \
+ SKIP_IC1(x) || \
x->op == SEND )
-#define SKIP_IC3(x) (SKIP_IC2(x) || \
+#define SKIP_IC3(x) (SKIP_IC2(x) || \
x->op == JUMPTABLE )
#define IS_CONDITIONAL(x) (x->op == EQ_OP || \
setIncludePath(void)
{
char *p;
+ set *tempSet=NULL;
/*
* Search logic:
*
- * 1. - $SDCC_INCLUDE
- * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
- * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
- * 4. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
+ * 1. - $SDCC_INCLUDE/target
+ * 2. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX/target
+ * 3. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX/target
+ * 4. - DATADIR/INCLUDE_DIR_SUFFIX/target (only on *nix)
+ * 5. - $SDCC_INCLUDE
+ * 6. - $SDCC_HOME/PREFIX2DATA_DIR/INCLUDE_DIR_SUFFIX
+ * 7. - path(argv[0])/BIN2DATA_DIR/INCLUDE_DIR_SUFFIX
+ * 8. - DATADIR/INCLUDE_DIR_SUFFIX (only on *nix)
*/
if (options.nostdinc)
return;
- includeDirsSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
+ tempSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX);
+ includeDirsSet = appendStrSet(tempSet, NULL, DIR_SEPARATOR_STRING);
+ includeDirsSet = appendStrSet(includeDirsSet, NULL, port->target);
+ mergeSets(&includeDirsSet, tempSet);
if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
addSetHead(&includeDirsSet, p);
#include "common.h"
/* memory segments */
-memmap *xstack = NULL; /* xternal stack data */
-memmap *istack = NULL; /* internal stack */
-memmap *code = NULL; /* code segment */
-memmap *data = NULL; /* internal data upto 128 */
-memmap *pdata = NULL; /* paged external data */
-memmap *xdata = NULL; /* external data */
+memmap *xstack = NULL; /* xternal stack data */
+memmap *istack = NULL; /* internal stack */
+memmap *code = NULL; /* code segment */
+memmap *data = NULL; /* internal data upto 128 */
+memmap *pdata = NULL; /* paged external data */
+memmap *xdata = NULL; /* external data */
memmap *xidata = NULL; /* the initialized xdata */
memmap *xinit = NULL; /* the initializers for xidata */
-memmap *idata = NULL; /* internal data upto 256 */
-memmap *bit = NULL; /* bit addressable space */
-memmap *statsg = NULL; /* the constant data segment */
-memmap *sfr = NULL; /* register space */
-memmap *reg = NULL; /* register space */
-memmap *sfrbit = NULL; /* sfr bit space */
-memmap *generic = NULL; /* is a generic pointer */
-memmap *overlay = NULL; /* overlay segment */
-memmap *eeprom = NULL; /* eeprom location */
-memmap *home = NULL; /* Unswitchable code bank */
+memmap *idata = NULL; /* internal data upto 256 */
+memmap *bit = NULL; /* bit addressable space */
+memmap *statsg = NULL; /* the constant data segment */
+memmap *sfr = NULL; /* register space */
+memmap *reg = NULL; /* register space */
+memmap *sfrbit = NULL; /* sfr bit space */
+memmap *generic = NULL; /* is a generic pointer */
+memmap *overlay = NULL; /* overlay segment */
+memmap *eeprom = NULL; /* eeprom location */
+memmap *home = NULL; /* Unswitchable code bank */
/* this is a set of sets each set containing
symbols in a single overlay */
set *ovrSetSets = NULL;
int maxRegBank = 0;
-int fatalError = 0; /* fatal error flag */
+int fatalError = 0; /* fatal error flag */
/*-----------------------------------------------------------------*/
/* allocMap - allocates a memory map */
/*-----------------------------------------------------------------*/
memmap *
-allocMap (char rspace, /* sfr space */
- char farmap, /* far or near segment */
- char paged, /* can this segment be paged */
- char direct, /* directly addressable */
- char bitaddr, /* bit addressable space */
- char codemap, /* this is code space */
- unsigned sloc, /* starting location */
- const char *name, /* 2 character name */
- char dbName, /* debug name */
- int ptrType /* pointer type for this space */
+allocMap (char rspace, /* sfr space */
+ char farmap, /* far or near segment */
+ char paged, /* can this segment be paged */
+ char direct, /* directly addressable */
+ char bitaddr, /* bit addressable space */
+ char codemap, /* this is code space */
+ unsigned sloc, /* starting location */
+ const char *name, /* 2 character name */
+ char dbName, /* debug name */
+ int ptrType /* pointer type for this space */
)
{
memmap *map;
/*-----------------------------------------------------------------*/
/* initMem - allocates and initializes all the segments */
/*-----------------------------------------------------------------*/
-void
+void
initMem ()
{
/* allocate all the segments */
- /* xternal stack segment ;
+ /* xternal stack segment ;
SFRSPACE - NO
FAR-SPACE - YES
PAGED - YES
DIRECT-ACCESS - NO
BIT-ACCESS - NO
- CODE-ACESS - NO
+ CODE-ACESS - NO
DEBUG-NAME - 'A'
POINTER-TYPE - FPOINTER
*/
xstack = allocMap (0, 1, 1, 0, 0, 0, options.xstack_loc, XSTACK_NAME, 'A', PPOINTER);
- /* internal stack segment ;
+ /* internal stack segment ;
SFRSPACE - NO
FAR-SPACE - NO
PAGED - NO
DIRECT-ACCESS - NO
BIT-ACCESS - NO
- CODE-ACESS - NO
+ CODE-ACESS - NO
DEBUG-NAME - 'B'
POINTER-TYPE - POINTER
*/
if (ISTACK_NAME) {
- istack = allocMap (0, 0, 0, 0, 0, 0, options.stack_loc,
- ISTACK_NAME, 'B', POINTER);
+ istack = allocMap (0, 0, 0, 0, 0, 0, options.stack_loc,
+ ISTACK_NAME, 'B', POINTER);
} else {
istack=NULL;
}
- /* code segment ;
+ /* code segment ;
SFRSPACE - NO
FAR-SPACE - YES
PAGED - NO
DIRECT-ACCESS - NO
BIT-ACCESS - NO
- CODE-ACESS - YES
+ CODE-ACESS - YES
DEBUG-NAME - 'C'
POINTER-TYPE - CPOINTER
*/
code = allocMap (0, 1, 0, 0, 0, 1, options.code_loc, CODE_NAME, 'C', CPOINTER);
- /* home segment ;
+ /* home segment ;
SFRSPACE - NO
FAR-SPACE - YES
PAGED - NO
DIRECT-ACCESS - NO
BIT-ACCESS - NO
- CODE-ACESS - YES
+ CODE-ACESS - YES
DEBUG-NAME - 'C'
POINTER-TYPE - CPOINTER
*/
PAGED - NO
DIRECT-ACCESS - NO
BIT-ACCESS - NO
- CODE-ACESS - YES
+ CODE-ACESS - YES
DEBUG-NAME - 'D'
POINTER-TYPE - CPOINTER
*/
PAGED - NO
DIRECT-ACCESS - YES
BIT-ACCESS - NO
- CODE-ACESS - NO
+ CODE-ACESS - NO
DEBUG-NAME - 'E'
POINTER-TYPE - POINTER
*/
PAGED - NO
DIRECT-ACCESS - YES
BIT-ACCESS - NO
- CODE-ACESS - NO
+ CODE-ACESS - NO
DEBUG-NAME - 'E'
POINTER-TYPE - POINTER
*/
pdata = NULL;
}
- /* Xternal Data segment -
+ /* Xternal Data segment -
SFRSPACE - NO
FAR-SPACE - YES
PAGED - NO
DIRECT-ACCESS - NO
BIT-ACCESS - NO
- CODE-ACESS - NO
+ CODE-ACESS - NO
DEBUG-NAME - 'F'
POINTER-TYPE - FPOINTER
*/
PAGED - NO
DIRECT-ACCESS - NO
BIT-ACCESS - NO
- CODE-ACESS - NO
+ CODE-ACESS - NO
DEBUG-NAME - 'G'
POINTER-TYPE - IPOINTER
*/
if (IDATA_NAME) {
- idata = allocMap (0, 0, 0, 0, 0, 0, options.idata_loc,
- IDATA_NAME, 'G', IPOINTER);
+ idata = allocMap (0, 0, 0, 0, 0, 0, options.idata_loc,
+ IDATA_NAME, 'G', IPOINTER);
} else {
- idata = NULL;
+ idata=NULL;
}
/* Static segment (code for variables );
PAGED - NO
DIRECT-ACCESS - YES
BIT-ACCESS - YES
- CODE-ACESS - NO
+ CODE-ACESS - NO
DEBUG-NAME - 'H'
POINTER-TYPE - _NONE_
*/
PAGED - NO
DIRECT-ACCESS - YES
BIT-ACCESS - NO
- CODE-ACESS - NO
+ CODE-ACESS - NO
DEBUG-NAME - 'I'
POINTER-TYPE - _NONE_
*/
PAGED - NO
DIRECT-ACCESS - NO
BIT-ACCESS - NO
- CODE-ACESS - NO
+ CODE-ACESS - NO
DEBUG-NAME - ' '
POINTER-TYPE - _NONE_
*/
reg = allocMap (1, 0, 0, 0, 0, 0, 0, REG_NAME, ' ', 0);
- /* SFR bit space
+ /* SFR bit space
SFRSPACE - YES
FAR-SPACE - NO
PAGED - NO
DIRECT-ACCESS - YES
BIT-ACCESS - YES
- CODE-ACESS - NO
+ CODE-ACESS - NO
DEBUG-NAME - 'J'
POINTER-TYPE - _NONE_
*/
sfrbit = allocMap (1, 0, 0, 1, 1, 0, 0, REG_NAME, 'J', 0);
- /* EEPROM bit space
+ /* EEPROM bit space
SFRSPACE - NO
FAR-SPACE - YES
PAGED - NO
DIRECT-ACCESS - NO
BIT-ACCESS - NO
- CODE-ACESS - NO
+ CODE-ACESS - NO
DEBUG-NAME - 'K'
POINTER-TYPE - EEPPOINTER
*/
/*-----------------------------------------------------------------*/
/* allocIntoSeg - puts a symbol into a memory segment */
/*-----------------------------------------------------------------*/
-void
+void
allocIntoSeg (symbol * sym)
{
memmap *segment = SPEC_OCLS (sym->etype);
/*-----------------------------------------------------------------*/
/* deleteFromSeg - deletes a symbol from segment used when a var */
-/* firest declared as "extern" then no extern */
+/* first declared as "extern" then no extern */
/*-----------------------------------------------------------------*/
void deleteFromSeg(symbol *sym)
{
if (SPEC_OCLS(sym->etype)) {
- memmap *segment = SPEC_OCLS (sym->etype);
- deleteSetItem(&segment->syms,sym);
+ memmap *segment = SPEC_OCLS (sym->etype);
+ deleteSetItem(&segment->syms,sym);
}
}
/*-----------------------------------------------------------------*/
/* allocGlobal - assigns the output segment to a global var */
/*-----------------------------------------------------------------*/
-void
+void
allocGlobal (symbol * sym)
{
/* symbol name is internal name */
- if (!sym->level) /* local statics can come here */
- SNPRINTF (sym->rname, sizeof(sym->rname),
- "%s%s", port->fun_prefix, sym->name);
+ if (!sym->level) /* local statics can come here */
+ SNPRINTF (sym->rname, sizeof(sym->rname),
+ "%s%s", port->fun_prefix, sym->name);
/* add it to the operandKey reset */
if (!isinSet (operKeyReset, sym)) {
then put it in the interrupt service array */
if (FUNC_ISISR (sym->type) && !options.noiv
&& (FUNC_INTNO (sym->type) != INTNO_UNSPEC))
- {
+ {
if (interrupts[FUNC_INTNO (sym->type)])
werror (E_INT_DEFINED,
FUNC_INTNO (sym->type),
/* automagically extend the maximum interrupts */
if (FUNC_INTNO (sym->type) >= maxInterrupts)
maxInterrupts = FUNC_INTNO (sym->type) + 1;
- }
+ }
/* if it is not compiler defined */
if (!sym->cdef)
allocIntoSeg (sym);
{
SPEC_OCLS (sym->etype) =
- (SPEC_SCLS (sym->etype) == S_SFR ? sfr : sfrbit);
+ (SPEC_SCLS (sym->etype) == S_SFR ? sfr : sfrbit);
allocIntoSeg (sym);
return;
if(!TARGET_IS_PIC16 || (TARGET_IS_PIC16 && sym->level))
/* register storage class ignored changed to FIXED */
- if (SPEC_SCLS (sym->etype) == S_REGISTER)
- SPEC_SCLS (sym->etype) = S_FIXED;
+ if (SPEC_SCLS (sym->etype) == S_REGISTER)
+ SPEC_SCLS (sym->etype) = S_FIXED;
/* if data specified then */
if (SPEC_SCLS (sym->etype) == S_DATA)
{
// should we move this to the initialized data segment?
if (port->genXINIT &&
- sym->ival && (sym->level==0) && !SPEC_ABSA(sym->etype)) {
+ sym->ival && (sym->level==0) && !SPEC_ABSA(sym->etype)) {
SPEC_OCLS(sym->etype)=xidata;
} else {
SPEC_OCLS (sym->etype) = xdata;
/*-----------------------------------------------------------------*/
/* allocParms - parameters are always passed on stack */
/*-----------------------------------------------------------------*/
-void
+void
allocParms (value * val)
{
value *lval;
if (lval->sym)
lval->sym->onStack = 1;
- /* choose which stack 2 use */
- /* use xternal stack */
- if (options.useXstack)
- {
- /* PENDING: stack direction support */
- SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xstack;
- SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
- xstackPtr - getSize (lval->type);
- xstackPtr -= getSize (lval->type);
- }
- else
- { /* use internal stack */
- SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = istack;
- if (port->stack.direction > 0)
- {
- SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
- stackPtr - (FUNC_REGBANK (currFunc->type) ? port->stack.bank_overhead : 0) -
- getSize (lval->type) -
- (FUNC_ISISR (currFunc->type) ? port->stack.isr_overhead : 0);
- stackPtr -= getSize (lval->type);
- }
- else
- {
- /* This looks like the wrong order but it turns out OK... */
- /* PENDING: isr, bank overhead, ... */
- SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
- stackPtr +
- ((IFFUNC_ISBANKEDCALL (currFunc->type) && !SPEC_STAT(getSpec(currFunc->etype)))? port->stack.banked_overhead : 0) +
- (FUNC_ISISR (currFunc->type) ? port->stack.isr_overhead : 0) +
- 0;
- stackPtr += getSize (lval->type);
- }
- }
- allocIntoSeg (lval->sym);
- }
+ /* choose which stack 2 use */
+ /* use xternal stack */
+ if (options.useXstack)
+ {
+ /* PENDING: stack direction support */
+ SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xstack;
+ SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
+ xstackPtr - getSize (lval->type);
+ xstackPtr -= getSize (lval->type);
+ }
+ else
+ { /* use internal stack */
+ SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = istack;
+ if (port->stack.direction > 0)
+ {
+ SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
+ stackPtr - (FUNC_REGBANK (currFunc->type) ? port->stack.bank_overhead : 0) -
+ getSize (lval->type) -
+ (FUNC_ISISR (currFunc->type) ? port->stack.isr_overhead : 0);
+ stackPtr -= getSize (lval->type);
+ }
+ else
+ {
+ /* This looks like the wrong order but it turns out OK... */
+ /* PENDING: isr, bank overhead, ... */
+ SPEC_STAK (lval->etype) = SPEC_STAK (lval->sym->etype) = lval->sym->stack =
+ stackPtr +
+ ((IFFUNC_ISBANKEDCALL (currFunc->type) && !SPEC_STAT(getSpec(currFunc->etype)))? port->stack.banked_overhead : 0) +
+ (FUNC_ISISR (currFunc->type) ? port->stack.isr_overhead : 0) +
+ 0;
+ stackPtr += getSize (lval->type);
+ }
+ }
+ allocIntoSeg (lval->sym);
+ }
else
- { /* allocate them in the automatic space */
- /* generate a unique name */
- SNPRINTF (lval->sym->rname, sizeof(lval->sym->rname),
- "%s%s_PARM_%d", port->fun_prefix, currFunc->name, pNum);
- strncpyz (lval->name, lval->sym->rname, sizeof(lval->name));
-
- /* if declared in external storage */
- if (SPEC_SCLS (lval->etype) == S_XDATA)
- SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xdata;
- else
- /* other wise depending on the memory model
- note here that we put it into the overlay segment
- first, we will remove it from the overlay segment
- after the overlay determination has been done */
- if (options.model == MODEL_SMALL)
- {
- SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) =
- (options.noOverlay ? port->mem.default_local_map
- : overlay);
- }
- else
- {
- SPEC_SCLS (lval->etype) = S_XDATA;
- SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xdata;
- }
- allocIntoSeg (lval->sym);
- }
+ { /* allocate them in the automatic space */
+ /* generate a unique name */
+ SNPRINTF (lval->sym->rname, sizeof(lval->sym->rname),
+ "%s%s_PARM_%d", port->fun_prefix, currFunc->name, pNum);
+ strncpyz (lval->name, lval->sym->rname, sizeof(lval->name));
+
+ /* if declared in external storage */
+ if (SPEC_SCLS (lval->etype) == S_XDATA)
+ SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xdata;
+ else if (SPEC_SCLS (lval->etype) == S_BIT)
+ SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = bit;
+ else
+ /* otherwise depending on the memory model
+ note here that we put it into the overlay segment
+ first, we will remove it from the overlay segment
+ after the overlay determination has been done */
+ if (options.model == MODEL_SMALL)
+ {
+ SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) =
+ (options.noOverlay ? port->mem.default_local_map
+ : overlay);
+ }
+ else
+ {
+ SPEC_SCLS (lval->etype) = S_XDATA;
+ SPEC_OCLS (lval->etype) = SPEC_OCLS (lval->sym->etype) = xdata;
+ }
+ allocIntoSeg (lval->sym);
+ }
}
return;
/*-----------------------------------------------------------------*/
/* deallocParms - parameters are always passed on stack */
/*-----------------------------------------------------------------*/
-void
+void
deallocParms (value * val)
{
value *lval;
deleteSym (SymbolTab, lval->sym, lval->sym->name);
if (!lval->sym->isref)
- {
- lval->sym->allocreq = 0;
- werror (W_NO_REFERENCE,
- currFunc ? currFunc->name : "(unknown)",
- "function argument", lval->sym->name);
- }
+ {
+ lval->sym->allocreq = 0;
+ werror (W_NO_REFERENCE,
+ currFunc ? currFunc->name : "(unknown)",
+ "function argument", lval->sym->name);
+ }
/* move the rname if any to the name for both val & sym */
/* and leave a copy of it in the symbol table */
if (lval->sym->rname[0])
- {
- char buffer[SDCC_NAME_MAX];
- strncpyz (buffer, lval->sym->rname, sizeof(buffer));
- lval->sym = copySymbol (lval->sym);
- strncpyz (lval->sym->rname, buffer, sizeof(lval->sym->rname));
- strncpyz (lval->sym->name, buffer, sizeof(lval->sym->name));
- strncpyz (lval->name, buffer, sizeof(lval->name));
- addSym (SymbolTab, lval->sym, lval->sym->name,
- lval->sym->level, lval->sym->block, 1);
- lval->sym->_isparm = 1;
- if (!isinSet (operKeyReset, lval->sym)) {
- addSet(&operKeyReset, lval->sym);
- }
- }
+ {
+ char buffer[SDCC_NAME_MAX];
+ strncpyz (buffer, lval->sym->rname, sizeof(buffer));
+ lval->sym = copySymbol (lval->sym);
+ strncpyz (lval->sym->rname, buffer, sizeof(lval->sym->rname));
+ strncpyz (lval->sym->name, buffer, sizeof(lval->sym->name));
+ strncpyz (lval->name, buffer, sizeof(lval->name));
+ addSym (SymbolTab, lval->sym, lval->sym->name,
+ lval->sym->level, lval->sym->block, 1);
+ lval->sym->_isparm = 1;
+ if (!isinSet (operKeyReset, lval->sym)) {
+ addSet(&operKeyReset, lval->sym);
+ }
+ }
}
/*-----------------------------------------------------------------*/
/* allocLocal - allocate local variables */
/*-----------------------------------------------------------------*/
-void
+void
allocLocal (symbol * sym)
{
/* generate an unique name */
- SNPRINTF (sym->rname, sizeof(sym->rname),
- "%s%s_%s_%d_%d",
- port->fun_prefix,
- currFunc->name, sym->name, sym->level, sym->block);
+ SNPRINTF (sym->rname, sizeof(sym->rname),
+ "%s%s_%s_%d_%d",
+ port->fun_prefix,
+ currFunc->name, sym->name, sym->level, sym->block);
sym->islocal = 1;
sym->localof = currFunc;
} else {
SPEC_OCLS (sym->etype) = istack;
if (port->stack.direction > 0) {
- SPEC_STAK (sym->etype) = sym->stack = (stackPtr + 1);
- stackPtr += getSize (sym->type);
+ SPEC_STAK (sym->etype) = sym->stack = (stackPtr + 1);
+ stackPtr += getSize (sym->type);
} else {
- stackPtr -= getSize (sym->type);
- SPEC_STAK (sym->etype) = sym->stack = stackPtr;
+ stackPtr -= getSize (sym->type);
+ SPEC_STAK (sym->etype) = sym->stack = stackPtr;
}
}
allocIntoSeg (sym);
return;
}
-
+
/* else depending on the storage class specified */
if (SPEC_SCLS (sym->etype) == S_XDATA)
{
allocIntoSeg (sym);
return;
}
-
+
if (SPEC_SCLS (sym->etype) == S_IDATA)
{
SPEC_OCLS (sym->etype) = idata;
SPEC_SCLS (sym->etype) == S_SBIT)
{
SPEC_OCLS (sym->etype) =
- (SPEC_SCLS (sym->etype) == S_SFR ? sfr : sfrbit);
+ (SPEC_SCLS (sym->etype) == S_SFR ? sfr : sfrbit);
allocIntoSeg (sym);
return;
}
/* again note that we have put it into the overlay segment
- will remove and put into the 'data' segment if required after
+ will remove and put into the 'data' segment if required after
overlay analysis has been done */
if (options.model == MODEL_SMALL) {
- SPEC_OCLS (sym->etype) =
- (options.noOverlay ? port->mem.default_local_map
- : overlay);
+ SPEC_OCLS (sym->etype) =
+ (options.noOverlay ? port->mem.default_local_map
+ : overlay);
} else {
SPEC_OCLS (sym->etype) = port->mem.default_local_map;
}
/*-----------------------------------------------------------------*/
/* deallocLocal - deallocates the local variables */
/*-----------------------------------------------------------------*/
-void
+void
deallocLocal (symbol * csym)
{
symbol *sym;
for (sym = csym; sym; sym = sym->next)
{
- if (sym->_isparm)
- continue;
+ if (sym->_isparm)
+ continue;
/* if it is on the stack */
if (sym->onStack)
- {
- if (options.useXstack)
- xstackPtr -= getSize (sym->type);
- else
- stackPtr -= getSize (sym->type);
- }
+ {
+ if (options.useXstack)
+ xstackPtr -= getSize (sym->type);
+ else
+ stackPtr -= getSize (sym->type);
+ }
/* if not used give a warning */
if (!sym->isref && !IS_STATIC (sym->etype))
- werror (W_NO_REFERENCE,
- currFunc ? currFunc->name : "(unknown)",
- "local variable", sym->name);
+ werror (W_NO_REFERENCE,
+ currFunc ? currFunc->name : "(unknown)",
+ "local variable", sym->name);
/* now delete it from the symbol table */
deleteSym (SymbolTab, sym, sym->name);
}
/*-----------------------------------------------------------------*/
/* overlay2data - moves declarations from the overlay seg to data */
/*-----------------------------------------------------------------*/
-void
+void
overlay2data ()
{
symbol *sym;
/* overlay2Set - will add all symbols from the overlay segment to */
/* the set of sets containing the overlable symbols */
/*-----------------------------------------------------------------*/
-void
+void
overlay2Set ()
{
symbol *sym;
/*-----------------------------------------------------------------*/
/* allocVariables - creates decl & assign storage class for a v */
/*-----------------------------------------------------------------*/
-int
+int
allocVariables (symbol * symChain)
{
symbol *sym;
/* if this is a typedef then add it */
/* to the typedef table */
if (IS_TYPEDEF (sym->etype))
- {
- /* check if the typedef already exists */
- csym = findSym (TypedefTab, NULL, sym->name);
- if (csym && csym->level == sym->level)
- werror (E_DUPLICATE_TYPEDEF, sym->name);
-
- SPEC_EXTR (sym->etype) = 0;
- addSym (TypedefTab, sym, sym->name, sym->level, sym->block, 0);
- continue; /* go to the next one */
- }
+ {
+ /* check if the typedef already exists */
+ csym = findSym (TypedefTab, NULL, sym->name);
+ if (csym && csym->level == sym->level)
+ werror (E_DUPLICATE_TYPEDEF, sym->name);
+
+ SPEC_EXTR (sym->etype) = 0;
+ addSym (TypedefTab, sym, sym->name, sym->level, sym->block, 0);
+ continue; /* go to the next one */
+ }
/* make sure it already exist */
csym = findSymWithLevel (SymbolTab, sym);
if (!csym || (csym && csym->level != sym->level))
- csym = sym;
+ csym = sym;
/* check the declaration */
checkDecl (csym,0);
/* if this is a extern variable then change the */
/* level to zero temporarily */
if (IS_EXTERN (csym->etype) || IS_FUNC (csym->type))
- {
- saveLevel = csym->level;
- csym->level = 0;
- }
+ {
+ saveLevel = csym->level;
+ csym->level = 0;
+ }
/* if this is a literal then it is an enumerated */
/* type so need not allocate it space for it */
if (IS_LITERAL (sym->etype))
- continue;
+ continue;
/* generate the actual declaration */
if (csym->level)
- {
- allocLocal (csym);
- if (csym->onStack)
- stack += getSize (csym->type);
- }
+ {
+ allocLocal (csym);
+ if (csym->onStack)
+ stack += getSize (csym->type);
+ }
else
- allocGlobal (csym);
+ allocGlobal (csym);
/* restore the level */
if (IS_EXTERN (csym->etype) || IS_FUNC (csym->type))
- csym->level = saveLevel;
+ csym->level = saveLevel;
}
return stack;
/*-----------------------------------------------------------------*/
/* redoStackOffsets :- will reassign the values for stack offsets */
/*-----------------------------------------------------------------*/
-void
+void
redoStackOffsets (void)
{
symbol *sym;
int size = getSize (sym->type);
/* nothing to do with parameters so continue */
if ((sym->_isparm && !IS_REGPARM (sym->etype)))
- continue;
+ continue;
if (IS_AGGREGATE (sym->type))
- {
- if (port->stack.direction > 0)
- {
- SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1);
- sPtr += size;
- }
- else
- {
- sPtr -= size;
- SPEC_STAK (sym->etype) = sym->stack = sPtr;
- }
- continue;
- }
+ {
+ if (port->stack.direction > 0)
+ {
+ SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1);
+ sPtr += size;
+ }
+ else
+ {
+ sPtr -= size;
+ SPEC_STAK (sym->etype) = sym->stack = sPtr;
+ }
+ continue;
+ }
/* if allocation not required then subtract
size from overall stack size & continue */
if (!sym->allocreq)
- {
- currFunc->stack -= size;
- SPEC_STAK (currFunc->etype) -= size;
- continue;
- }
+ {
+ currFunc->stack -= size;
+ SPEC_STAK (currFunc->etype) -= size;
+ continue;
+ }
if (port->stack.direction > 0)
- {
- SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1);
- sPtr += size;
- }
+ {
+ SPEC_STAK (sym->etype) = sym->stack = (sPtr + 1);
+ sPtr += size;
+ }
else
- {
- sPtr -= size;
- SPEC_STAK (sym->etype) = sym->stack = sPtr;
- }
+ {
+ sPtr -= size;
+ SPEC_STAK (sym->etype) = sym->stack = sPtr;
+ }
}
/* do the same for the external stack */
int size = getSize (sym->type);
/* nothing to do with parameters so continue */
if ((sym->_isparm && !IS_REGPARM (sym->etype)))
- continue;
+ continue;
if (IS_AGGREGATE (sym->type))
- {
- SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
- xsPtr += size;
- continue;
- }
+ {
+ SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
+ xsPtr += size;
+ continue;
+ }
/* if allocation not required then subtract
size from overall stack size & continue */
if (!sym->allocreq)
- {
- currFunc->xstack -= size;
- SPEC_STAK (currFunc->etype) -= size;
- continue;
- }
+ {
+ currFunc->xstack -= size;
+ SPEC_STAK (currFunc->etype) -= size;
+ continue;
+ }
SPEC_STAK (sym->etype) = sym->stack = (xsPtr + 1);
xsPtr += size;
/*-----------------------------------------------------------------*/
/* printAllocInfoSeg- print the allocation for a given section */
/*-----------------------------------------------------------------*/
-static void
+static void
printAllocInfoSeg (memmap * map, symbol * func, FILE * of)
{
symbol *sym;
return;
if (!map->syms)
return;
-
+
for (sym = setFirstItem (map->syms); sym;
sym = setNextItem (map->syms))
{
if (sym->level == 0)
- continue;
+ continue;
if (sym->localof != func)
- continue;
-
+ continue;
+
fprintf (of, ";%-25s Allocated ", sym->name);
/* if assigned to registers */
if (!sym->allocreq && sym->reqv)
- {
- int i;
-
- sym = OP_SYMBOL (sym->reqv);
- if (!sym->isspilt || sym->remat)
- {
- fprintf (of, "to registers ");
- for (i = 0; i < 4 && sym->regs[i]; i++)
- fprintf (of, "%s ", port->getRegName (sym->regs[i]));
- fprintf (of, "\n");
- continue;
- }
- else
- {
- sym = sym->usl.spillLoc;
- }
- }
+ {
+ int i;
+
+ sym = OP_SYMBOL (sym->reqv);
+ if (!sym->isspilt || sym->remat)
+ {
+ fprintf (of, "to registers ");
+ for (i = 0; i < 4 && sym->regs[i]; i++)
+ fprintf (of, "%s ", port->getRegName (sym->regs[i]));
+ fprintf (of, "\n");
+ continue;
+ }
+ else
+ {
+ sym = sym->usl.spillLoc;
+ }
+ }
/* if on stack */
if (sym->onStack)
- {
- fprintf (of, "to stack - offset %d\n", sym->stack);
- continue;
- }
+ {
+ fprintf (of, "to stack - offset %d\n", sym->stack);
+ continue;
+ }
/* otherwise give rname */
fprintf (of, "with name '%s'\n", sym->rname);
/*-----------------------------------------------------------------*/
/* canOverlayLocals - returns true if the local variables can overlayed */
/*-----------------------------------------------------------------*/
-static bool
+static bool
canOverlayLocals (eBBlock ** ebbs, int count)
{
int i;
options.stackAuto ||
(currFunc &&
(IFFUNC_ISREENT (currFunc->type) ||
- FUNC_ISISR (currFunc->type))) ||
+ FUNC_ISISR (currFunc->type))) ||
elementsInSet (overlay->syms) == 0)
return FALSE;
iCode *ic;
for (ic = ebbs[i]->sch; ic; ic = ic->next)
- if (ic) {
- if (ic->op == CALL) {
- sym_link *ftype = operandType(IC_LEFT(ic));
- /* builtins only can use overlays */
- if (!IFFUNC_ISBUILTIN(ftype)) return FALSE;
- } else if (ic->op == PCALL) return FALSE;
- }
+ if (ic) {
+ if (ic->op == CALL) {
+ sym_link *ftype = operandType(IC_LEFT(ic));
+ /* builtins only can use overlays */
+ if (!IFFUNC_ISBUILTIN(ftype)) return FALSE;
+ } else if (ic->op == PCALL) return FALSE;
+ }
}
/* no function calls found return TRUE */
/*-----------------------------------------------------------------*/
/* doOverlays - move the overlay segment to appropriate location */
/*-----------------------------------------------------------------*/
-void
+void
doOverlays (eBBlock ** ebbs, int count)
{
if (!overlay) {
/*-----------------------------------------------------------------*/
/* printAllocInfo - prints allocation information for a function */
/*-----------------------------------------------------------------*/
-void
+void
printAllocInfo (symbol * func, FILE * of)
{
if (!func)
- return;
-
+ return;
+
if (!of)
of = stdout;
printAllocInfoSeg (idata, func, of);
printAllocInfoSeg (sfr, func, of);
printAllocInfoSeg (sfrbit, func, of);
-
+
{
set *ovrset;
set *tempOverlaySyms = overlay->syms;
-
+
/* search the set of overlay sets for local variables/parameters */
for (ovrset = setFirstItem (ovrSetSets); ovrset;
ovrset = setNextItem (ovrSetSets))
}
overlay->syms = tempOverlaySyms;
}
-
+
fprintf (of, ";------------------------------------------------------------\n");
}
werror (E_PREV_DEF_CONFLICT, csym->name, "interrupt");
}
- if (FUNC_REGBANK (csym->type) != FUNC_REGBANK (sym->type))
+ /* I don't think this is necessary for interrupts. An isr is a */
+ /* root in the calling tree. */
+ if ((FUNC_REGBANK (csym->type) != FUNC_REGBANK (sym->type)) &&
+ (!FUNC_ISISR (sym->type)))
{
werror (E_PREV_DEF_CONFLICT, csym->name, "using");
}
{
werror (E_PREV_DEF_CONFLICT, csym->name, "_naked");
}
-
+
/* Really, reentrant should match regardless of argCnt, but */
/* this breaks some existing code (the fp lib functions). If */
/* the first argument is always passed the same way, this */
SNPRINTF (val->name, sizeof(val->name),
"_%s_PARM_%d", func->name, pNum++);
val->sym = newSymbol (val->name, 1);
- SPEC_OCLS (val->etype) = port->mem.default_local_map;
+ if (SPEC_SCLS(val->etype) == S_BIT)
+ SPEC_OCLS (val->etype) = bit;
+ else
+ SPEC_OCLS (val->etype) = port->mem.default_local_map;
val->sym->type = copyLinkChain (val->type);
val->sym->etype = getSpec (val->sym->type);
val->sym->_isparm = 1;
SNPRINTF (val->name, sizeof(val->name), "_%s_PARM_%d", func->name, pNum++);
strncpyz (val->sym->rname, val->name, sizeof(val->sym->rname));
val->sym->_isparm = 1;
- SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) =
- (options.model != MODEL_SMALL ? xdata : data);
+ if (SPEC_SCLS(val->etype) == S_BIT)
+ SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) = bit;
+ else
+ SPEC_OCLS (val->etype) = SPEC_OCLS (val->sym->etype) =
+ (options.model != MODEL_SMALL ? xdata : data);
#if 0
/* ?? static functions shouldn't imply static parameters - EEP */
ic->regsSaved = 1;
if (options.useXstack)
{
- if (bitVectBitValue (rsave, R0_IDX))
+ int count = bitVectnBitsOn (rsave);
+
+ if (count == 1)
{
- emitcode ("mov", "a,r0");
- emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
+ i = bitVectFirstBit (rsave);
+ emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
+ emitcode ("mov", "r0,%s", spname);
+ emitcode ("inc", "%s", spname);// allocate before use
+ emitcode ("movx", "@r0,a");
+ if (bitVectBitValue (rsave, R0_IDX))
+ emitcode ("mov", "r0,a");
}
- emitcode ("mov", "r0,%s", spname);
- for (i = 0; i < mcs51_nRegs; i++)
+ else if (count != 0)
{
- if (bitVectBitValue (rsave, i))
+ if (bitVectBitValue (rsave, R0_IDX))
{
- if (i != R0_IDX)
- emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
- emitcode ("movx", "@r0,a");
- emitcode ("inc", "r0");
+ emitcode ("push", "%s", mcs51_regWithIdx (R0_IDX)->dname);
+ }
+ emitcode ("mov", "r0,%s", spname);
+ MOVA ("r0");
+ emitcode ("add", "a,#%d", count);
+ emitcode ("mov", "%s,a", spname);
+ for (i = 0; i < mcs51_nRegs; i++)
+ {
+ if (bitVectBitValue (rsave, i))
+ {
+ if (i == R0_IDX)
+ {
+ emitcode ("pop", "acc");
+ emitcode ("push", "acc");
+ }
+ else
+ {
+ emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
+ }
+ emitcode ("movx", "@r0,a");
+ if (--count)
+ {
+ emitcode ("inc", "r0");
+ }
+ }
+ }
+ if (bitVectBitValue (rsave, R0_IDX))
+ {
+ emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
}
- }
- emitcode ("mov", "%s,r0", spname);
- if (bitVectBitValue (rsave, R0_IDX))
- {
- emitcode ("pop", "%s", mcs51_regWithIdx (R0_IDX)->dname);
}
}
else
if (options.useXstack)
{
- emitcode ("mov", "r0,%s", spname);
- for (i = mcs51_nRegs; i >= 0; i--)
- {
- if (bitVectBitValue (rsave, i))
- {
- emitcode ("dec", "r0");
- emitcode ("movx", "a,@r0");
- if (i != R0_IDX)
- emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
- }
+ int count = bitVectnBitsOn (rsave);
+ if (count == 1)
+ {
+ emitcode ("mov", "r0,%s", spname);
+ emitcode ("dec", "r0");
+ emitcode ("movx", "a,@r0");
+ i = bitVectFirstBit (rsave);
+ emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
+ emitcode ("dec", "%s", spname);
}
- emitcode ("mov", "%s,r0", spname);
- if (bitVectBitValue (rsave, R0_IDX))
+ else
{
- emitcode ("mov", "r0,a");
+ emitcode ("mov", "r0,%s", spname);
+ for (i = mcs51_nRegs; i >= 0; i--)
+ {
+ if (bitVectBitValue (rsave, i))
+ {
+ emitcode ("dec", "r0");
+ emitcode ("movx", "a,@r0");
+ if (i != R0_IDX)
+ emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
+ }
+ }
+ emitcode ("mov", "%s,r0", spname);
+ if (bitVectBitValue (rsave, R0_IDX))
+ {
+ emitcode ("mov", "r0,a");
+ }
}
}
else
if (bitVectBitValue (rsave, i))
emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
}
-
}
aopOp (IC_LEFT (ic), ic, FALSE);
r = getFreePtr (ic, &aop, FALSE);
-
- emitcode ("mov", "%s,_spx", r->name);
-
size = AOP_SIZE (IC_LEFT (ic));
- while (size--)
- {
- char *l = aopGet (AOP (IC_LEFT (ic)),
- offset++, FALSE, FALSE);
- MOVA (l);
+ if (size == 1)
+ {
+ MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
+ emitcode ("mov", "%s,%s", r->name, spname);
+ emitcode ("inc", "%s", spname); // allocate space first
emitcode ("movx", "@%s,a", r->name);
- emitcode ("inc", "%s", r->name);
-
}
+ else
+ {
+ // allocate space first
+ emitcode ("mov", "%s,%s", r->name, spname);
+ MOVA (r->name);
+ emitcode ("add", "a,#%d", size);
+ emitcode ("mov", "%s,a", spname);
-
- emitcode ("mov", "_spx,%s", r->name);
+ while (size--)
+ {
+ MOVA (aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, FALSE));
+ emitcode ("movx", "@%s,a", r->name);
+ emitcode ("inc", "%s", r->name);
+ }
+ }
freeAsmop (NULL, aop, ic, TRUE);
freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
/* then do the push */
aopOp (IC_LEFT (ic), ic, FALSE);
-
// pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
size = AOP_SIZE (IC_LEFT (ic));
}
else
emitcode ("push", "%s", l);
- }
+ }
freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
}
}
/*-----------------------------------------------------------------*/
-/* unsaveRBank - restores the resgister bank from stack */
+/* saveRBank - saves an entire register bank on the stack */
/*-----------------------------------------------------------------*/
static void
-unsaveRBank (int bank, iCode * ic, bool popPsw)
+saveRBank (int bank, iCode * ic, bool pushPsw)
{
int i;
+ int count = mcs51_nRegs + (pushPsw ? 1 : 0);
asmop *aop = NULL;
regs *r = NULL;
if (options.useXstack)
- {
+ {
if (!ic)
{
/* Assume r0 is available for use. */
aop = newAsmop (0);
r = getFreePtr (ic, &aop, FALSE);
}
- emitcode ("mov", "%s,_spx", r->name);
- }
+ // allocate space first
+ emitcode ("mov", "%s,%s", r->name, spname);
+ MOVA (r->name);
+ emitcode ("add", "a,#%d", count);
+ emitcode ("mov", "%s,a", spname);
+ }
- if (popPsw)
+ for (i = 0; i < mcs51_nRegs; i++)
{
if (options.useXstack)
- {
- emitcode ("movx", "a,@%s", r->name);
- emitcode ("mov", "psw,a");
- emitcode ("dec", "%s", r->name);
+ {
+ emitcode ("mov", "a,(%s+%d)",
+ regs8051[i].base, 8 * bank + regs8051[i].offset);
+ emitcode ("movx", "@%s,a", r->name);
+ if (--count)
+ emitcode ("inc", "%s", r->name);
}
else
- {
- emitcode ("pop", "psw");
- }
+ emitcode ("push", "(%s+%d)",
+ regs8051[i].base, 8 * bank + regs8051[i].offset);
}
- for (i = (mcs51_nRegs - 1); i >= 0; i--)
+ if (pushPsw)
{
if (options.useXstack)
{
- emitcode ("movx", "a,@%s", r->name);
- emitcode ("mov", "(%s+%d),a",
- regs8051[i].base, 8 * bank + regs8051[i].offset);
- emitcode ("dec", "%s", r->name);
+ emitcode ("mov", "a,psw");
+ emitcode ("movx", "@%s,a", r->name);
}
else
- emitcode ("pop", "(%s+%d)",
- regs8051[i].base, 8 * bank + regs8051[i].offset);
+ {
+ emitcode ("push", "psw");
+ }
+
+ emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
}
- if (options.useXstack)
+ if (aop)
{
- emitcode ("mov", "_spx,%s", r->name);
+ freeAsmop (NULL, aop, ic, TRUE);
}
- if (aop)
+ if (ic)
{
- freeAsmop (NULL, aop, ic, TRUE);
+ ic->bankSaved = 1;
}
}
/*-----------------------------------------------------------------*/
-/* saveRBank - saves an entire register bank on the stack */
+/* unsaveRBank - restores the register bank from stack */
/*-----------------------------------------------------------------*/
static void
-saveRBank (int bank, iCode * ic, bool pushPsw)
+unsaveRBank (int bank, iCode * ic, bool popPsw)
{
int i;
asmop *aop = NULL;
if (options.useXstack)
{
if (!ic)
- {
+ {
/* Assume r0 is available for use. */
r = mcs51_regWithIdx (R0_IDX);;
- }
+ }
else
- {
+ {
aop = newAsmop (0);
r = getFreePtr (ic, &aop, FALSE);
- }
- emitcode ("mov", "%s,_spx", r->name);
+ }
+ emitcode ("mov", "%s,%s", r->name, spname);
}
- for (i = 0; i < mcs51_nRegs; i++)
+ if (popPsw)
{
if (options.useXstack)
{
- emitcode ("inc", "%s", r->name);
- emitcode ("mov", "a,(%s+%d)",
- regs8051[i].base, 8 * bank + regs8051[i].offset);
- emitcode ("movx", "@%s,a", r->name);
+ emitcode ("dec", "%s", r->name);
+ emitcode ("movx", "a,@%s", r->name);
+ emitcode ("mov", "psw,a");
}
else
- emitcode ("push", "(%s+%d)",
- regs8051[i].base, 8 * bank + regs8051[i].offset);
+ {
+ emitcode ("pop", "psw");
+ }
}
- if (pushPsw)
+ for (i = (mcs51_nRegs - 1); i >= 0; i--)
{
if (options.useXstack)
{
- emitcode ("mov", "a,psw");
- emitcode ("movx", "@%s,a", r->name);
- emitcode ("inc", "%s", r->name);
- emitcode ("mov", "_spx,%s", r->name);
-
+ emitcode ("dec", "%s", r->name);
+ emitcode ("movx", "a,@%s", r->name);
+ emitcode ("mov", "(%s+%d),a",
+ regs8051[i].base, 8 * bank + regs8051[i].offset);
}
else
- {
- emitcode ("push", "psw");
- }
+ {
+ emitcode ("pop", "(%s+%d)",
+ regs8051[i].base, 8 * bank + regs8051[i].offset);
+ }
+ }
- emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
+ if (options.useXstack)
+ {
+ emitcode ("mov", "%s,%s", spname, r->name);
}
if (aop)
{
freeAsmop (NULL, aop, ic, TRUE);
}
-
- if (ic)
- {
- ic->bankSaved = 1;
- }
}
/*-----------------------------------------------------------------*/
static void
genFunction (iCode * ic)
{
- symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+ symbol *sym = OP_SYMBOL (IC_LEFT (ic));
sym_link *ftype;
- bool switchedPSW = FALSE;
- int calleesaves_saved_register = -1;
- int stackAdjust = sym->stack;
- int accIsFree = sym->recvSize < 4;
- iCode * ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
+ bool switchedPSW = FALSE;
+ int calleesaves_saved_register = -1;
+ int stackAdjust = sym->stack;
+ int accIsFree = sym->recvSize < 4;
+ iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
+ bool fReentrant = (IFFUNC_ISREENT (sym->type) || options.stackAuto);
_G.nRegsSaved = 0;
/* create the function header */
}
- if (reentrant)
+ if (fReentrant)
{
if (options.useXstack)
{
- emitcode ("inc", "%s", spname);
- emitcode ("mov", "r0,%s", spname);
- emitcode ("xch", "a,_bp");
- emitcode ("movx", "@r0,a");
- emitcode ("mov", "a,r0");
- emitcode ("xch", "a,_bp");
+ emitcode ("mov", "r0,%s", spname);
+ emitcode ("inc", "%s", spname);
+ emitcode ("xch", "a,_bp");
+ emitcode ("movx", "@r0,a");
+ emitcode ("inc", "r0");
+ emitcode ("mov", "a,r0");
+ emitcode ("xch", "a,_bp");
}
else
{
if (i > 3 && accIsFree)
{
-
emitcode ("mov", "a,sp");
emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
emitcode ("mov", "sp,a");
-
}
else if (i > 5)
{
if (sym->xstack)
{
+ char i = ((char) sym->xstack & 0xff);
- if (!accIsFree)
- emitcode ("push", "acc");
- emitcode ("mov", "a,_spx");
- emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
- emitcode ("mov", "_spx,a");
- if (!accIsFree)
- emitcode ("pop", "acc");
+ if (i > 3 && accIsFree)
+ {
+ emitcode ("mov", "a,_spx");
+ emitcode ("add", "a,#0x%02x", i);
+ emitcode ("mov", "_spx,a");
+ }
+ else if (i > 5)
+ {
+ emitcode ("push", "acc");
+ emitcode ("mov", "a,_spx");
+ emitcode ("add", "a,#0x%02x", i);
+ emitcode ("mov", "_spx,a");
+ emitcode ("pop", "acc");
+ }
+ else
+ {
+ while (i--)
+ emitcode ("inc", "_spx");
+ }
}
/* if critical function then turn interrupts off */
emitcode ("mov", "ea,c");
}
- if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
+ if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) && !options.useXstack)
{
emitcode ("mov", "%s,_bp", spname);
}
local stack */
if (options.useXstack && sym->stack)
{
- if (!accIsFree)
- emitcode ("push", "acc");
- emitcode ("mov", "a,sp");
- emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
- emitcode ("mov", "sp,a");
- if (!accIsFree)
- emitcode ("pop", "acc");
+ char count = sym->stack;
+
+ if ((count>3) && accIsFree)
+ {
+ emitcode ("mov", "a,sp");
+ emitcode ("add", "a,#0x%02x", ((char) -count) & 0xff);
+ emitcode ("mov", "sp,a");
+ }
+ else
+ {
+ while (count--)
+ emitcode ("dec", "sp");
+ }
}
if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
if (options.useXstack)
{
emitcode ("xch", "a,_bp");
- emitcode ("mov", "r0,%s", spname);
+ emitcode ("mov", "r0,a");
+ emitcode ("dec", "r0");
emitcode ("movx", "a,@r0");
emitcode ("xch", "a,_bp");
- emitcode ("dec", "%s", spname); //read before freeing stack space (interrupts)
+ emitcode ("mov", "%s,r0", spname); //read before freeing stack space (interrupts)
}
else
{
!IS_FLOAT (operandType (right)) &&
(lit < 256L))
{
+ while ((size) && (lit))
+ {
+ aopPut (AOP (result),
+ aopGet (AOP (right), offset, FALSE, FALSE),
+ offset,
+ isOperandVolatile (result, FALSE));
+ lit >>= 8;
+ offset++;
+ size--;
+ }
emitcode ("clr", "a");
while (size--)
{
- if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
- aopPut (AOP (result), "a", size, isOperandVolatile (result, FALSE));
- else
- aopPut (AOP (result),
- aopGet (AOP (right), size, FALSE, FALSE),
- size,
- isOperandVolatile (result, FALSE));
+ aopPut (AOP (result), "a", offset, isOperandVolatile (result, FALSE));
+ offset++;
}
}
else
void mcs51_assignRegisters (eBBlock ** ebbs, int count);
-static int regParmFlg = 0; /* determine if we can register a parameter */
+static int regParmFlg = 0; /* determine if we can register a parameter */
static void
_mcs51_init (void)
static int
_mcs51_regparm (sym_link * l)
{
+ if (IS_SPEC(l) && (SPEC_NOUN(l) == V_BIT))
+ return 0;
if (options.parms_in_bank1 == 0) {
- /* simple can pass only the first parameter in a register */
- if (regParmFlg)
- return 0;
+ /* simple can pass only the first parameter in a register */
+ if (regParmFlg)
+ return 0;
- regParmFlg = 1;
- return 1;
+ regParmFlg = 1;
+ return 1;
} else {
- int size = getSize(l);
- int remain ;
-
- /* first one goes the usual way to DPTR */
- if (regParmFlg == 0) {
- regParmFlg += 4 ;
- return 1;
- }
- /* second one onwards goes to RB1_0 thru RB1_7 */
+ int size = getSize(l);
+ int remain ;
+
+ /* first one goes the usual way to DPTR */
+ if (regParmFlg == 0) {
+ regParmFlg += 4 ;
+ return 1;
+ }
+ /* second one onwards goes to RB1_0 thru RB1_7 */
remain = regParmFlg - 4;
- if (size > (8 - remain)) {
- regParmFlg = 12 ;
- return 0;
- }
- regParmFlg += size ;
- return regParmFlg - size + 1;
+ if (size > (8 - remain)) {
+ regParmFlg = 12 ;
+ return 0;
+ }
+ regParmFlg += size ;
+ return regParmFlg - size + 1;
}
}
_mcs51_genAssemblerPreamble (FILE * of)
{
if (options.parms_in_bank1) {
- int i ;
- for (i=0; i < 8 ; i++ )
- fprintf (of,"b1_%d = 0x%x \n",i,8+i);
+ int i ;
+ for (i=0; i < 8 ; i++ )
+ fprintf (of,"b1_%d = 0x%x \n",i,8+i);
}
-
}
/* Generate interrupt vector table. */
return TRUE;
}
-static void
+static void
_mcs51_genExtraAreas(FILE *of, bool hasMain)
{
tfprintf (of, "\t!area\n", port->mem.code_name);
tfprintf (of, "\t!global\n", "__sdcc_gsinit_startup");
tfprintf (of, "\t!global\n", "__sdcc_program_startup");
tfprintf (of, "\t!global\n", "__start__stack");
-
+
if (options.useXstack)
{
tfprintf (of, "\t!global\n", "__sdcc_init_xstack");
{
port->genXINIT(of);
}
-
+
if (!getenv("SDCC_NOGENRAMCLEAR"))
tfprintf (of, "\t!global\n", "__mcs51_genRAMCLEAR");
}
/* Generate code to copy XINIT to XISEG */
static void _mcs51_genXINIT (FILE * of) {
tfprintf (of, "\t!global\n", "__mcs51_genXINIT");
-
+
if (!getenv("SDCC_NOGENRAMCLEAR"))
tfprintf (of, "\t!global\n", "__mcs51_genXRAMCLEAR");
}
/* if it is a pointer then return ok for now */
if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
-
- /* if bitwise | add & subtract then no since mcs51 is pretty good at it
+
+ /* if bitwise | add & subtract then no since mcs51 is pretty good at it
so we will cse only if they are local (i.e. both ic & pdic belong to
the same basic block */
if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
- /* then if they are the same Basic block then ok */
- if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
- else return 0;
+ /* then if they are the same Basic block then ok */
+ if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
+ else return 0;
}
-
+
/* for others it is cheaper to do the cse */
return 1;
}
{
if (IN_FARSPACE(oclass))
return 1;
-
+
return 0;
}
/* Based on the current (2003-08-22) code generation for the
small library, the top instruction probability is:
-
+
57% mov/movx/movc
6% push
6% pop
if (*(inst+3)=='c') return 1; /* movc */
if (IS_C (op1) || IS_C (op2)) return 2;
if (IS_A (op1))
- {
- if (IS_Rn (op2) || IS_atRi (op2)) return 1;
- return 2;
- }
+ {
+ if (IS_Rn (op2) || IS_atRi (op2)) return 1;
+ return 2;
+ }
if (IS_Rn(op1) || IS_atRi(op1))
- {
- if (IS_A(op2)) return 1;
- return 2;
- }
+ {
+ if (IS_A(op2)) return 1;
+ return 2;
+ }
if (strcmp (op1, "dptr") == 0) return 3;
if (IS_A (op2) || IS_Rn (op2) || IS_atRi (op2)) return 2;
return 3;
}
-
+
if (ISINST ("push")) return 2;
if (ISINST ("pop")) return 2;
if (ISINST ("jb")) return 3;
if (ISINST ("jnb")) return 3;
if (ISINST ("jbc")) return 3;
- if (ISINST ("jmp")) return 1; // always jmp @a+dptr
+ if (ISINST ("jmp")) return 1; // always jmp @a+dptr
if (ISINST ("jz")) return 2;
if (ISINST ("jnz")) return 2;
if (ISINST ("cjne")) return 3;
if (ISINST ("acall")) return 2;
if (ISINST ("ajmp")) return 2;
-
+
if (ISINST ("add") || ISINST ("addc") || ISINST ("subb") || ISINST ("xch"))
{
if (IS_Rn(op2) || IS_atRi(op2)) return 1;
{
if (IS_C(op1)) return 2;
if (IS_A(op1))
- {
- if (IS_Rn(op2) || IS_atRi(op2)) return 1;
- return 2;
- }
+ {
+ if (IS_Rn(op2) || IS_atRi(op2)) return 1;
+ return 2;
+ }
else
- {
- if (IS_A(op2)) return 2;
- return 3;
- }
+ {
+ if (IS_A(op2)) return 2;
+ return 3;
+ }
}
if (ISINST ("clr") || ISINST ("setb") || ISINST ("cpl"))
{
aln->size = 0;
aln->regsRead = NULL;
aln->regsWritten = NULL;
-
+
return aln;
}
return strcmp((const char *)key, ((mcs51operanddata *)member)->name);
}
-static void
+static void
updateOpRW (asmLineNode *aln, char *op, char *optype)
{
mcs51operanddata *opdat;
char *dot;
-
+
dot = strchr(op, '.');
if (dot)
*dot = '\0';
opdat = bsearch (op, mcs51operandDataTable,
- sizeof(mcs51operandDataTable)/sizeof(mcs51operanddata),
- sizeof(mcs51operanddata), mcs51operandCompare);
-
+ sizeof(mcs51operandDataTable)/sizeof(mcs51operanddata),
+ sizeof(mcs51operanddata), mcs51operandCompare);
+
if (opdat && strchr(optype,'r'))
{
if (opdat->regIdx1 >= 0)
if (!strcmp(op, "@r1"))
aln->regsRead = bitVectSetBit (aln->regsRead, R1_IDX);
if (strstr(op, "dptr"))
- {
- aln->regsRead = bitVectSetBit (aln->regsRead, DPL_IDX);
- aln->regsRead = bitVectSetBit (aln->regsRead, DPH_IDX);
- }
+ {
+ aln->regsRead = bitVectSetBit (aln->regsRead, DPL_IDX);
+ aln->regsRead = bitVectSetBit (aln->regsRead, DPH_IDX);
+ }
if (strstr(op, "a+"))
- aln->regsRead = bitVectSetBit (aln->regsRead, A_IDX);
+ aln->regsRead = bitVectSetBit (aln->regsRead, A_IDX);
}
}
{"xchd", "", "", "rw", "rw"},
{"xrl", "", "", "rw", "r"},
};
-
+
static int
mcs51opcodeCompare (const void *key, const void *member)
{
mcs51opcodedata *opdat;
p = ln->line;
-
+
while (*p && isspace(*p)) p++;
for (op = inst, opsize=1; *p; p++)
{
break;
else
if (opsize < sizeof(inst))
- *op++ = tolower(*p), opsize++;
+ *op++ = tolower(*p), opsize++;
}
*op = '\0';
if (*p == ';' || *p == ':' || *p == '=')
return aln;
-
+
while (*p && isspace(*p)) p++;
if (*p == '=')
return aln;
*op++ = tolower(*p), opsize++;
}
*op = '\0';
-
+
if (*p == ',') p++;
for (op = op2, opsize=1; *p && *p != ','; p++)
{
aln->regsWritten = newBitVect (END_IDX);
opdat = bsearch (inst, mcs51opcodeDataTable,
- sizeof(mcs51opcodeDataTable)/sizeof(mcs51opcodedata),
- sizeof(mcs51opcodedata), mcs51opcodeCompare);
+ sizeof(mcs51opcodeDataTable)/sizeof(mcs51opcodedata),
+ sizeof(mcs51opcodedata), mcs51opcodeCompare);
if (opdat)
{
{
if (!line->aln)
line->aln = asmLineNodeFromLineNode (line);
-
+
return line->aln->size;
}
{
if (!line->aln)
line->aln = asmLineNodeFromLineNode (line);
-
+
return line->aln->regsRead;
}
{
if (!line->aln)
line->aln = asmLineNodeFromLineNode (line);
-
+
return line->aln->regsWritten;
}
{
TARGET_ID_MCS51,
"mcs51",
- "MCU 8051", /* Target name */
- NULL, /* Processor name */
+ "MCU 8051", /* Target name */
+ NULL, /* Processor name */
{
glue,
- TRUE, /* Emit glue around main */
+ TRUE, /* Emit glue around main */
MODEL_SMALL | MODEL_LARGE,
MODEL_SMALL
},
{
_asmCmd,
NULL,
- "-plosgffc", /* Options with debug */
- "-plosgff", /* Options without debug */
+ "-plosgffc", /* Options with debug */
+ "-plosgff", /* Options without debug */
0,
".asm",
- NULL /* no do_assemble function */
+ NULL /* no do_assemble function */
},
{
_linkCmd,
getRegsWritten
},
{
- /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
+ /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
1, 2, 2, 4, 1, 2, 3, 1, 4, 4
},
{
_mcs51_getRegName,
_mcs51_keywords,
_mcs51_genAssemblerPreamble,
- NULL, /* no genAssemblerEnd */
+ NULL, /* no genAssemblerEnd */
_mcs51_genIVT,
_mcs51_genXINIT,
_mcs51_genInitStartup,
NULL,
NULL,
NULL,
- hasExtBitOp, /* hasExtBitOp */
- oclsExpense, /* oclsExpense */
+ hasExtBitOp, /* hasExtBitOp */
+ oclsExpense, /* oclsExpense */
FALSE,
- TRUE, /* little endian */
- 0, /* leave lt */
- 0, /* leave gt */
- 1, /* transform <= to ! > */
- 1, /* transform >= to ! < */
- 1, /* transform != to !(a == b) */
- 0, /* leave == */
+ TRUE, /* little endian */
+ 0, /* leave lt */
+ 0, /* leave gt */
+ 1, /* transform <= to ! > */
+ 1, /* transform >= to ! < */
+ 1, /* transform != to !(a == b) */
+ 0, /* leave == */
FALSE, /* No array initializer support. */
cseCostEstimation,
- NULL, /* no builtin functions */
- GPOINTER, /* treat unqualified pointers as "generic" pointers */
- 1, /* reset labelKey to 1 */
- 1, /* globals & local static allowed */
+ NULL, /* no builtin functions */
+ GPOINTER, /* treat unqualified pointers as "generic" pointers */
+ 1, /* reset labelKey to 1 */
+ 1, /* globals & local static allowed */
PORT_MAGIC
};
regs regs8051[] =
{
- {REG_GPR, R2_IDX, REG_GPR, "r2", "ar2", "0", 2, 1},
- {REG_GPR, R3_IDX, REG_GPR, "r3", "ar3", "0", 3, 1},
- {REG_GPR, R4_IDX, REG_GPR, "r4", "ar4", "0", 4, 1},
- {REG_GPR, R5_IDX, REG_GPR, "r5", "ar5", "0", 5, 1},
- {REG_GPR, R6_IDX, REG_GPR, "r6", "ar6", "0", 6, 1},
- {REG_GPR, R7_IDX, REG_GPR, "r7", "ar7", "0", 7, 1},
- {REG_PTR, R0_IDX, REG_PTR, "r0", "ar0", "0", 0, 1},
- {REG_PTR, R1_IDX, REG_PTR, "r1", "ar1", "0", 1, 1},
- {REG_GPR, X8_IDX, REG_GPR, "x8", "x8", "xreg", 0, 1},
- {REG_GPR, X9_IDX, REG_GPR, "x9", "x9", "xreg", 1, 1},
+ {REG_GPR, R2_IDX, REG_GPR, "r2", "ar2", "0", 2, 1},
+ {REG_GPR, R3_IDX, REG_GPR, "r3", "ar3", "0", 3, 1},
+ {REG_GPR, R4_IDX, REG_GPR, "r4", "ar4", "0", 4, 1},
+ {REG_GPR, R5_IDX, REG_GPR, "r5", "ar5", "0", 5, 1},
+ {REG_GPR, R6_IDX, REG_GPR, "r6", "ar6", "0", 6, 1},
+ {REG_GPR, R7_IDX, REG_GPR, "r7", "ar7", "0", 7, 1},
+ {REG_PTR, R0_IDX, REG_PTR, "r0", "ar0", "0", 0, 1},
+ {REG_PTR, R1_IDX, REG_PTR, "r1", "ar1", "0", 1, 1},
+ {REG_GPR, X8_IDX, REG_GPR, "x8", "x8", "xreg", 0, 1},
+ {REG_GPR, X9_IDX, REG_GPR, "x9", "x9", "xreg", 1, 1},
{REG_GPR, X10_IDX, REG_GPR, "x10", "x10", "xreg", 2, 1},
{REG_GPR, X11_IDX, REG_GPR, "x11", "x11", "xreg", 3, 1},
{REG_GPR, X12_IDX, REG_GPR, "x12", "x12", "xreg", 4, 1},
- {REG_CND, CND_IDX, REG_CND, "C", "psw", "0xd0", 0, 1},
- {0, DPL_IDX, 0, "dpl", "dpl", "0x82", 0, 0},
- {0, DPH_IDX, 0, "dph", "dph", "0x83", 0, 0},
- {0, B_IDX, 0, "b", "b", "0xf0", 0, 0},
- {0, A_IDX, 0, "a", "acc", "0xe0", 0, 0},
+ {REG_CND, CND_IDX, REG_CND, "C", "psw", "0xd0", 0, 1},
+ {0, DPL_IDX, 0, "dpl", "dpl", "0x82", 0, 0},
+ {0, DPH_IDX, 0, "dph", "dph", "0x83", 0, 0},
+ {0, B_IDX, 0, "b", "b", "0xf0", 0, 0},
+ {0, A_IDX, 0, "a", "acc", "0xe0", 0, 0},
};
int mcs51_nRegs = 17;
static void spillThis (symbol *);
/* set the type to the spilling symbol */
sloc->type = copyLinkChain (sym->type);
sloc->etype = getSpec (sloc->type);
- SPEC_SCLS (sloc->etype) = S_DATA;
+ if (SPEC_SCLS (sloc->etype) != S_BIT)
+ {
+ SPEC_SCLS (sloc->etype) = S_DATA;
+ }
SPEC_EXTR (sloc->etype) = 0;
SPEC_STAT (sloc->etype) = 0;
SPEC_VOLATILE(sloc->etype) = 0;
ebbs[i]->entryLabel != returnLabel))
continue;
- /* of all instructions do */
+ /* for all instructions do */
for (ic = ebbs[i]->sch; ic; ic = ic->next)
{
#if 1
spillThis (sym);
continue;
}
+
+ /* if this is a bit variable then don't use precious registers
+ along with expensive bit-to-char conversions but just spill
+ it */
+ if (SPEC_NOUN(sym->etype) == V_BIT) {
+ spillThis (sym);
+ continue;
+ }
+
/* if trying to allocate this will cause
a spill and there is nothing to spill
or this one is rematerializable then
for (j = 0; j < sym->nRegs; j++)
{
if (sym->regs[j]) /* EEP - debug */
- rumask = bitVectSetBit (rumask,
- sym->regs[j]->rIdx);
+ rumask = bitVectSetBit (rumask, sym->regs[j]->rIdx);
}
return rumask;
}
/*-----------------------------------------------------------------*/
-/* packForPush - hueristics to reduce iCode for pushing */
+/* packForPush - heuristics to reduce iCode for pushing */
/*-----------------------------------------------------------------*/
static void
packForPush (iCode * ic, eBBlock ** ebpp, int blockno)
# These ports will be cleaned with 'make clean'
CLEAN_PORTS = $(filter-out CVS,$(notdir $(wildcard $(PORTS_DIR)/*)))
+MAKE_LIBRARY =
+
all: test-ports
# Test all of the ports
test-ports:
- for i in $(ALL_PORTS); do $(MAKE) test-port PORT=$$i; done
+ for i in $(ALL_PORTS); do $(MAKE) make_library test-port PORT=$$i; done
# Helper rule for testing the z80 port only
test-z80:
$(MAKE) test-port PORT=mcs51-large
test-mcs51-stack-auto:
- $(MAKE) make-library test-port PORT=mcs51-stack-auto
+ $(MAKE) make_library test-port PORT=mcs51-stack-auto
+
+test-mcs51-xstack-auto:
+ $(MAKE) make_library test-port PORT=mcs51-xstack-auto
# Helper rule for testing the ds390 port only
test-ds390:
include $(PORTS_DIR)/$(PORT)/spec.mk
endif
+make_library: $(MAKE_LIBRARY)
+
SDCCFLAGS += -Ifwk/include -Itests -I$(INC_DIR)
# List of intermediate files to keep. Pretty much keep everything as
#define _REENTRANT reentrant
#endif
+#if defined(SDCC_mcs51)
+/* until changed, isr's must have a prototype in the module containing main */
+void T2_isr (void) interrupt 5;
+#endif
+
/** Define this if the port's div or mod functions are broken.
A slow loop based method will be substituded.
*/
int __numTests;
int __numFailures;
-void
+void
__fail(const char *szMsg, const char *szCond, const char *szFile, int line)
{
__printf("--- FAIL: \"%s\" on %s at %s:%u\n", szMsg, szCond, szFile, line);
__numFailures++;
}
-int
+int
main(void)
{
TESTFUNP *cases;
cases++;
numCases++;
}
-
- __printf("--- Summary: %u/%u/%u: %u failed of %u tests in %u cases.\n",
+
+ __printf("--- Summary: %u/%u/%u: %u failed of %u tests in %u cases.\n",
__numFailures, __numTests, numCases,
__numFailures, __numTests, numCases
);
OBJECTS = $(patsubst %.c,$(LIBDIR)/%.rel,$(SOURCES))
MODULES = $(patsubst %.c,%,$(SOURCES))
-.PHONY: make-library
-make-library: $(LIBDIR) $(OBJECTS) lib-files
-
+MAKE_LIBRARY = $(LIBDIR) $(OBJECTS) lib-files
$(LIBDIR):
mkdir -p $(LIBDIR)
--- /dev/null
+# Port specification for the mcs51 port running with uCsim
+#
+# model small stack-auto
+
+include $(PORTS_DIR)/mcs51-stack-auto/spec.mk
+
+LIBSDCCFLAGS+= --xstack
+SDCCFLAGS +=$(LIBSDCCFLAGS)
--- /dev/null
+//dummy interrupt service routine
+//just to make linker happy
+
+void T2_isr (void) interrupt 5
+{
+}
--- /dev/null
+T2_isr.rel
EXEEXT = .ihx
EXTRAS = $(PORTS_DIR)/$(PORT)/testfwk$(OBJEXT) $(PORTS_DIR)/$(PORT)/support$(OBJEXT)
+FWKLIB = $(PORTS_DIR)/$(PORT)/T2_isr$(OBJEXT)
# Rule to link into .ihx
-%$(EXEEXT): %$(OBJEXT) $(EXTRAS)
- $(SDCC) $(SDCCFLAGS) $(LINKFLAGS) -L $(LIBDIR) $(EXTRAS) $< -o $@
+%$(EXEEXT): %$(OBJEXT) $(EXTRAS) $(FWKLIB) $(PORTS_DIR)/$(PORT)/fwk.lib
+ $(SDCC) $(SDCCFLAGS) $(LINKFLAGS) -L $(LIBDIR) $(EXTRAS) $(PORTS_DIR)/$(PORT)/fwk.lib $< -o $@
%$(OBJEXT): %.c
$(SDCC) $(SDCCFLAGS) -c $< -o $@
$(PORTS_DIR)/$(PORT)/testfwk$(OBJEXT): fwk/lib/testfwk.c
$(SDCC) $(SDCCFLAGS) -c $< -o $@
+$(PORTS_DIR)/$(PORT)/fwk.lib:
+ cp $(PORTS_DIR)/mcs51/fwk.lib $(PORTS_DIR)/$(PORT)/fwk.lib
+
# run simulator with 30 seconds timeout
%.out: %$(EXEEXT) fwk/lib/timeout
mkdir -p `dirname $@`
--- /dev/null
+/** Bit vars test.
+
+*/
+#include <testfwk.h>
+
+#if defined (SDCC_STACK_AUTO) || defined (SDCC_hc08) || defined (SDCC_z80) || defined (PORT_HOST)
+#define NO_BITS
+#endif
+
+#ifndef NO_BITS
+char foo(bit a, bit b, char c)
+{
+ return a + b + c;
+}
+#endif
+
+void
+testBits(void)
+{
+#ifndef NO_BITS
+ bit x = 2;
+ ASSERT (foo(x,3,4) == 6);
+#endif
+}
--- /dev/null
+/* Keyword "critical" tests.
+ */
+#include <testfwk.h>
+
+#if defined(SDCC_mcs51)
+#include <8052.h>
+
+typedef union
+{
+ unsigned int a;
+ struct
+ {
+ unsigned char b;
+ unsigned char c;
+ };
+} big;
+
+//must be at least 2 bytes big and volatile
+volatile big global_var = { 0 };
+
+unsigned int get_global (void) critical
+{
+ return global_var.a;
+}
+#endif
+
+void
+testCritical(void)
+{
+#if defined(SDCC_mcs51)
+ big x;
+ unsigned char i;
+
+ //enable the interrupt and set it
+ ET2 = 1;
+ EA = 1;
+ TF2 = 1;
+
+ critical x.a = global_var.a;
+ ASSERT(x.b == x.c);
+
+ x.a = get_global();
+ ASSERT(x.b == x.c);
+
+ for (i=10; i!=0; i--)
+ {
+ critical x.a = global_var.a;
+ ASSERT(x.b == x.c);
+
+ x.a = get_global();
+ ASSERT(x.b == x.c);
+ }
+ //check the interrupt has run at all
+ ASSERT(x.a != 0);
+#else
+ ASSERT(1);
+#endif
+}
+
+#if defined(SDCC_mcs51)
+void T2_isr (void) interrupt 5 using 2
+{
+ //do not clear flag ET2 so it keeps interrupting !
+ global_var.b++;
+ if (global_var.b == 0)
+ global_var.b++;
+ global_var.c = global_var.b;
+}
+#endif