a better constant to type check
[fw/sdcc] / src / mcs51 / gen.c
index a141aa6b29c3899ef797b9fec13af9ec1d5fcdea..38c60a98bc3c590a9a716fd5a01045abae92079c 100644 (file)
@@ -44,7 +44,7 @@
 #ifdef HAVE_ENDIAN_H
 #include <endian.h>
 #else
-#if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__)
+#if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
 #endif
@@ -239,7 +239,7 @@ endOfWorld:
   /* other wise this is true end of the world */
   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
          "getFreePtr should never reach here");
-  exit (0);
+  exit (1);
 }
 
 /*-----------------------------------------------------------------*/
@@ -273,7 +273,12 @@ static asmop *
 aopForSym (iCode * ic, symbol * sym, bool result)
 {
   asmop *aop;
-  memmap *space = SPEC_OCLS (sym->etype);
+  memmap *space;
+
+  wassertl (ic != NULL, "Got a null iCode");
+  wassertl (sym != NULL, "Got a null symbol");
+
+  space = SPEC_OCLS (sym->etype);
 
   /* if already has one */
   if (sym->aop)
@@ -555,7 +560,6 @@ aopOp (operand * op, iCode * ic, bool result)
 
   sym = OP_SYMBOL (op);
 
-
   /* if the type is a conditional */
   if (sym->regType == REG_CND)
     {
@@ -592,6 +596,7 @@ aopOp (operand * op, iCode * ic, bool result)
       if (sym->ruonly)
        {
          unsigned i;
+
          aop = op->aop = sym->aop = newAsmop (AOP_STR);
          aop->size = getSize (sym->type);
          for (i = 0; i < fReturnSizeMCS51; i++)
@@ -849,7 +854,7 @@ aopGet (asmop * aop, int offset, bool bit16, bool dname)
 
   werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
          "aopget got unsupported aop->type");
-  exit (0);
+  exit (1);
 }
 /*-----------------------------------------------------------------*/
 /* aopPut - puts a string for a aop                                */
@@ -863,7 +868,7 @@ aopPut (asmop * aop, char *s, int offset)
     {
       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
              "aopPut got offset > aop->size");
-      exit (0);
+      exit (1);
     }
 
   /* will assign value to value */
@@ -908,7 +913,7 @@ aopPut (asmop * aop, char *s, int offset)
        {
          werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
                  "aopPut writting to code space");
-         exit (0);
+         exit (1);
        }
 
       while (offset > aop->coff)
@@ -1006,7 +1011,7 @@ aopPut (asmop * aop, char *s, int offset)
                }
              {
                symbol *lbl = newiTempLabel (NULL);
-               emitcode ("clr", "c; oops");
+               emitcode ("clr", "c");
                emitcode ("jz", "%05d$", lbl->key + 100);
                emitcode ("cpl", "c");
                emitcode ("", "%05d$:", lbl->key + 100);
@@ -1034,7 +1039,7 @@ aopPut (asmop * aop, char *s, int offset)
     default:
       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
              "aopPut got unsupported aop->type");
-      exit (0);
+      exit (1);
     }
 
 }
@@ -3246,12 +3251,17 @@ genMinus (iCode * ic)
       else
        {
          /* first add without previous c */
-         if (!offset)
-           emitcode ("add", "a,#0x%02x",
-                     (unsigned int) (lit & 0x0FFL));
-         else
+         if (!offset) {
+           if (!size && lit==-1) {
+             emitcode ("dec", "a");
+           } else {
+             emitcode ("add", "a,#0x%02x", 
+                       (unsigned int) (lit & 0x0FFL));
+           }
+         } else {
            emitcode ("addc", "a,#0x%02x",
                      (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
+         }
        }
       aopPut (AOP (IC_RESULT (ic)), "a", offset++);
     }
@@ -4208,7 +4218,7 @@ hasInc (operand *op, iCode *ic)
       return lic;
     }
     /* if the operand used or deffed */
-    if (bitVectBitValue(ic->uses,op->key) || (unsigned) ic->defKey == op->key) {
+    if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
       return NULL;
     }
     lic = lic->next;
@@ -5252,6 +5262,12 @@ genRRC (iCode * ic)
   /* move it to the result */
   size = AOP_SIZE (result);
   offset = size - 1;
+  if (size == 1) { /* special case for 1 byte */
+      l = aopGet (AOP (left), offset, FALSE, FALSE);
+      MOVA (l);
+      emitcode ("rr", "a");
+      goto release;
+  }
   CLRC;
   while (size--)
     {
@@ -5269,6 +5285,7 @@ genRRC (iCode * ic)
       MOVA (l);
     }
   emitcode ("mov", "acc.7,c");
+ release:
   aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
   freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (result, NULL, ic, TRUE);
@@ -5297,6 +5314,10 @@ genRLC (iCode * ic)
     {
       l = aopGet (AOP (left), offset, FALSE, FALSE);
       MOVA (l);
+      if (size == 0) { /* special case for 1 byte */
+             emitcode("rl","a");
+             goto release;
+      }
       emitcode ("add", "a,acc");
       if (AOP_SIZE (result) > 1)
        aopPut (AOP (result), "a", offset++);
@@ -5317,6 +5338,7 @@ genRLC (iCode * ic)
       MOVA (l);
     }
   emitcode ("mov", "acc.0,c");
+ release:
   aopPut (AOP (result), "a", 0);
   freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (result, NULL, ic, TRUE);
@@ -6782,7 +6804,7 @@ genUnpackBits (operand * result, char *rname, int ptype)
 
     case CPOINTER:
       emitcode ("clr", "a");
-      emitcode ("movc", "a,%s", "@a+dptr");
+      emitcode ("movc", "a,@a+dptr");
       break;
 
     case GPOINTER:
@@ -6835,7 +6857,7 @@ genUnpackBits (operand * result, char *rname, int ptype)
        case CPOINTER:
          emitcode ("clr", "a");
          emitcode ("inc", "dptr");
-         emitcode ("movc", "a", "@a+dptr");
+         emitcode ("movc", "a,@a+dptr");
          break;
 
        case GPOINTER:
@@ -6947,8 +6969,9 @@ genNearPointerGet (operand * left,
     }
   else
     rname = aopGet (AOP (left), 0, FALSE, FALSE);
-
-  aopOp (result, ic, FALSE);
+  
+  //aopOp (result, ic, FALSE);
+  aopOp (result, ic, result?TRUE:FALSE);
 
   /* if bitfield then unpack the bits */
   if (IS_BITVAR (retype))
@@ -7549,7 +7572,7 @@ genNearPointerSet (operand * right,
       genDataPointerSet (right, result, ic);
       return;
     }
-
+  
   /* if the value is already in a pointer register
      then don't need anything more */
   if (!AOP_INPREG (AOP (result)))
@@ -8164,7 +8187,8 @@ genCast (iCode * ic)
   aopOp (result, ic, FALSE);
 
   /* if the result is a bit */
-  if (AOP_TYPE (result) == AOP_CRY)
+  // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
+  if (IS_BITVAR(OP_SYMBOL(result)->type))
     {
       /* if the right size is a literal then
          we know what the value is */
@@ -8454,6 +8478,64 @@ genReceive (iCode * ic)
   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
 }
 
+/*-----------------------------------------------------------------*/
+/* gen51AggregateAssign - copy complete array's or structures            */
+/*-----------------------------------------------------------------*/
+void gen51AggregateAssign(iCode *ic) {
+  operand *left=IC_LEFT(ic);
+  operand *right=IC_RIGHT(ic);
+  char *fromName=OP_SYMBOL(right)->rname;
+  char *toName=OP_SYMBOL(left)->rname;
+  int fromSize=getSize(OP_SYMBOL(right)->type);
+  int toSize=getSize(OP_SYMBOL(left)->type);
+  int count=toSize;
+
+  if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
+      SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
+    // well, this code isn't used yet from anywhere else as for initialising
+    fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
+    exit (457);
+  }
+
+  if (fromSize!=toSize) {
+    fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
+            ic->filename, ic->lineno);
+    exit (821);
+  }
+
+#if 1
+  // use the generic memcpy() for now
+  emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
+  emitcode ("mov", "dptr,#_memcpy_PARM_2");
+  emitcode ("mov", "a,#%s", fromName);
+  emitcode ("movx", "@dptr,a");
+  emitcode ("inc", "dptr");
+  emitcode ("mov", "a,#(%s>>8)", fromName);
+  emitcode ("movx", "@dptr,a");
+  emitcode ("inc", "dptr");
+  emitcode ("mov", "a,#%02x;   only from cseg for now", 2);
+  emitcode ("movx", "@dptr,a");
+  emitcode ("mov", "dptr,#_memcpy_PARM_3");
+  emitcode ("mov", "a,#(%d>>0);        number of bytes", count);
+  emitcode ("movx", "@dptr,a");
+  emitcode ("inc", "dptr");
+  emitcode ("mov", "a,#(%d>>8)", count);
+  emitcode ("movx", "@dptr,a");
+  emitcode ("mov", "dptr,#%s", toName);
+  emitcode ("mov", "b,#%02x;   only to xseg for now", 1);
+  emitcode ("lcall", "_memcpy");
+#else
+  // more efficient, but will require the native_memcpy_cs2xs
+  emitcode ("mov", "r0,#%s", fromName);
+  emitcode ("mov", "r1,#(%s>>8)", fromName);
+  emitcode ("mov", "r2,#%s", toName);
+  emitcode ("mov", "r3,#(%s>>8)", toName);
+  emitcode ("mov", "r4,#%d", count);
+  emitcode ("mov", "r5,#(%d>>8)", count);
+  emitcode ("lcall", "_native_memcpy_cs2xs");
+#endif
+}
+
 /*-----------------------------------------------------------------*/
 /* gen51Code - generate code for 8051 based controllers            */
 /*-----------------------------------------------------------------*/
@@ -8694,6 +8776,10 @@ gen51Code (iCode * lic)
          addSet (&_G.sendSet, ic);
          break;
 
+       case ARRAYINIT:
+         gen51AggregateAssign(ic);
+         break;
+
        default:
          ic = ic;
        }