* src/SDCCsymt.c (copyLinkChain): fixed bug 770487, copy structdef and fields-list too
[fw/sdcc] / src / SDCCast.c
index 9e7d4fbba77da5f6da9fa6418dbf2523ad6e8a5c..83214a5abd2442bc0fe828f85cde3d527e8ceea6 100644 (file)
@@ -55,7 +55,10 @@ static ast *createIvalCharPtr (ast *, sym_link *, ast *);
 static ast *optimizeCompare (ast *);
 ast *optimizeRRCRLC (ast *);
 ast *optimizeSWAP (ast *);
-ast *optimizeGetHbit (ast *);
+ast *optimizeGetHbit (ast *, RESULT_TYPE);
+ast *optimizeGetAbit (ast *, RESULT_TYPE);
+ast *optimizeGetByte (ast *, RESULT_TYPE);
+ast *optimizeGetWord (ast *, RESULT_TYPE);
 ast *backPatchLabels (ast *, symbol *, symbol *);
 void PA(ast *t);
 int inInitMode = 0;
@@ -218,6 +221,7 @@ copyAst (ast * src)
   dest->lineno = src->lineno;
   dest->level = src->level;
   dest->funcName = src->funcName;
+  dest->reversed = src->reversed;
 
   if (src->ftype)
     dest->etype = getSpec (dest->ftype = copyLinkChain (src->ftype));
@@ -572,7 +576,7 @@ funcOfType (char *name, sym_link * type, sym_link * argType,
     }
 
   /* save it */
-  addSymChain (sym);
+  addSymChain (&sym);
   sym->cdef = 1;
   allocVariables (sym);
   return sym;
@@ -612,7 +616,7 @@ funcOfTypeVarg (char *name, char * rtype, int nArgs , char **atypes)
     }
 
     /* save it */
-    addSymChain (sym);
+    addSymChain (&sym);
     sym->cdef = 1;
     allocVariables (sym);
     return sym;
@@ -630,11 +634,25 @@ reverseParms (ast * ptree)
     return;
 
   /* top down if we find a nonParm tree then quit */
-  if (ptree->type == EX_OP && ptree->opval.op == PARAM)
+  if (ptree->type == EX_OP && ptree->opval.op == PARAM && !ptree->reversed)
     {
+      /* The various functions expect the parameter tree to be right heavy. */
+      /* Rotate the tree to be left heavy so that after reversal it is */
+      /* right heavy again. */
+      while ((ttree = ptree->right) && ttree->type == EX_OP &&
+             ttree->opval.op == PARAM)
+        {
+          ptree->right = ttree->right;
+          ttree->right = ttree->left;
+          ttree->left = ptree->left;
+          ptree->left = ttree;
+        }
+    
+      /* Now reverse */
       ttree = ptree->left;
       ptree->left = ptree->right;
       ptree->right = ttree;
+      ptree->reversed = 1;
       reverseParms (ptree->left);
       reverseParms (ptree->right);
     }
@@ -678,11 +696,15 @@ processParms (ast *func,
   /* if the function is being called via a pointer &   */
   /* it has not been defined a reentrant then we cannot */
   /* have parameters                                   */
-  if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
+  /* PIC16 port can... */
+  if (!TARGET_IS_PIC16)
     {
-      werror (W_NONRENT_ARGS);
-      fatalError++;
-      return 1;
+      if (func->type != EX_VALUE && !IFFUNC_ISREENT (functype) && !options.stackAuto)
+        {
+          werror (W_NONRENT_ARGS);
+          fatalError++;
+          return 1;
+        }
     }
 
   /* if defined parameters ended but actual parameters */
@@ -834,8 +856,8 @@ createIvalType (ast * sym, sym_link * type, initList * ilist)
   if (ilist->type == INIT_DEEP)
     ilist = ilist->init.deep;
 
-  iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
-  return decorateType (newNode ('=', sym, iExpr), RESULT_CHECK);
+  iExpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
+  return decorateType (newNode ('=', sym, iExpr), RESULT_TYPE_NONE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -865,8 +887,8 @@ createIvalStruct (ast * sym, sym_link * type, initList * ilist)
         break;
       sflds->implicit = 1;
       lAst = newNode (PTR_OP, newNode ('&', sym, NULL), newAst_VALUE (symbolVal (sflds)));
-      lAst = decorateType (resolveSymbols (lAst), RESULT_CHECK);
-      rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), RESULT_CHECK);
+      lAst = decorateType (resolveSymbols (lAst), RESULT_TYPE_NONE);
+      rast = decorateType (resolveSymbols (createIval (lAst, sflds->type, iloop, rast)), RESULT_TYPE_NONE);
     }
 
   if (iloop) {
@@ -896,9 +918,9 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
   if (IS_CHAR (type->next))
     if ((rast = createIvalCharPtr (sym,
                                    type,
-                        decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK))))
+                        decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE))))
 
-      return decorateType (resolveSymbols (rast), RESULT_CHECK);
+      return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
 
     /* not the special case             */
     if (ilist->type != INIT_DEEP)
@@ -914,7 +936,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
     {
         ast *aSym;
 
-        aSym = decorateType (resolveSymbols(sym), RESULT_CHECK);
+        aSym = decorateType (resolveSymbols(sym), RESULT_TYPE_NONE);
         
         rast = newNode(ARRAYINIT, aSym, NULL);
         rast->values.constlist = literalL;
@@ -943,7 +965,7 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
             ast *aSym;
             
             aSym = newNode ('[', sym, newAst_VALUE (valueFromLit ((float) (size++))));
-            aSym = decorateType (resolveSymbols (aSym), RESULT_CHECK);
+            aSym = decorateType (resolveSymbols (aSym), RESULT_TYPE_NONE);
             rast = createIval (aSym, type->next, iloop, rast);
             iloop = (iloop ? iloop->next : NULL);
             if (!iloop)
@@ -969,11 +991,10 @@ createIvalArray (ast * sym, sym_link * type, initList * ilist)
     /* if we have not been given a size  */
     if (!DCL_ELEM (type))
     {
-        /* but this still updates the typedef instead of the instance ! see bug 770487 */
         DCL_ELEM (type) = size;
     }
 
-    return decorateType (resolveSymbols (rast), RESULT_CHECK);
+    return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
 }
 
 
@@ -1008,8 +1029,12 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
       if (size>symsize)
         {
           if (size>(symsize+1))
-            werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
-                      "string", sym->opval.val->sym->name);
+            {
+              char *name = (IS_AST_SYM_VALUE(sym)) ? AST_SYMBOL(sym)->name : "";
+
+              werrorfl (iexpr->filename, iexpr->lineno, W_EXCESS_INITIALIZERS,
+                        "string", name);
+            }
           size = symsize;
         }
 
@@ -1027,7 +1052,7 @@ createIvalCharPtr (ast * sym, sym_link * type, ast * iexpr)
       // now WE don't need iexpr's symbol anymore
       freeStringSymbol(AST_SYMBOL(iexpr));
 
-      return decorateType (resolveSymbols (rast), RESULT_CHECK);
+      return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
     }
 
   return NULL;
@@ -1046,7 +1071,7 @@ createIvalPtr (ast * sym, sym_link * type, initList * ilist)
   if (ilist->type == INIT_DEEP)
     ilist = ilist->init.deep;
 
-  iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_CHECK);
+  iexpr = decorateType (resolveSymbols (list2expr (ilist)), RESULT_TYPE_NONE);
 
   /* if character pointer */
   if (IS_CHAR (type->next))
@@ -1084,9 +1109,9 @@ createIval (ast * sym, sym_link * type, initList * ilist, ast * wid)
     rast = createIvalType (sym, type, ilist);
 
   if (wid)
-    return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_CHECK);
+    return decorateType (resolveSymbols (newNode (NULLOP, wid, rast)), RESULT_TYPE_NONE);
   else
-    return decorateType (resolveSymbols (rast), RESULT_CHECK);
+    return decorateType (resolveSymbols (rast), RESULT_TYPE_NONE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1115,6 +1140,21 @@ gatherAutoInit (symbol * autoChain)
       if (sym->ival)
         resolveIvalSym (sym->ival, sym->type);
 
+#if 1
+      /* if we are PIC16 port,
+       * and this is a static,
+       * and have initial value,
+       * and not S_CODE, don't emit in gs segment,
+       * but allow glue.c:pic16emitRegularMap to put symbol
+       * in idata section */
+      if(TARGET_IS_PIC16 &&
+        IS_STATIC (sym->etype) && sym->ival
+        && SPEC_SCLS(sym->etype) != S_CODE) {
+        SPEC_SCLS (sym->etype) = S_DATA;
+        continue;
+      }
+#endif
+
       /* if this is a static variable & has an */
       /* initial value the code needs to be lifted */
       /* here to the main portion since they can be */
@@ -1216,7 +1256,7 @@ stringToSymbol (value * val)
   static int charLbl = 0;
   symbol *sym;
   set *sp;
-  int size;
+  unsigned int size;
 
   // have we heard this before?
   for (sp=statsg->syms; sp; sp=sp->next) {
@@ -1249,7 +1289,7 @@ stringToSymbol (value * val)
   if (noAlloc == 0)
     {
       /* allocate it */
-      addSymChain (sym);
+      addSymChain (&sym);
       allocVariables (sym);
     }
   sym->ival = NULL;
@@ -1302,7 +1342,7 @@ bool constExprTree (ast *cexpr) {
     return TRUE;
   }
 
-  cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
+  cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
 
   switch (cexpr->type) 
     {
@@ -1366,7 +1406,7 @@ bool constExprTree (ast *cexpr) {
 value *
 constExprValue (ast * cexpr, int check)
 {
-  cexpr = decorateType (resolveSymbols (cexpr), RESULT_CHECK);
+  cexpr = decorateType (resolveSymbols (cexpr), RESULT_TYPE_NONE);
 
   /* if this is not a constant then */
   if (!IS_LITERAL (cexpr->ftype))
@@ -1499,6 +1539,8 @@ isLoopCountable (ast * initExpr, ast * condExpr, ast * loopExpr,
         }
 
     }
+  else
+    return FALSE;
 
   /* check loop expression is of the form <sym>++ */
   if (!IS_AST_OP (loopExpr))
@@ -1720,6 +1762,9 @@ isConformingBody (ast * pbody, symbol * sym, ast * body)
     case '%':
     case LEFT_OP:
     case RIGHT_OP:
+    case GETABIT:
+    case GETBYTE:
+    case GETWORD:
 
       if (IS_AST_SYM_VALUE (pbody->left) &&
           isSymbolEqual (AST_SYMBOL (pbody->left), sym))
@@ -1961,7 +2006,7 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
                                                   rloop))));
 
   rloop->lineno=init->lineno;
-  return decorateType (rloop, RESULT_CHECK);
+  return decorateType (rloop, RESULT_TYPE_NONE);
 
 }
 
@@ -1969,7 +2014,7 @@ reverseLoop (ast * loop, symbol * sym, ast * init, ast * end)
 /* searchLitOp - search tree (*ops only) for an ast with literal */
 /*-----------------------------------------------------------------*/
 static ast *
-searchLitOp (ast *tree, ast **parent, const char *ops)
+searchLitOp (ast *tree, ast **parent, const unsigned char *ops)
 {
   ast *ret;
 
@@ -2045,7 +2090,7 @@ getResultTypeFromType (sym_link *type)
 /* addCast - adds casts to a type specified by RESULT_TYPE         */
 /*-----------------------------------------------------------------*/
 static ast *
-addCast (ast *tree, RESULT_TYPE resultType, bool upcast)
+addCast (ast *tree, RESULT_TYPE resultType, bool promote)
 {
   sym_link *newLink;
   bool upCasted = FALSE;
@@ -2053,16 +2098,30 @@ addCast (ast *tree, RESULT_TYPE resultType, bool upcast)
   switch (resultType)
     {
       case RESULT_TYPE_NONE:
-        /* char: promote to int */
-        if (!upcast ||
+        /* if thing smaller than int must be promoted to int */
+        if (!promote ||
             getSize (tree->etype) >= INTSIZE)
+          /* promotion not necessary or already an int */
+          return tree;
+        /* char and bits: promote to int */
+        newLink = newIntLink();
+        upCasted = TRUE;
+        break;
+      case RESULT_TYPE_BIT:
+        if (!promote ||
+            /* already an int */
+            bitsForType (tree->etype) >= 16 ||
+            /* bit to bit operation: don't promote, the code generators
+               hopefully know everything about promotion rules */
+            bitsForType (tree->etype) == 1)
           return tree;
         newLink = newIntLink();
         upCasted = TRUE;
         break;
       case RESULT_TYPE_CHAR:
         if (IS_CHAR (tree->etype) ||
-            IS_FLOAT(tree->etype))
+            IS_FLOAT(tree->etype) ||
+            IS_FIXED(tree->etype))
           return tree;
         newLink = newCharLink();
         break;
@@ -2075,14 +2134,14 @@ addCast (ast *tree, RESULT_TYPE resultType, bool upcast)
           }
 #endif
         /* char: promote to int */
-        if (!upcast ||
+        if (!promote ||
             getSize (tree->etype) >= INTSIZE)
           return tree;
         newLink = newIntLink();
         upCasted = TRUE;
         break;
       case RESULT_TYPE_OTHER:
-        if (!upcast)
+        if (!promote)
           return tree;
         /* return type is long, float: promote char to int */
         if (getSize (tree->etype) >= INTSIZE)
@@ -2111,6 +2170,9 @@ resultTypePropagate (ast *tree, RESULT_TYPE resultType)
 {
   switch (tree->opval.op)
     {
+      case AND_OP:
+      case OR_OP:
+        return resultType;
       case '=':
       case '?':
       case ':':
@@ -2560,10 +2622,37 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           /* see if this is a GETHBIT operation if yes
              then return that */
           {
-            ast *otree = optimizeGetHbit (tree);
+            ast *otree = optimizeGetHbit (tree, resultType);
 
             if (otree != tree)
-              return decorateType (otree, RESULT_CHECK);
+              return decorateType (otree, RESULT_TYPE_NONE);
+          }
+
+          /* see if this is a GETABIT operation if yes
+             then return that */
+          {
+            ast *otree = optimizeGetAbit (tree, resultType);
+
+            if (otree != tree)
+              return decorateType (otree, RESULT_TYPE_NONE);
+          }
+
+          /* see if this is a GETBYTE operation if yes
+             then return that */
+          {
+            ast *otree = optimizeGetByte (tree, resultType);
+
+            if (otree != tree)
+              return decorateType (otree, RESULT_TYPE_NONE);
+          }
+
+          /* see if this is a GETWORD operation if yes
+             then return that */
+          {
+            ast *otree = optimizeGetWord (tree, resultType);
+
+            if (otree != tree)
+              return decorateType (otree, RESULT_TYPE_NONE);
           }
 
           /* if left is a literal exchange left & right */
@@ -2594,15 +2683,6 @@ decorateType (ast * tree, RESULT_TYPE resultType)
 
           LRVAL (tree) = RRVAL (tree) = 1;
           
-          /* AND is signless so make signedness of literal equal */
-          /* to signedness of left for better optimized code */
-          if (IS_LITERAL (RTYPE (tree)) &&
-              (getSize(LTYPE(tree)) == getSize(RTYPE(tree))) &&
-              (SPEC_USIGN(LTYPE(tree)) != SPEC_USIGN(RTYPE(tree))) )
-            {
-              SPEC_USIGN(RTYPE(tree)) = SPEC_USIGN(LTYPE(tree));
-            }
-
           TTYPE (tree) = computeType (LTYPE (tree),
                                       RTYPE (tree),
                                       resultType,
@@ -2698,15 +2778,15 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /*  bitwise or                */
       /*----------------------------*/
     case '|':
-      /* if the rewrite succeeds then don't go any furthur */
+      /* if the rewrite succeeds then don't go any further */
       {
         ast *wtree = optimizeRRCRLC (tree);
         if (wtree != tree)
-          return decorateType (wtree, RESULT_CHECK);
+          return decorateType (wtree, RESULT_TYPE_NONE);
         
         wtree = optimizeSWAP (tree);
         if (wtree != tree)
-          return decorateType (wtree, RESULT_CHECK);
+          return decorateType (wtree, RESULT_TYPE_NONE);
       }
 
       /* if left is a literal exchange left & right */
@@ -2792,15 +2872,6 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             }
         }
 
-      /* OR/XOR are signless so make signedness of literal equal */
-      /* to signedness of left for better optimized code */
-      if (IS_LITERAL (RTYPE (tree)) &&
-          (getSize(LTYPE(tree)) == getSize(RTYPE(tree))) &&
-          (SPEC_USIGN(LTYPE(tree)) != SPEC_USIGN(RTYPE(tree))) )
-        {
-          SPEC_USIGN(RTYPE(tree)) = SPEC_USIGN(LTYPE(tree));
-        }
-
       LRVAL (tree) = RRVAL (tree) = 1;
 
       TTYPE (tree) = computeType (LTYPE (tree),
@@ -2868,7 +2939,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
               else
                 {
                   /* litTree->left is literal: no gcse possible.
-                     We can't call decorateType(parent, RESULT_CHECK), because
+                     We can't call decorateType(parent, RESULT_TYPE_NONE), because
                      this would cause an infinit loop. */
                   parent->decorated = 1;
                   decorateType (litTree, resultType);
@@ -3354,7 +3425,23 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           TETYPE (tree) = TTYPE (tree) = tree->opval.val->type;
           return addCast (tree, resultType, TRUE);
         }
-      tree->left = addCast (tree->left, resultType, TRUE);
+
+      if (resultType == RESULT_TYPE_BIT &&
+          IS_UNSIGNED (tree->left->etype) &&
+          getSize (tree->left->etype) < INTSIZE)
+        {
+          /* promotion rules are responsible for this strange result:
+             bit -> int -> ~int -> bit
+             uchar -> int -> ~int -> bit
+          */
+          werror(W_COMPLEMENT);
+
+          /* optimize bit-result, even if we optimize a buggy source */
+          tree->type = EX_VALUE;
+          tree->opval.val = constVal ("1");
+        }
+      else
+        tree->left = addCast (tree->left, resultType, TRUE);
       LRVAL (tree) = 1;
       COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree));
       return tree;
@@ -3383,7 +3470,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           return tree;
         }
       LRVAL (tree) = 1;
-      TTYPE (tree) = TETYPE (tree) = newCharLink ();
+      TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -3398,7 +3485,16 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       return tree;
 
     case GETHBIT:
-      TTYPE (tree) = TETYPE (tree) = newCharLink ();
+    case GETABIT:
+      TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
+      return tree;
+
+    case GETBYTE:
+      TTYPE (tree) = TETYPE (tree) = newCharLink();
+      return tree;
+
+    case GETWORD:
+      TTYPE (tree) = TETYPE (tree) = newIntLink();
       return tree;
 
     case LEFT_OP:
@@ -3432,6 +3528,24 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           return tree;
         }
 
+      /* see if this is a GETBYTE operation if yes
+         then return that */
+      {
+        ast *otree = optimizeGetByte (tree, resultType);
+
+        if (otree != tree)
+          return decorateType (otree, RESULT_TYPE_NONE);
+      }
+
+      /* see if this is a GETWORD operation if yes
+         then return that */
+      {
+        ast *otree = optimizeGetWord (tree, resultType);
+
+        if (otree != tree)
+          return decorateType (otree, RESULT_TYPE_NONE);
+      }
+
       LRVAL (tree) = RRVAL (tree) = 1;
       if (tree->opval.op == LEFT_OP)
         {
@@ -3484,6 +3598,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
         }
 
       /* make sure the type is complete and sane */
+      changePointer(LTYPE(tree));
       checkTypeSanity(LETYPE(tree), "(cast)");
 
       /* If code memory is read only, then pointers to code memory */
@@ -3546,11 +3661,37 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       if (IS_ADDRESS_OF_OP(tree->right)
           && IS_AST_SYM_VALUE (tree->right->left)
           && SPEC_ABSA (AST_SYMBOL (tree->right->left)->etype)) {
+        
+        symbol * sym = AST_SYMBOL (tree->right->left);
+        unsigned int gptype = 0;
+        unsigned int addr = SPEC_ADDR (sym->etype);
 
+        if (IS_GENPTR (LTYPE (tree)) && GPTRSIZE > FPTRSIZE)
+          {
+            switch (SPEC_SCLS (sym->etype))
+              {
+              case S_CODE:
+                gptype = GPTYPE_CODE;
+                break;
+              case S_XDATA:
+                gptype = GPTYPE_FAR;
+                break;
+              case S_DATA:
+              case S_IDATA:
+                gptype = GPTYPE_NEAR;
+                break;
+              case S_PDATA:
+                gptype = GPTYPE_XSTACK;
+                break;
+              default:
+                gptype = 0;
+              }
+            addr |= gptype << (8*(GPTRSIZE - 1));
+          }
+        
         tree->type = EX_VALUE;
         tree->opval.val =
-          valCastLiteral (LTYPE (tree),
-                          SPEC_ADDR (AST_SYMBOL (tree->right->left)->etype));
+          valCastLiteral (LTYPE (tree), addr);
         TTYPE (tree) = tree->opval.val->type;
         TETYPE (tree) = getSpec (TTYPE (tree));
         tree->left = NULL;
@@ -3689,7 +3830,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           return tree;
         }
       LRVAL (tree) = RRVAL (tree) = 1;
-      TTYPE (tree) = TETYPE (tree) = newCharLink ();
+      TTYPE (tree) = TETYPE (tree) = (resultTypeProp == RESULT_TYPE_BIT) ? newBoolLink() :newCharLink();
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -3774,7 +3915,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                                      tree->right); /* val 0 */
               tree->right->lineno = tree->lineno;
               tree->right->left->lineno = tree->lineno;
-              decorateType (tree->right, RESULT_CHECK);
+              decorateType (tree->right, RESULT_TYPE_NONE);
             }
         }
       /* if they are both literal then */
@@ -3832,6 +3973,9 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                 case V_FLOAT:
                     typeofv = TYPEOF_FLOAT;
                     break;
+                case V_FIXED16X16:
+                    typeofv = TYPEOF_FIXED16X16;
+                    break;
                 case V_CHAR:
                     typeofv = TYPEOF_CHAR;
                     break;
@@ -3916,7 +4060,8 @@ decorateType (ast * tree, RESULT_TYPE resultType)
 
     case ':':
       /* if they don't match we have a problem */
-      if (compareType (LTYPE (tree), RTYPE (tree)) == 0)
+      if ((compareType (LTYPE (tree), RTYPE (tree)) == 0) &&
+          (compareType (RTYPE (tree), LTYPE (tree)) == 0))
         {
           werror (E_TYPE_MISMATCH, "conditional operator", " ");
           goto errorTreeReturn;
@@ -4061,7 +4206,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           goto errorTreeReturn;
         }
 
-      tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_CHECK);
+      tree->right = decorateType (newNode ('+', copyAst (tree->left), tree->right), RESULT_TYPE_NONE);
       tree->opval.op = '=';
 
       return tree;
@@ -4132,8 +4277,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
         }
 
       /* require a function or pointer to function */
-      if (!IS_FUNC (LTYPE (tree))
-          && !(IS_CODEPTR (LTYPE (tree)) && IS_FUNC (LTYPE (tree)->next)))
+      if (!IS_FUNC (LTYPE (tree)) && !IS_FUNCPTR (LTYPE (tree)))
         {
           werrorfl (tree->filename, tree->lineno, E_FUNCTION_EXPECTED);
           goto errorTreeReturn;
@@ -4147,7 +4291,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
           sym_link *functype;      
           parmNumber = 1;
 
-          if (IS_CODEPTR(LTYPE(tree)))
+          if (IS_FUNCPTR (LTYPE (tree)))
             functype = LTYPE (tree)->next;
           else
             functype = LTYPE (tree);
@@ -4199,7 +4343,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
             decorateType (newNode (CAST,
                           newAst_LINK (copyLinkChain (currFunc->type->next)),
                                         tree->right),
-                          RESULT_CHECK);
+                          RESULT_TYPE_NONE);
         }
 
       RRVAL (tree) = 1;
@@ -4248,9 +4392,9 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       /*----------------------------*/
     case FOR:
 
-      decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_CHECK);
-      decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_CHECK);
-      decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_CHECK);
+      decorateType (resolveSymbols (AST_FOR (tree, initExpr)), RESULT_TYPE_NONE);
+      decorateType (resolveSymbols (AST_FOR (tree, condExpr)), RESULT_TYPE_NONE);
+      decorateType (resolveSymbols (AST_FOR (tree, loopExpr)), RESULT_TYPE_NONE);
 
       /* if the for loop is reversible then
          reverse it otherwise do what we normally
@@ -4269,7 +4413,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                                           AST_FOR (tree, initExpr),
                                           AST_FOR (tree, condExpr),
                                           AST_FOR (tree, loopExpr),
-                                          tree->left), RESULT_CHECK);
+                                          tree->left), RESULT_TYPE_NONE);
       }
     case PARAM:
       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
@@ -4433,7 +4577,6 @@ createBlock (symbol * decl, ast * body)
   ex = newNode (BLOCK, NULL, body);
   ex->values.sym = decl;
   
-  ex->right = ex->right;
   ex->level++;
   ex->lineno = 0;
   return ex;
@@ -4494,7 +4637,7 @@ createCase (ast * swStat, ast * caseVal, ast * stmnt)
       return NULL;
     }
 
-  caseVal = decorateType (resolveSymbols (caseVal), RESULT_CHECK);
+  caseVal = decorateType (resolveSymbols (caseVal), RESULT_TYPE_NONE);
   /* if not a constant then error  */
   if (!IS_LITERAL (caseVal->ftype))
     {
@@ -4819,41 +4962,194 @@ createWhile (symbol * trueLabel, symbol * continueLabel,
 }
 
 /*-----------------------------------------------------------------*/
-/* optimizeGetHbit - get highest order bit of the expression       */
+/* isShiftRightLitVal _BitAndLitVal - helper function              */
 /*-----------------------------------------------------------------*/
-ast *
-optimizeGetHbit (ast * tree)
+static ast *
+isShiftRightLitVal_BitAndLitVal (ast * tree)
 {
-  int i, j;
   /* if this is not a bit and */
   if (!IS_BITAND (tree))
-    return tree;
+    return NULL;
+
+  /* will look for tree of the form
+     ( expr >> litval2) & litval1 */
+  if (!IS_AST_LIT_VALUE (tree->right))
+    return NULL;
+
+  if (!IS_RIGHT_OP (tree->left))
+    return NULL;
+
+  if (!IS_AST_LIT_VALUE (tree->left->right))
+    return NULL;
+
+  return tree->left->left;
+}
+
+/*-----------------------------------------------------------------*/
+/* isBitAndPowOf2 - helper function                                */
+/*-----------------------------------------------------------------*/
+static int
+isBitAndPow2 (ast * tree)
+{
+  /* if this is not a bit and */
+  if (!IS_BITAND (tree))
+    return -1;
 
   /* will look for tree of the form
-     ( expr >> ((sizeof expr) -1) ) & 1 */
+     ( expr & (1 << litval) */
   if (!IS_AST_LIT_VALUE (tree->right))
+    return -1;
+
+  return powof2 ((TYPE_UDWORD)AST_LIT_VALUE (tree->right));
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetHbit - get highest order bit of the expression       */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetHbit (ast * tree, RESULT_TYPE resultType)
+{
+  int i, j;
+  ast * expr;
+
+  expr = isShiftRightLitVal_BitAndLitVal(tree);
+  if (expr)
+    {
+      if ((AST_LIT_VALUE (tree->right) != 1) ||
+          ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
+          (j = (getSize (TTYPE (expr)) * 8 - 1))))
+        expr = NULL;
+    }
+  if (!expr && (resultType == RESULT_TYPE_BIT))
+    {
+      expr = tree->left;
+      if (isBitAndPow2 (tree) != getSize (TTYPE (expr)) * 8 - 1)
+        expr = NULL;
+    }
+  if (!expr)
     return tree;
 
-  if (AST_LIT_VALUE (tree->right) != 1)
+  /* make sure the port supports GETHBIT */
+  if (port->hasExtBitOp
+      && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (expr))))
     return tree;
 
-  if (!IS_RIGHT_OP (tree->left))
+  return decorateType (newNode (GETHBIT, expr, NULL), RESULT_TYPE_NONE);
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetAbit - get a single bit of the expression            */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetAbit (ast * tree, RESULT_TYPE resultType)
+{
+  ast * expr;
+  ast * count = NULL;
+
+  expr = isShiftRightLitVal_BitAndLitVal(tree);
+  if (expr)
+    {
+  if (AST_LIT_VALUE (tree->right) != 1)
+        expr = NULL;
+      count = tree->left->right;
+    }
+  if (!expr && (resultType == RESULT_TYPE_BIT))
+    {
+      int p2 = isBitAndPow2 (tree);
+      if (p2 >= 0)
+        {
+          expr = tree->left;
+          count = newAst_VALUE (valueFromLit (p2));
+        }
+    }
+  if (!expr)
     return tree;
 
-  if (!IS_AST_LIT_VALUE (tree->left->right))
+  /* make sure the port supports GETABIT */
+  if (port->hasExtBitOp
+      && !port->hasExtBitOp(GETABIT, getSize (TTYPE (expr))))
     return tree;
 
-  if ((i = (int) AST_LIT_VALUE (tree->left->right)) !=
-      (j = (getSize (TTYPE (tree->left->left)) * 8 - 1)))
+  return decorateType (newNode (GETABIT, expr, count), RESULT_TYPE_NONE);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetByte - get a byte of the expression                  */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetByte (ast * tree, RESULT_TYPE resultType)
+{
+  unsigned int i = 0;
+  ast * expr;
+  ast * count = NULL;
+
+  expr = isShiftRightLitVal_BitAndLitVal(tree);
+  if (expr)
+    {
+      i = (unsigned int) AST_LIT_VALUE (tree->left->right);
+      count = tree->left->right;
+      if (AST_LIT_VALUE (tree->right) != 0xFF)
+        expr = NULL;
+    }
+  if (!expr && resultType == RESULT_TYPE_CHAR)
+    {
+      /* if this is a right shift over a multiple of 8 */
+      if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
+        {
+          i = (unsigned int) AST_LIT_VALUE (tree->right);
+          count = tree->right;
+            expr = tree->left;
+        }
+    }
+  if (!expr || (i == 0) || (i % 8) || (i >= getSize (TTYPE (expr)) * 8))
     return tree;
       
-  /* make sure the port supports GETHBIT */
+  /* make sure the port supports GETBYTE */
   if (port->hasExtBitOp
-      && !port->hasExtBitOp(GETHBIT, getSize (TTYPE (tree->left->left))))
+      && !port->hasExtBitOp(GETBYTE, getSize (TTYPE (expr))))
     return tree;
 
-  return decorateType (newNode (GETHBIT, tree->left->left, NULL), RESULT_CHECK);
+  return decorateType (newNode (GETBYTE, expr, count), RESULT_TYPE_NONE);
+}
+
+/*-----------------------------------------------------------------*/
+/* optimizeGetWord - get two bytes of the expression               */
+/*-----------------------------------------------------------------*/
+ast *
+optimizeGetWord (ast * tree, RESULT_TYPE resultType)
+{
+  unsigned int i = 0;
+  ast * expr;
+  ast * count = NULL;
+
+  expr = isShiftRightLitVal_BitAndLitVal(tree);
+  if (expr)
+    {
+      i = (unsigned int) AST_LIT_VALUE (tree->left->right);
+      count = tree->left->right;
+      if (AST_LIT_VALUE (tree->right) != 0xFFFF)
+        expr = NULL;
+    }      
+  if (!expr && resultType == RESULT_TYPE_INT)
+    {
+      /* if this is a right shift over a multiple of 8 */
+      if (IS_RIGHT_OP (tree) && IS_AST_LIT_VALUE (tree->right))
+        {
+          i = (unsigned int) AST_LIT_VALUE (tree->right);
+          count = tree->right;
+            expr = tree->left;
+        }
+    }
+  if (!expr || (i == 0) || (i % 8) || (i >= (getSize (TTYPE (expr))-1) * 8))
+    return tree;
+      
+  /* make sure the port supports GETWORD */
+  if (port->hasExtBitOp
+      && !port->hasExtBitOp(GETWORD, getSize (TTYPE (expr))))
+    return tree;
 
+  return decorateType (newNode (GETWORD, expr, count), RESULT_TYPE_NONE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -5079,7 +5375,7 @@ optimizeSWAP (ast * root)
 }
 
 /*-----------------------------------------------------------------*/
-/* optimizeCompare - otimizes compares for bit variables     */
+/* optimizeCompare - optimizes compares for bit variables          */
 /*-----------------------------------------------------------------*/
 static ast *
 optimizeCompare (ast * root)
@@ -5119,7 +5415,7 @@ optimizeCompare (ast * root)
           break;
         }
 
-      return decorateType (optExpr, RESULT_CHECK);
+      return decorateType (optExpr, RESULT_TYPE_NONE);
     }
 
   vleft = (root->left->type == EX_VALUE ?
@@ -5193,7 +5489,7 @@ optimizeCompare (ast * root)
               break;
             }
         }
-      return decorateType (resolveSymbols (optExpr), RESULT_CHECK);
+      return decorateType (resolveSymbols (optExpr), RESULT_TYPE_NONE);
     }                           /* end-of-if of BITVAR */
 
 noOptimize:
@@ -5296,21 +5592,26 @@ createFunction (symbol * name, ast * body)
     }
   else
     {
-      addSymChain (name);
+      addSymChain (&name);
       allocVariables (name);
     }
   name->lastLine = mylineno;
   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 = 0;
+
   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 */
@@ -5371,7 +5672,7 @@ createFunction (symbol * name, ast * body)
     {
       GcurMemmap = statsg;
       codeOutFile = statsg->oFile;
-      eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_CHECK)));
+      eBBlockFromiCode (iCodeFromAst (decorateType (resolveSymbols (staticAutos), RESULT_TYPE_NONE)));
       staticAutos = NULL;
     }
 
@@ -5728,7 +6029,7 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                 return;
                 /*------------------------------------------------------------------*/
                 /*----------------------------*/
-                /*    compliment              */
+                /*    complement              */
                 /*----------------------------*/
         case '~':
                 fprintf(outfile,"COMPL (%p) type (",tree);
@@ -5775,6 +6076,27 @@ void ast_print (ast * tree, FILE *outfile, int indent)
                 fprintf(outfile,")\n");
                 ast_print(tree->left,outfile,indent+2);
                 return ;
+        case GETABIT:
+                fprintf(outfile,"GETABIT (%p) type (",tree);
+                printTypeChain(tree->ftype,outfile);
+                fprintf(outfile,")\n");
+                ast_print(tree->left,outfile,indent+2);
+                ast_print(tree->right,outfile,indent+2);
+                return ;
+        case GETBYTE:
+                fprintf(outfile,"GETBYTE (%p) type (",tree);
+                printTypeChain(tree->ftype,outfile);
+                fprintf(outfile,")\n");
+                ast_print(tree->left,outfile,indent+2);
+                ast_print(tree->right,outfile,indent+2);
+                return ;
+        case GETWORD:
+                fprintf(outfile,"GETWORD (%p) type (",tree);
+                printTypeChain(tree->ftype,outfile);
+                fprintf(outfile,")\n");
+                ast_print(tree->left,outfile,indent+2);
+                ast_print(tree->right,outfile,indent+2);
+                return ;
         case LEFT_OP:
                 fprintf(outfile,"LEFT_SHIFT (%p) type (",tree);
                 printTypeChain(tree->ftype,outfile);