a better constant to type check
[fw/sdcc] / src / mcs51 / gen.c
index fe322b0ae9cb16a00fcfb8ba9ffbfa17c92a91b4..38c60a98bc3c590a9a716fd5a01045abae92079c 100644 (file)
@@ -28,6 +28,9 @@
       Made everything static
 -------------------------------------------------------------------------*/
 
+#define D(x)
+//#define D(x) x
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -41,7 +44,7 @@
 #ifdef HAVE_ENDIAN_H
 #include <endian.h>
 #else
-#if !defined(__BORLANDC__) && !defined(_MSC_VER)
+#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
@@ -162,9 +165,9 @@ getFreePtr (iCode * ic, asmop ** aopp, bool result)
 
   /* first check if r0 & r1 are used by this
      instruction, in which case we are in trouble */
-  if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
-      (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
-    {
+  r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
+  r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
+  if (r0iu && r1iu) {
       goto endOfWorld;
     }
 
@@ -236,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);
 }
 
 /*-----------------------------------------------------------------*/
@@ -270,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)
@@ -552,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)
     {
@@ -589,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++)
@@ -846,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                                */
@@ -860,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 */
@@ -905,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)
@@ -1031,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);
     }
 
 }
@@ -1611,6 +1619,8 @@ genIpush (iCode * ic)
   int size, offset = 0;
   char *l;
 
+  D(emitcode (";", "genIpush"));
+
   /* if this is not a parm push : ie. it is spill push
      and spill push is always done on the local stack */
   if (!ic->parmPush)
@@ -1839,6 +1849,7 @@ genCall (iCode * ic)
   bool restoreBank = FALSE;
   bool swapBanks = FALSE;
 
+  D(emitcode(";", "genCall"));
   /* if send set is not empty the assign */
   if (_G.sendSet)
     {
@@ -2509,8 +2520,8 @@ genEndFunction (iCode * ic)
        emitcode ("setb", "ea");
 
       /* if debug then send end of function */
-/*  if (options.debug && currFunc)  */
-      if (currFunc)
+      /*  if (options.debug && currFunc)  */
+      if (options.debug && currFunc)
        {
          _G.debugLine = 1;
          emitcode ("", "C$%s$%d$%d$%d ==.",
@@ -2549,7 +2560,7 @@ genEndFunction (iCode * ic)
        }
 
       /* if debug then send end of function */
-      if (currFunc)
+      if (options.debug && currFunc)
        {
          _G.debugLine = 1;
          emitcode ("", "C$%s$%d$%d$%d ==.",
@@ -3240,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++);
     }
@@ -3339,9 +3355,9 @@ genMultOneByte (operand * left,
     /* AND literal negative */
     if (val < 0) {
       emitcode ("cpl", "F0"); // complement sign flag
-      emitcode ("mov", "b,#%02x", -val);
+      emitcode ("mov", "b,#0x%02x", -val);
     } else {
-      emitcode ("mov", "b,#%02x", val);
+      emitcode ("mov", "b,#0x%02x", val);
     }
   } else {
     lbl=newiTempLabel(NULL);
@@ -4202,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;
@@ -4592,9 +4608,20 @@ genAnd (iCode * ic, iCode * ifx)
            emitcode ("setb", "c");
          while (sizer--)
            {
-             MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
-             emitcode ("anl", "a,%s",
-                       aopGet (AOP (left), offset, FALSE, FALSE));
+             if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+               emitcode ("anl", "a,%s",
+                         aopGet (AOP (right), offset, FALSE, FALSE));
+             } else {
+               if (AOP_TYPE(left)==AOP_ACC) {
+                 emitcode("mov", "b,a");
+                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
+                 emitcode("anl", "a,b");
+               }else {
+                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
+                 emitcode ("anl", "a,%s",
+                           aopGet (AOP (left), offset, FALSE, FALSE));
+               }
+             }
              emitcode ("jnz", "%05d$", tlbl->key + 100);
              offset++;
            }
@@ -4861,9 +4888,14 @@ genOr (iCode * ic, iCode * ifx)
            emitcode ("setb", "c");
          while (sizer--)
            {
-             MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
-             emitcode ("orl", "a,%s",
-                       aopGet (AOP (left), offset, FALSE, FALSE));
+             if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+               emitcode ("orl", "a,%s",
+                         aopGet (AOP (right), offset, FALSE, FALSE));
+             } else {
+               MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
+               emitcode ("orl", "a,%s",
+                         aopGet (AOP (left), offset, FALSE, FALSE));
+             }
              emitcode ("jnz", "%05d$", tlbl->key + 100);
              offset++;
            }
@@ -5113,9 +5145,14 @@ genXor (iCode * ic, iCode * ifx)
                }
              else
                {
-                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
-                 emitcode ("xrl", "a,%s",
-                           aopGet (AOP (left), offset, FALSE, FALSE));
+                 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+                   emitcode ("xrl", "a,%s",
+                             aopGet (AOP (right), offset, FALSE, FALSE));
+                 } else {
+                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
+                   emitcode ("xrl", "a,%s",
+                             aopGet (AOP (left), offset, FALSE, FALSE));
+                 }
                }
              emitcode ("jnz", "%05d$", tlbl->key + 100);
              offset++;
@@ -5225,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--)
     {
@@ -5242,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);
@@ -5270,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++);
@@ -5290,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);
@@ -6755,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:
@@ -6808,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:
@@ -6920,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))
@@ -7522,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)))
@@ -7991,6 +8041,8 @@ genAssign (iCode * ic)
   int size, offset;
   unsigned long lit = 0L;
 
+  D(emitcode(";","genAssign"));
+
   result = IC_RESULT (ic);
   right = IC_RIGHT (ic);
 
@@ -8125,6 +8177,8 @@ genCast (iCode * ic)
   operand *right = IC_RIGHT (ic);
   int size, offset;
 
+  D(emitcode(";", "genCast"));
+
   /* if they are equivalent then do nothing */
   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
     return;
@@ -8133,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 */
@@ -8278,7 +8333,7 @@ genCast (iCode * ic)
   /* now depending on the sign of the source && destination */
   size = AOP_SIZE (result) - AOP_SIZE (right);
   /* if unsigned or not an integral type */
-  if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
+  if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
     {
       while (size--)
        aopPut (AOP (result), zero, offset++);
@@ -8423,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            */
 /*-----------------------------------------------------------------*/
@@ -8438,8 +8551,8 @@ gen51Code (iCode * lic)
   if (allocInfo)
     printAllocInfo (currFunc, codeOutFile);
   /* if debug information required */
-/*     if (options.debug && currFunc) { */
-  if (currFunc)
+  /*     if (options.debug && currFunc) { */
+  if (options.debug && currFunc)
     {
       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
       _G.debugLine = 1;
@@ -8663,6 +8776,10 @@ gen51Code (iCode * lic)
          addSet (&_G.sendSet, ic);
          break;
 
+       case ARRAYINIT:
+         gen51AggregateAssign(ic);
+         break;
+
        default:
          ic = ic;
        }