* src/regression/bank1.c, src/regression/compare6.c,
authortecodev <tecodev@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Mon, 22 Jan 2007 01:18:52 +0000 (01:18 +0000)
committertecodev <tecodev@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Mon, 22 Jan 2007 01:18:52 +0000 (01:18 +0000)
  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
device/lib/pic/libsdcc/idata.c [new file with mode: 0644]
src/pic/gen.c
src/pic/glue.c
src/pic/pcode.c
src/pic/pcode.h
src/regression/add.c
src/regression/bank1.c
src/regression/compare6.c

index 45c8381709f98fad8203451d728cbd039e36be13..ac8f64a313aa507734c8d549f584d29f14369228 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2007-01-22 Raphael Neider <rneider AT web.de>
+
+       * 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 <borut.razem AT siol.net>
 
        * 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 (file)
index 0000000..a73f29d
--- /dev/null
@@ -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 <rneider @ web.de>
+ * 
+ * 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;
+}
+
index baa457df66870e40524f42b8ae77e04543b3c1f7..7cf251c42bc1ada681fbb381e1cc67a7167f9a01 100644 (file)
 #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;
 }
+
index 1ad65c0b2c4722dcc15a0007dd4581df25996048..dcd6a971d5c37ce3b3dd627a2589d085c6a144bf 100644 (file)
@@ -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");
+}
+
index 45aef3532bd98e9d06ebf501e3827f8c856e2fa9..82e5397109ed6ca2d255bad1d5112810706e15c8 100644 (file)
@@ -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);
        }
 }
 
index 60ee4e603be87f6779fd740a9afe98405a076d4f..d90eb86cd531048fb537ee8b6e1484a1c46533c2 100644 (file)
 //#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
 
index 118d5c96626de2d29bc21af3c9f944e0e12767bb..99fce7a90dfa53a35c9bc53bbab69a469c9aaa30 100644 (file)
@@ -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();
 }
index 05fcd8d73177d6452b7ffed2f6f7ae6c485dbd98..3c58189b6d42584fc60d215b5b767786fe627130 100644 (file)
@@ -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);
index c613df03b264a40960a8f58d9e427eed697d7750..f189ba82467ea46ad1d1e5f7d89a539f0c2fb21a 100644 (file)
@@ -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 ();
 }
+