From 9d473d57f7c6cc242274d523f950f8bb873ec1fb Mon Sep 17 00:00:00 2001 From: tecodev Date: Mon, 22 Jan 2007 01:18:52 +0000 Subject: [PATCH] * src/regression/bank1.c, src/regression/compare6.c, src/regression/add.c: cosmetic changes * src/pic/pcode.h: moved GPTRTAG_* here from gen.c * src/pic/gen.c: fixed global zero and one, (aopForSym): removed unued code, (aopGet): assert aop is defined, check and use `index' of pCodeImmd operands (fixes #1630908), * src/pic/pcode.c (get_op): added output of generic pointer tag, (register_reassign): prevent accidental register unification, (ReuseReg): cosmetic changes (also above) * src/pic/glue.c (pic14_constructAbsMap,pic14emitRegularMap, pic14emitStaticSeg): do not emit initialized data, (printIval*): replaced with working versions, (pic14createInterruptVect,picglue): use idata for initialized data, now init data should work in all modules (not only main()), * device/lib/pic/libsdcc/idata.c: NEW, handle initialized data git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@4593 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 19 ++ device/lib/pic/libsdcc/idata.c | 80 +++++ src/pic/gen.c | 91 +----- src/pic/glue.c | 542 +++++++++++++++++++++++++++++++-- src/pic/pcode.c | 122 +++++--- src/pic/pcode.h | 5 + src/regression/add.c | 8 +- src/regression/bank1.c | 6 +- src/regression/compare6.c | 13 +- 9 files changed, 713 insertions(+), 173 deletions(-) create mode 100644 device/lib/pic/libsdcc/idata.c diff --git a/ChangeLog b/ChangeLog index 45c83817..ac8f64a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,22 @@ +2007-01-22 Raphael Neider + + * src/regression/bank1.c, src/regression/compare6.c, + src/regression/add.c: cosmetic changes + * src/pic/pcode.h: moved GPTRTAG_* here from gen.c + * src/pic/gen.c: fixed global zero and one, + (aopForSym): removed unued code, + (aopGet): assert aop is defined, check and use `index' of + pCodeImmd operands (fixes #1630908), + * src/pic/pcode.c (get_op): added output of generic pointer tag, + (register_reassign): prevent accidental register unification, + (ReuseReg): cosmetic changes (also above) + * src/pic/glue.c (pic14_constructAbsMap,pic14emitRegularMap, + pic14emitStaticSeg): do not emit initialized data, + (printIval*): replaced with working versions, + (pic14createInterruptVect,picglue): use idata for initialized data, + now init data should work in all modules (not only main()), + * device/lib/pic/libsdcc/idata.c: NEW, handle initialized data + 2007-01-21 Borut Razem * sim/ucsim/configure.in: introduced macro DD_COPT_NO_IGNORE, diff --git a/device/lib/pic/libsdcc/idata.c b/device/lib/pic/libsdcc/idata.c new file mode 100644 index 00000000..a73f29d9 --- /dev/null +++ b/device/lib/pic/libsdcc/idata.c @@ -0,0 +1,80 @@ +/* + * idata.c - startup code evaluating gputils' cinit structure + * + * This code fragment copies initialized data from ROM to their + * assigned RAM locations. The requierd cinit structure is created + * by gputils' linker and comprises initial values of all linked in + * modules. + * + * (c) 2007 by Raphael Neider + * + * This file is part of SDCC's pic14 library and distributed under + * the terms of the GPLv2 with linking exception; see COPYING in some + * parent directory for details. + */ + +/* + * We call the user's main() after initialization is done. + */ +extern void main(void); + +/* + * Force generation of _cinit symbol. + */ +static char force_cinit = 0; + +/* + * This struct describes one initialized variable. + */ +typedef struct { + unsigned src; // source address of data in CODE space + unsigned dst; // destination address of values in DATA space + unsigned size; // number of bytes to copy from `src' to `dst' +} cinit_t; + +/* + * This structure provides the number and position of the above + * structs. to initialize all variables in the .hex file. + */ +extern __code struct { + unsigned records; // number of entries in this file + cinit_t entry[]; // intialization descriptor +} cinit; + +/* + * Iterate over all records and copy values from ROM to RAM. + */ +void +_sdcc_gsinit_startup(void) +{ + unsigned num, size; + __code cinit_t *cptr; + __code char *src; + __data char *dst; + + num = cinit.records; + cptr = &cinit.entry[0]; + + // iterate over all cinit entries + while (num--) { + size = cptr->size; + src = (__code char *) cptr->src; + dst = (__data char *) cptr->dst; + + // copy data byte-wise from ROM to RAM + while (size--) { + *dst = *src; + src++; + dst++; + } // while + + // XXX: might need to clear the watchdog timer here... + cptr++; + } // while + + // call main after initialization + __asm + GOTO _main + __endasm; +} + diff --git a/src/pic/gen.c b/src/pic/gen.c index baa457df..7cf251c4 100644 --- a/src/pic/gen.c +++ b/src/pic/gen.c @@ -44,11 +44,6 @@ #include "gen.h" #include "glue.h" -/* When changing these, you must also update the assembler template - * in device/lib/libsdcc/macros.inc */ -#define GPTRTAG_DATA 0x00 -#define GPTRTAG_CODE 0x80 - /* The PIC port(s) need not differentiate between POINTER and FPOINTER. */ #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x)) #define PIC_IS_FARPTR(x) (PIC_IS_DATA_PTR(x)) @@ -82,8 +77,8 @@ kludgy & hacky stuff. This is what it is all about CODE GENERATION for a specific MCU . some of the routines may be reusable, will have to see */ -static char *zero = "#0x00"; -static char *one = "#0x01"; +static char *zero = "0x00"; +static char *one = "0x01"; static char *spname = "sp"; char *fReturnpic14[] = {"temp1","temp2","temp3","temp4" }; @@ -516,84 +511,7 @@ static asmop *aopForSym (iCode *ic,symbol *sym,bool result) if (sym->aop) return sym->aop; -#if 0 - /* assign depending on the storage class */ - /* if it is on the stack or indirectly addressable */ - /* space we need to assign either r0 or r1 to it */ - if ((sym->onStack && !options.stack10bit) || sym->iaccess) { - sym->aop = aop = newAsmop(0); - aop->aopu.aop_ptr = getFreePtr(ic,&aop,result); - aop->size = getSize(sym->type); - - /* now assign the address of the variable to - the pointer register */ - if (aop->type != AOP_STK) { - - if (sym->onStack) { - if ( _G.accInUse ) - pic14_emitcode("push","acc"); - - pic14_emitcode("mov","a,_bp"); - pic14_emitcode("add","a,#0x%02x", - ((sym->stack < 0) ? - ((char)(sym->stack - _G.nRegsSaved )) : - ((char)sym->stack)) & 0xff); - pic14_emitcode("mov","%s,a", - aop->aopu.aop_ptr->name); - - if ( _G.accInUse ) - pic14_emitcode("pop","acc"); - } else - pic14_emitcode("mov","%s,#%s", - aop->aopu.aop_ptr->name, - sym->rname); - aop->paged = space->paged; - } else - aop->aopu.aop_stk = sym->stack; - return aop; - } - - if (sym->onStack && options.stack10bit) - { - /* It's on the 10 bit stack, which is located in - * far data space. - */ - - //DEBUGpic14_emitcode(";","%d",__LINE__); - - if ( _G.accInUse ) - pic14_emitcode("push","acc"); - - pic14_emitcode("mov","a,_bp"); - pic14_emitcode("add","a,#0x%02x", - ((sym->stack < 0) ? - ((char)(sym->stack - _G.nRegsSaved )) : - ((char)sym->stack)) & 0xff); - - genSetDPTR(1); - pic14_emitcode ("mov","dpx1,#0x40"); - pic14_emitcode ("mov","dph1,#0x00"); - pic14_emitcode ("mov","dpl1, a"); - genSetDPTR(0); - - if ( _G.accInUse ) - pic14_emitcode("pop","acc"); - - sym->aop = aop = newAsmop(AOP_DPTR2); - aop->size = getSize(sym->type); - return aop; - } -#endif - //DEBUGpic14_emitcode(";","%d",__LINE__); - /* if in bit space */ - if (IN_BITSPACE(space)) { - sym->aop = aop = newAsmop (AOP_CRY); - aop->aopu.aop_dir = sym->rname ; - aop->size = getSize(sym->type); - //DEBUGpic14_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size); - return aop; - } /* if it is in direct space */ if (IN_DIRSPACE(space)) { sym->aop = aop = newAsmop (AOP_DIR); @@ -1109,6 +1027,7 @@ char *aopGet (asmop *aop, int offset, bool bit16, bool dname) //DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); /* offset is greater than size then zero */ + assert(aop); if (offset > (aop->size - 1) && aop->type != AOP_LIT) return zero; @@ -1236,6 +1155,9 @@ char *aopGet (asmop *aop, int offset, bool bit16, bool dname) pCodeOp *pcop = aop->aopu.pcop; DEBUGpic14_emitcode(";","%d: aopGet AOP_PCODE type %s",__LINE__,pCodeOpType(pcop)); if(pcop->name) { + if (pcop->type == PO_IMMEDIATE) { + offset += PCOI(pcop)->index; + } if (offset) { DEBUGpic14_emitcode(";","%s offset %d",pcop->name,offset); sprintf(s,"(%s+%d)", pcop->name,offset); @@ -10897,3 +10819,4 @@ op_isLitLike (operand *op) if (IS_PTR(OP_SYM_TYPE(op)) && AOP_TYPE(op) == AOP_PCODE && AOP(op)->aopu.pcop->type == PO_IMMEDIATE) return 1; return 0; } + diff --git a/src/pic/glue.c b/src/pic/glue.c index 1ad65c0b..dcd6a971 100644 --- a/src/pic/glue.c +++ b/src/pic/glue.c @@ -42,7 +42,7 @@ #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff) extern symbol *interrupts[256]; -static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb); +static void showAllMemmaps(FILE *of); // XXX: emits initialized symbols extern int noAlloc; extern set *publics; extern set *externs; @@ -200,17 +200,27 @@ pic14_constructAbsMap (struct dbuf_s *oBuf) size = 1; aliases = hTabItemWithKey (ht, addr); if (aliases && elementsInSet(aliases)) { - dbuf_printf (oBuf, "udata_abs_%s_%x\tudata_ovr\t0x%04x", + /* Make sure there is no initialized value at this location! */ + for (sym = setFirstItem(aliases); sym; sym = setNextItem(aliases)) { + if (sym->ival) break; + } // for + if (sym) continue; + + dbuf_printf (oBuf, "udata_abs_%s_%x\tudata_ovr\t0x%04x\n", moduleName, addr, addr); for (sym = setFirstItem (aliases); sym; sym = setNextItem (aliases)) { - /* emit STATUS as well as _STATUS, required for SFRs only */ - dbuf_printf (oBuf, "\n%s", sym->name); - dbuf_printf (oBuf, "\n%s", sym->rname); if (getSize(sym->type) > size) { size = getSize(sym->type); } + + /* initialized values are handled somewhere else */ + if (sym->ival) continue; + + /* emit STATUS as well as _STATUS, required for SFRs only */ + dbuf_printf (oBuf, "%s\n", sym->name); + dbuf_printf (oBuf, "%s\n", sym->rname); if (sym->islocal) { // global symbols must be emitted again as 'global sym->name' pic14_stringInSet(sym->name, &emitted, 1); @@ -368,6 +378,7 @@ pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag) } else { + if (!sym->ival) { emitSymbol (&map->oBuf, sym->rname, NULL, @@ -377,6 +388,7 @@ pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag) : -1, 0, 0); + } /* { int i, size; @@ -391,7 +403,8 @@ pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag) } //dbuf_printf (&map->oBuf, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff); } - + +#if 0 /* if it has a initial value then do it only if it is a global variable */ if (sym->ival && sym->level == 0) { @@ -407,10 +420,12 @@ pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag) eBBlockFromiCode (iCodeFromAst (ival)); sym->ival = NULL; } +#endif } } +#if 0 /*-----------------------------------------------------------------*/ /* printIvalType - generates ival for int/char */ /*-----------------------------------------------------------------*/ @@ -787,6 +802,7 @@ printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb) return; } } +#endif extern void pCodeConstString(char *name, char *value); /*-----------------------------------------------------------------*/ @@ -852,6 +868,7 @@ pic14emitStaticSeg (memmap * map) /* if it has an initial value */ if (sym->ival) { +#if 0 pBlock *pb; dbuf_printf (&code->oBuf, "%s:\n", sym->rname); @@ -864,6 +881,7 @@ pic14emitStaticSeg (memmap * map) printIval (sym, sym->type, sym->ival, pb); noAlloc--; +#endif } else { @@ -909,6 +927,7 @@ pic14emitMaps () /*-----------------------------------------------------------------*/ /* createInterruptVect - creates the interrupt vector */ /*-----------------------------------------------------------------*/ +pCodeOp *popGetExternal (char *str); static void pic14createInterruptVect (struct dbuf_s * vBuf) { @@ -942,6 +961,7 @@ pic14createInterruptVect (struct dbuf_s * vBuf) dbuf_printf (vBuf, "\tnop\n"); /* first location for used by incircuit debugger */ dbuf_printf (vBuf, "\tpagesel __sdcc_gsinit_startup\n"); dbuf_printf (vBuf, "\tgoto\t__sdcc_gsinit_startup\n"); + popGetExternal("__sdcc_gsinit_startup"); } @@ -1296,7 +1316,7 @@ picglue () /* print the global struct definitions */ if (options.debug) cdbStructBlock (0); - + /* emit code for the all the variables declared */ pic14emitMaps (); /* do the overlay segments */ @@ -1432,6 +1452,9 @@ picglue () fprintf (asmFile, "%s", iComments2); dbuf_write_and_destroy (&bit->oBuf, asmFile); + /* emit initialized data */ + showAllMemmaps(asmFile); + /* copy the interrupt vector table */ if (mainf && IFFUNC_HASBODY(mainf->type)) dbuf_write_and_destroy (&vBuf, asmFile); @@ -1441,29 +1464,6 @@ picglue () /* create interupt ventor handler */ pic14_emitInterruptHandler (asmFile); - if (mainf && IFFUNC_HASBODY(mainf->type)) { - /* initialize data memory */ - /* do NOT name this code_init to avoid conflicts with init.c */ - fprintf (asmFile, "c_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file - fprintf (asmFile,"__sdcc_gsinit_startup\n"); - /* FIXME: This is temporary. The idata section should be used. If - not, we could add a special feature to the linker. This will - work in the mean time. Put all initalized data in main.c */ - copypCode(asmFile, statsg->dbName); - fprintf (asmFile,"\tpagesel _main\n"); - fprintf (asmFile,"\tgoto _main\n"); - } - -#if 0 - - /* copy global & static initialisations */ - fprintf (asmFile, "%s", iComments2); - fprintf (asmFile, "; global & static initialisations\n"); - fprintf (asmFile, "%s", iComments2); - copypCode(asmFile, statsg->dbName); - -#endif - /* copy over code */ fprintf (asmFile, "%s", iComments2); fprintf (asmFile, "; code\n"); @@ -1488,3 +1488,485 @@ picglue () fclose (asmFile); } + +/* + * Deal with initializers. + */ +#undef DEBUGprintf +#if 0 +// debugging output +#define DEBUGprintf printf +#else +// be quiet +#define DEBUGprintf 1 ? (void)0 : (void)printf +#endif + + +void ast_print (ast * tree, FILE *outfile, int indent); + +#if 0 +/* + * Emit all memmaps. + */ +static void +showInitList(initList *list, int level) +{ + static const char *list_type[] = { "INIT_NODE", "INIT_DEEP", "INIT_HOLE" }; + static const char *ast_type[] = { "EX_OP", "EX_VALUE", "EX_LINK", "EX_OPERAND" }; + struct ast *ast; + while (list) { + printf (" %d: type %u (%s), init %p, next %p\n", level, list->type, list_type[list->type], list->init.node, list->next); + if (list->type == INIT_DEEP) { + showInitList(list->init.deep, level + 1); + } else if (list->type == INIT_NODE) { + ast = list->init.node; + printf (" type %u (%s), level %d, block %d, seqPoint %d\n", + ast->type, ast_type[ast->type], ast->level, ast->block, ast->seqPoint); + if (ast->type == EX_VALUE) { + printf (" VAL %lf\n", floatFromVal(ast->opval.val)); + } else if (ast->type == EX_LINK) { + printTypeChain(ast->opval.lnk, NULL); + } else if (ast->type == EX_OP) { + printf (" OP %u\n", ast->opval.op); + } + } // if + list = list->next; + } // while +} +#endif + +/* + * DEBUG: Print a value. + */ +void +printVal(value *val) +{ + printf ("value %p: name %s, type %p, etype %p, sym %s, vArgs %d, lit 0x%lx/%ld\n", + val, val->name, val->type, val->etype, + val->sym ? val->sym->name : NULL, val->vArgs, + (long)floatFromVal(val), (long)floatFromVal(val)); + printTypeChain(val->type, stdout); + printf ("\n"); + printTypeChain(val->etype, stdout); + printf ("\n"); +} + +//prototype from ../SDCCicode.c +operand *operandFromAst (ast * tree,int lvl); + +char * +parseIvalAst (ast *node, int *inCodeSpace) { +#define LEN 4096 + char *buffer = NULL; + char *left, *right; + + if (IS_AST_VALUE(node)) { + value *val = AST_VALUE(node); + symbol *sym = IS_AST_SYM_VALUE(node) ? AST_SYMBOL(node) : NULL; + if (inCodeSpace && val->type + && (IS_FUNC(val->type) || IS_CODE(getSpec(val->type)))) + { + *inCodeSpace = 1; + } + if (inCodeSpace && sym + && (IS_FUNC(sym->type) + || IS_CODE(getSpec(sym->type)))) + { + *inCodeSpace = 1; + } + + DEBUGprintf ("%s: AST_VALUE\n", __FUNCTION__); + if (IS_AST_LIT_VALUE(node)) { + buffer = Safe_alloc(LEN); + SNPRINTF(buffer, LEN, "0x%lx", (long)AST_LIT_VALUE(node)); + } else if (IS_AST_SYM_VALUE(node)) { + assert ( AST_SYMBOL(node) ); + /* + printf ("sym %s: ", AST_SYMBOL(node)->rname); + printTypeChain(AST_SYMBOL(node)->type, stdout); + printTypeChain(AST_SYMBOL(node)->etype, stdout); + printf ("\n---sym %s: done\n", AST_SYMBOL(node)->rname); + */ + buffer = Safe_strdup(AST_SYMBOL(node)->rname); + } else { + assert ( !"Invalid values type for initializers in AST." ); + } + } else if (IS_AST_OP(node)) { + DEBUGprintf ("%s: AST_OP\n", __FUNCTION__); + switch (node->opval.op) { + case CAST: + assert (node->right); + buffer = parseIvalAst(node->right, inCodeSpace); + DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer); + break; + case '&': + assert ( node->left && !node->right ); + buffer = parseIvalAst(node->left, inCodeSpace); + DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer); + break; + case '+': + assert (node->left && node->right ); + left = parseIvalAst(node->left, inCodeSpace); + right = parseIvalAst(node->right, inCodeSpace); + buffer = Safe_alloc(LEN); + SNPRINTF(buffer, LEN, "(%s + %s)", left, right); + DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer); + Safe_free(left); + Safe_free(right); + break; + case '[': + assert ( node->left && node->right ); + assert ( IS_AST_VALUE(node->left) && AST_VALUE(node->left)->sym ); + right = parseIvalAst(node->right, inCodeSpace); + buffer = Safe_alloc(LEN); + SNPRINTF(buffer, LEN, "(%s + %u * %s)", + AST_VALUE(node->left)->sym->rname, getSize(AST_VALUE(node->left)->type), right); + Safe_free(right); + DEBUGprintf ("%s: %s\n", __FUNCTION__, &buffer[0]); + break; + default: + assert ( !"Unhandled operation in initializer." ); + break; + } + } else { + assert ( !"Invalid construct in initializer." ); + } + + return (buffer); +} + +/* + * Emit the section preamble, absolute location (if any) and + * symbol name(s) for intialized data. + */ +static int +emitIvalLabel(FILE *of, symbol *sym) +{ + char *segname; + static int in_code = 0; + + if (sym) { + // code or data space? + if (IS_CODE(getSpec(sym->type))) { + segname = "code"; + in_code = 1; + } else { + segname = "idata"; + in_code = 0; + } + fprintf(of, "\nD_%s_%s\t%s", moduleName, sym->name, segname); + if (SPEC_ABSA(getSpec(sym->type))) { + // specify address for absolute symbols + fprintf(of, "\t0x%04X", SPEC_ADDR(getSpec(sym->type))); + } // if + fprintf(of, "\n%s\n", sym->rname); + } + return (in_code); +} + +char *get_op(pCodeOp *pcop,char *buffer, size_t size); +/* + * Actually emit the initial values in .asm format. + */ +static void +emitIvals(FILE *of, symbol *sym, initList *list, long lit, int size) +{ + int i; + ast *node; + operand *op; + value *val = NULL; + int inCodeSpace = 0; + char *str = NULL; + int in_code; + + assert (size <= sizeof(long)); + assert (!list || (list->type == INIT_NODE)); + node = list ? list->init.node : NULL; + + in_code = emitIvalLabel(of, sym); + if (!in_code) fprintf (of, "\tdb\t"); + + if (!node) { + // initialize as zero + for (i=0; i < size; i++) { + if (in_code) { + fprintf (of, "\tretlw 0x00"); + } else { + fprintf (of, "%s0x00", (i == 0) ? "" : ", "); + } + } // for + fprintf (of, "\n"); + return; + } // if + + op = NULL; + if (constExprTree(node) && (val = constExprValue(node, 0))) { + op = operandFromValue(val); + DEBUGprintf ("%s: constExpr ", __FUNCTION__); + //printVal(val); + } else if (IS_AST_VALUE(node)) { + op = operandFromAst(node, 0); + } else if (IS_AST_OP(node)) { + str = parseIvalAst(node, &inCodeSpace); + DEBUGprintf("%s: AST_OP: %s\n", __FUNCTION__, str); + op = NULL; + } else { + assert ( !"Unhandled construct in intializer." ); + } + + if (op) { + aopOp(op, NULL, 1); + assert(AOP(op)); + //printOperand(op, of); + } + + for (i=0; i < size; i++) { + char *text = op ? aopGet(AOP(op), i, 0, 0) + : get_op(newpCodeOpImmd(str, i, 0, inCodeSpace, 0), NULL, 0); + if (in_code) { + fprintf (of, "\tretlw %s\n", text); + } else { + fprintf (of, "%s%s", (i == 0) ? "" : ", ", text); + } + } // for + fprintf (of, "\n"); +} + +/* + * For UNIONs, we first have to find the correct alternative to map the + * initializer to. This function maps the structure of the initializer to + * the UNION members recursively. + * Returns the type of the first `fitting' member. + */ +static sym_link * +matchIvalToUnion (initList *list, sym_link *type, int size) +{ + symbol *sym; + + assert (type); + + if (IS_PTR(type) || IS_CHAR(type) || IS_INT(type) || IS_LONG(type) + || IS_FLOAT(type)) + { + if (!list || (list->type == INIT_NODE)) { + DEBUGprintf ("OK, simple type\n"); + return (type); + } else { + DEBUGprintf ("ERROR, simple type\n"); + return (NULL); + } + } else if (IS_BITFIELD(type)) { + if (!list || (list->type == INIT_NODE)) { + DEBUGprintf ("OK, bitfield\n"); + return (type); + } else { + DEBUGprintf ("ERROR, bitfield\n"); + return (NULL); + } + } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == STRUCT) { + if (!list || (list->type == INIT_DEEP)) { + if (list) list = list->init.deep; + sym = SPEC_STRUCT(type)->fields; + while (sym) { + DEBUGprintf ("Checking STRUCT member %s\n", sym->name); + if (!matchIvalToUnion(list, sym->type, 0)) { + DEBUGprintf ("ERROR, STRUCT member %s\n", sym->name); + return (NULL); + } + if (list) list = list->next; + sym = sym->next; + } // while + + // excess initializers? + if (list) { + DEBUGprintf ("ERROR, excess initializers\n"); + return (NULL); + } + + DEBUGprintf ("OK, struct\n"); + return (type); + } + return (NULL); + } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == UNION) { + if (!list || (list->type == INIT_DEEP)) { + if (list) list = list->init.deep; + sym = SPEC_STRUCT(type)->fields; + while (sym) { + DEBUGprintf ("Checking UNION member %s.\n", sym->name); + if (((IS_STRUCT(sym->type) || getSize(sym->type) == size)) + && matchIvalToUnion(list, sym->type, size)) + { + DEBUGprintf ("Matched UNION member %s.\n", sym->name); + return (sym->type); + } + sym = sym->next; + } // while + } // if + // no match found + DEBUGprintf ("ERROR, no match found.\n"); + return (NULL); + } else { + assert ( !"Unhandled type in UNION." ); + } + + assert ( !"No match found in UNION for the given initializer structure." ); + return (NULL); +} + +/* + * Parse the type and its initializer and emit it (recursively). + */ +static void +emitInitVal(FILE *of, symbol *topsym, sym_link *my_type, initList *list) +{ + symbol *sym; + int size, i; + long lit; + + size = getSize(my_type); + + if (IS_PTR(my_type)) { + DEBUGprintf ("(pointer, %d byte) %p\n", size, list ? (void *)(long)list2int(list) : NULL); + emitIvals(of, topsym, list, 0, size); + return; + } + + if (IS_ARRAY(my_type)) { + DEBUGprintf ("(array, %d items, %d byte) below\n", DCL_ELEM(my_type), size); + assert (!list || list->type == INIT_DEEP); + if (list) list = list->init.deep; + for (i = 0; i < DCL_ELEM(my_type); i++) { + emitInitVal(of, topsym, my_type->next, list); + topsym = NULL; + if (list) list = list->next; + } // for i + return; + } + + if (IS_FLOAT(my_type)) { + // float, 32 bit + DEBUGprintf ("(float, %d byte) %lf\n", size, list ? list2int(list) : 0.0); + emitIvals(of, topsym, list, 0, size); + return; + } + + if (IS_CHAR(my_type) || IS_INT(my_type) || IS_LONG(my_type)) { + // integral type, 8, 16, or 32 bit + DEBUGprintf ("(integral, %d byte) 0x%lx/%ld\n", size, list ? (long)list2int(list) : 0, list ? (long)list2int(list) : 0); + emitIvals(of, topsym, list, 0, size); + return; + + } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == STRUCT) { + // struct + DEBUGprintf ("(struct, %d byte) handled below\n", size); + assert (!list || (list->type == INIT_DEEP)); + + // iterate over struct members and initList + if (list) list = list->init.deep; + sym = SPEC_STRUCT(my_type)->fields; + while (sym) { + long bitfield = 0; + int len = 0; + if (IS_BITFIELD(sym->type)) { + while (sym && IS_BITFIELD(sym->type)) { + assert (!list || ((list->type == INIT_NODE) + && IS_AST_LIT_VALUE(list->init.node))); + lit = list ? list2int(list) : 0; + DEBUGprintf ( "(bitfield member) %02lx (%d bit, starting at %d, bitfield %02lx)\n", + lit, SPEC_BLEN(getSpec(sym->type)), + SPEC_BSTR(getSpec(sym->type)), bitfield); + bitfield |= (lit & ((1ul << SPEC_BLEN(getSpec(sym->type))) - 1)) << SPEC_BSTR(getSpec(sym->type)); + len += SPEC_BLEN(getSpec(sym->type)); + + sym = sym->next; + if (list) list = list->next; + } // while + assert (len < sizeof (long) * 8); // did we overflow our initializer?!? + len = (len + 7) & ~0x07; // round up to full bytes + emitIvals(of, topsym, NULL, bitfield, len / 8); + topsym = NULL; + } // if + + if (sym) { + emitInitVal(of, topsym, sym->type, list); + topsym = NULL; + sym = sym->next; + if (list) list = list->next; + } // if + } // while + if (list) { + assert ( !"Excess initializers." ); + } // if + return; + + } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == UNION) { + // union + DEBUGprintf ("(union, %d byte) handled below\n", size); + assert (list && list->type == INIT_DEEP); + + // iterate over union members and initList, try to map number and type of fields and initializers + my_type = matchIvalToUnion(list, my_type, size); + if (my_type) { + emitInitVal(of, topsym, my_type, list->init.deep); + topsym = NULL; + size -= getSize(my_type); + if (size > 0) { + // pad with (leading) zeros + emitIvals(of, NULL, NULL, 0, size); + } + return; + } // if + + assert ( !"No UNION member matches the initializer structure."); + } else if (IS_BITFIELD(my_type)) { + assert ( !"bitfields should only occur in structs..." ); + + } else { + printf ("SPEC_NOUN: %d\n", SPEC_NOUN(my_type)); + assert( !"Unhandled initialized type."); + } +} + +/* + * Iterate over all memmaps and emit their contents (attributes, symbols). + */ +static void +showAllMemmaps(FILE *of) +{ + memmap *maps[] = { + xstack, istack, code, data, pdata, xdata, xidata, xinit, + idata, bit, statsg, c_abs, x_abs, i_abs, d_abs, + sfr, sfrbit, reg, generic, overlay, eeprom, home }; + memmap * map; + symbol *sym; + initList *list; + int i; + + DEBUGprintf ("---begin memmaps---\n"); + for (i = 0; i < sizeof(maps) / sizeof (memmap *); i++) { + map = maps[i]; + //DEBUGprintf ("memmap %i: %p\n", i, map); + if (map) { + /* + DEBUGprintf (" pageno %c, sname %s, dbName %c, ptrType %d, slbl %d, sloc %u, fmap %u, paged %u, direct %u, bitsp %u, codesp %u, regsp %u, syms %p\n", + map->pageno, map->sname, map->dbName, map->ptrType, map->slbl, + map->sloc, map->fmap, map->paged, map->direct, map->bitsp, + map->codesp, map->regsp, map->syms); + */ + for (sym = setFirstItem(map->syms); sym; sym = setNextItem(map->syms)) { + /* + fprintf (of, "; name %s, rname %s, level %d, block %d, key %d, local %d, ival %p\n", + sym->name, sym->rname, sym->level, sym->block, sym->key, sym->islocal, sym->ival); + */ + list = sym->ival; + //if (list) showInitList(list, 0); + if (list) { + resolveIvalSym( list, sym->type ); + emitInitVal(of, sym, sym->type, sym->ival); + } + } // for sym + } // if (map) + } // for i + DEBUGprintf ("---end of memmaps---\n"); +} + diff --git a/src/pic/pcode.c b/src/pic/pcode.c index 45aef353..82e53971 100644 --- a/src/pic/pcode.c +++ b/src/pic/pcode.c @@ -3033,6 +3033,9 @@ char *get_op(pCodeOp *pcop,char *buffer, size_t size) case 1: SAFE_snprintf(&s,&size,"high (%s+%d)",pcop->name, PCOI(pcop)->index); break; + case 2: + SAFE_snprintf(&s,&size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA); + break; default: fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset); assert ( !"offset too large" ); @@ -3056,6 +3059,9 @@ char *get_op(pCodeOp *pcop,char *buffer, size_t size) case 1: SAFE_snprintf(&s,&size,"high (%s + %d)",pcop->name, PCOI(pcop)->index); break; + case 2: + SAFE_snprintf(&s,&size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA); + break; default: fprintf (stderr, "PO_IMMEDIATE/mutable/offset=%d\n", PCOI(pcop)->offset); assert ( !"offset too large" ); @@ -5245,7 +5251,6 @@ DEFSETFUNC (resetrIdx) /*-----------------------------------------------------------------*/ /* InitRegReuse - Initialises variables for code analyzer */ /*-----------------------------------------------------------------*/ - void InitReuseReg(void) { /* Find end of statically allocated variables for start idx */ @@ -5264,56 +5269,77 @@ void InitReuseReg(void) /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ -static unsigned register_reassign(pBlock *pb, unsigned idx) +static unsigned register_reassign(pBlock *pb, unsigned idx, unsigned level) { - pCode *pc; - - /* check recursion */ - pc = setFirstItem(pb->function_entries); - if(!pc) - return idx; + pCode *pc; - if (pb->visited) { - /* TODO: Recursion detection missing, should emit a warning as recursive code will fail. */ - return idx; - } - - pb->visited = 1; - - DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname)); - - if (pb->tregisters) { - regs *r; - for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) { - if (r->type == REG_GPR) { - if (!r->isFixed) { - if (r->rIdx < (int)idx) { - char s[20]; - r->rIdx = idx++; - if (peakIdx < idx) peakIdx = idx; - sprintf(s,"r0x%02X", r->rIdx); - DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s)); - free(r->name); - r->name = Safe_strdup(s); - } - } - } + /* check recursion */ + pc = setFirstItem(pb->function_entries); + if(!pc) + return idx; + + if (pb->visited) { + /* TODO: Recursion detection missing, should emit a warning as recursive code will fail. */ + return idx; + } + + pb->visited = 1; + + DFPRINTF((stderr," (%u) reassigning registers for function \"%s\"\n",level,PCF(pc)->fname)); + + if (pb->tregisters) { + regs *r; + for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) { + if (r->type == REG_GPR) { + if (!r->isFixed) { + if (r->rIdx < (int)idx) { + char s[20]; + set *regset; + // make sure, idx is not yet used in this routine... + do { + regset = pb->tregisters; + // do not touch s->curr ==> outer loop! + while (regset && ((regs *)regset->item)->rIdx != idx) { + regset = regset->next; + } + if (regset) idx++; + } while (regset); + r->rIdx = idx++; + if (peakIdx < idx) peakIdx = idx; + sprintf(s,"r0x%02X", r->rIdx); + DFPRINTF((stderr," (%u) reassigning register %p \"%s\" to \"%s\"\n",level,r,r->name,s)); + free(r->name); + r->name = Safe_strdup(s); + } } + } } - for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) { - - if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) { - char *dest = get_op_from_instruction(PCI(pc)); - - pCode *pcn = findFunction(dest); - if(pcn) { - register_reassign(pcn->pb,idx); - } - } - + } + for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) { + + if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) { + char *dest = get_op_from_instruction(PCI(pc)); + + pCode *pcn = findFunction(dest); + if(pcn) { + /* This index increment from subroutines is not required, as all subroutines + * may share registers NOT used by this one (< idx). + * BUT if called functions A and B share a register, which gets assigned + * rIdx = idx + 4 while analyzing A, we must not assign idx + 4 again while + * analyzing B! + * As an alternative to this "solution" we could check above whether an + * to-be-assigned rIdx is already present in the register set of the + * current function. This would increase the reused registers and make this + * `idx =' irrelevant. + * UPDATE: Implemented above; not fast, but works. + * (Problem shown with regression test src/regression/sub2.c) + */ + /*idx = */register_reassign(pcn->pb,idx,level+1); + } } - - return idx; + } + + return idx; } /*------------------------------------------------------------------*/ @@ -5344,8 +5370,8 @@ void ReuseReg(void) InitReuseReg(); for(pb = the_pFile->pbHead; pb; pb = pb->next) { /* Non static functions can be called from other modules so their registers must reassign */ - if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited)) - register_reassign(pb,peakIdx); + if (pb->function_entries && (PCF(setFirstItem(pb->function_entries))->isPublic || !pb->visited)) + register_reassign(pb,peakIdx,0); } } diff --git a/src/pic/pcode.h b/src/pic/pcode.h index 60ee4e60..d90eb86c 100644 --- a/src/pic/pcode.h +++ b/src/pic/pcode.h @@ -22,6 +22,11 @@ //#include "ralloc.h" struct regs; +/* When changing these, you must also update the assembler template + * in device/lib/libsdcc/macros.inc */ +#define GPTRTAG_DATA 0x00 +#define GPTRTAG_CODE 0x80 + /* Post code generation diff --git a/src/regression/add.c b/src/regression/add.c index 118d5c96..99fce7a9 100644 --- a/src/regression/add.c +++ b/src/regression/add.c @@ -166,18 +166,18 @@ void add_bit2uint(void) void main(void) { add_lit2uchar(); - ASSERT(_failures == 0); + ASSERT(MANGLE(failures) == 0); achar0=16; achar1=0; add_uchar2uchar(); - ASSERT(_failures == 0); + ASSERT(MANGLE(failures) == 0); achar0 = 0; achar1 = 32; add_uchar2uchar2(); - ASSERT(_failures == 0); + ASSERT(MANGLE(failures) == 0); #if SUPPORT_BIT_TYPES add_bits(); @@ -185,7 +185,7 @@ void main(void) add_bit2uchar(); add_bit2uint(); #endif - ASSERT(_failures == 0); + ASSERT(MANGLE(failures) == 0); done(); } diff --git a/src/regression/bank1.c b/src/regression/bank1.c index 05fcd8d7..3c58189b 100644 --- a/src/regression/bank1.c +++ b/src/regression/bank1.c @@ -17,11 +17,11 @@ byte d2; unsigned char uchar0 = 0xa5; -data at 0xa0 unsigned char uc_bank1_temp=0x42; -data at 0xa2 unsigned int ui_bank1_temp=0; +__data __at (0xa0) unsigned char uc_bank1_temp = 0x42; +__data __at (0xa2) unsigned int ui_bank1_temp = 3; void -done() +done(void) { dummy++; ASSERT(MANGLE(failures) == 0); diff --git a/src/regression/compare6.c b/src/regression/compare6.c index c613df03..f189ba82 100644 --- a/src/regression/compare6.c +++ b/src/regression/compare6.c @@ -22,7 +22,8 @@ done() PASSED(); } -void c_char(void) +void +c_char(void) { if(char0 || char1) @@ -66,7 +67,8 @@ void c_char(void) } -void c_int(void) +void +c_int(void) { if(int0 || int1) @@ -110,7 +112,8 @@ void c_int(void) } -void c_long(void) +void +c_long(void) { if(long0 || long1) @@ -153,7 +156,8 @@ void c_long(void) } -void c_uminus(void) +void +c_uminus(void) { int1 = -int0; @@ -177,3 +181,4 @@ main (void) success = failures; done (); } + -- 2.30.2