oops, needed dname==TRUE in my last update
[fw/sdcc] / src / ds390 / gen.c
index a718ba178ffd7c226e0cdd8266d8a428c19e5c4e..9eecde6d7f0920b285ae3c8ab1fca8cd3d59b8fd 100644 (file)
@@ -602,14 +602,14 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
     }
 
   /* special case for a function */
-  if (IS_FUNC (sym->type))
+  if (IS_FUNC (sym->type) && !(sym->isitmp))
     {
       sym->aop = aop = newAsmop (AOP_IMMD);
-      aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);  
+      aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
       aop->size = FPTRSIZE;
       return aop;
     }
-  
+
   /* only remaining is far space */
   /* in which case DPTR gets the address */
   sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
@@ -4000,7 +4000,7 @@ genPlus (iCode * ic)
   if ( AOP_IS_STR(IC_LEFT(ic)) &&
       isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
       aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
-      size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
+      size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
       if (size <= 9) {
          while (size--) emitcode ("inc","dptr");
       } else {
@@ -4586,7 +4586,7 @@ genMultOneByte (operand * left,
 
   /* if literal */
   if (AOP_TYPE(right)==AOP_LIT) {
-    signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
+    signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
     /* AND literal negative */
     if ((int) val < 0) {
       emitcode ("cpl", "F0"); // complement sign flag
@@ -4667,7 +4667,7 @@ static void genMultTwoByte (operand *left, operand *right,
        if (!umult) {
                emitcode("clr","F0");
                if (AOP_TYPE(right) == AOP_LIT) {
-                       int val=floatFromVal (AOP (right)->aopu.aop_lit);
+                       int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
                        if (val < 0) {
                                emitcode("setb","F0");
                                val = -val;
@@ -5010,7 +5010,7 @@ static void genDivTwoByte (operand *left, operand *right,
        /* load up MB with right */
        if (!umult) {
                if (AOP_TYPE(right) == AOP_LIT) {
-                       int val=floatFromVal (AOP (right)->aopu.aop_lit);
+                       int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
                        if (val < 0) {
                                lbl = newiTempLabel(NULL);
                                emitcode ("jbc","F0,!tlabel",lbl->key+100);
@@ -5267,7 +5267,7 @@ static void genModTwoByte (operand *left, operand *right,
        /* load up MB with right */
        if (!umult) {
                if (AOP_TYPE(right) == AOP_LIT) {
-                       int val=floatFromVal (AOP (right)->aopu.aop_lit);
+                       int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
                        if (val < 0) {
                                val = -val;
                        } 
@@ -8972,6 +8972,150 @@ release:
   freeAsmop (result, NULL, ic, TRUE);
 }
 
+
+/*-----------------------------------------------------------------*/
+/* emitPtrByteGet - emits code to get a byte into A through a      */
+/*                  pointer register (R0, R1, or DPTR). The        */
+/*                  original value of A can be preserved in B.     */
+/*-----------------------------------------------------------------*/
+static void
+emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
+{
+  switch (p_type)
+    {
+    case IPOINTER:
+    case POINTER:
+      if (preserveAinB)
+        emitcode ("mov", "b,a");
+      emitcode ("mov", "a,@%s", rname);
+      break;
+
+    case PPOINTER:
+      if (preserveAinB)
+        emitcode ("mov", "b,a");
+      emitcode ("movx", "a,@%s", rname);
+      break;
+      
+    case FPOINTER:
+      if (preserveAinB)
+        emitcode ("mov", "b,a");
+      emitcode ("movx", "a,@dptr");
+      break;
+
+    case CPOINTER:
+      if (preserveAinB)
+        emitcode ("mov", "b,a");
+      emitcode ("clr", "a");
+      emitcode ("movc", "a,@a+dptr");
+      break;
+
+    case GPOINTER:
+      if (preserveAinB)
+        {
+          emitcode ("push", "b");
+          emitcode ("push", "acc");
+        }
+      emitcode ("lcall", "__gptrget");
+      if (preserveAinB)
+        emitcode ("pop", "b");
+      break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* emitPtrByteSet - emits code to set a byte from src through a    */
+/*                  pointer register (R0, R1, or DPTR).            */
+/*-----------------------------------------------------------------*/
+static void
+emitPtrByteSet (char *rname, int p_type, char *src)
+{
+  switch (p_type)
+    {
+    case IPOINTER:
+    case POINTER:
+      if (*src=='@')
+        {
+          MOVA (src);
+          emitcode ("mov", "@%s,a", rname);
+        }
+      else
+        emitcode ("mov", "@%s,%s", rname, src);
+      break;
+
+    case PPOINTER:
+      MOVA (src);
+      emitcode ("movx", "@%s,a", rname);
+      break;
+      
+    case FPOINTER:
+      MOVA (src);
+      emitcode ("movx", "@dptr,a");
+      break;
+
+    case GPOINTER:
+      MOVA (src);
+      emitcode ("lcall", "__gptrput");
+      break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genUnpackBits - generates code for unpacking bits               */
+/*-----------------------------------------------------------------*/
+static void
+genUnpackBits (operand * result, char *rname, int ptype)
+{
+  int offset = 0;      /* result byte offset */
+  int rsize;           /* result size */
+  int rlen = 0;                /* remaining bitfield length */
+  sym_link *etype;     /* bitfield type information */
+  int blen;            /* bitfield length */
+  int bstr;            /* bitfield starting bit within byte */
+
+  D(emitcode (";     genUnpackBits",""));
+
+  etype = getSpec (operandType (result));
+  rsize = getSize (operandType (result));
+  blen = SPEC_BLEN (etype);
+  bstr = SPEC_BSTR (etype);
+
+  /* If the bitfield length is less than a byte */
+  if (blen < 8)
+    {
+      emitPtrByteGet (rname, ptype, FALSE);
+      AccRsh (bstr);
+      emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
+      aopPut (AOP (result), "a", offset++);
+      goto finish;
+    }
+
+  /* Bit field did not fit in a byte. Copy all
+     but the partial byte at the end.  */
+  for (rlen=blen;rlen>=8;rlen-=8)
+    {
+      emitPtrByteGet (rname, ptype, FALSE);
+      aopPut (AOP (result), "a", offset++);
+      if (rlen>8)
+        emitcode ("inc", "%s", rname);
+    }
+
+  /* Handle the partial byte at the end */
+  if (rlen)
+    {
+      emitPtrByteGet (rname, ptype, FALSE);
+      emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
+      aopPut (AOP (result), "a", offset++);
+    }
+
+finish:
+  if (offset < rsize)
+    {
+      rsize -= offset;
+      while (rsize--)
+       aopPut (AOP (result), zero, offset++);
+    }
+}
+#if 0
 /*-----------------------------------------------------------------*/
 /* genUnpackBits - generates code for unpacking bits               */
 /*-----------------------------------------------------------------*/
@@ -8979,13 +9123,15 @@ static void
 genUnpackBits (operand * result, char *rname, int ptype)
 {
   int shCnt;
-  int rlen;
+  int rlen = 0;
   sym_link *etype;
   int offset = 0;
+  int rsize;
 
   D (emitcode (";", "genUnpackBits "););
 
   etype = getSpec (operandType (result));
+  rsize = getSize (operandType (result));
 
   /* read the first byte  */
   switch (ptype)
@@ -9025,12 +9171,12 @@ genUnpackBits (operand * result, char *rname, int ptype)
 
       emitcode ("anl", "a,#!constbyte",
                ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
-      aopPut (AOP (result), "a", offset);
-      return;
+      aopPut (AOP (result), "a", offset++);
+      goto finish;
     }
 
   /* bit field did not fit in a byte  */
-  rlen = SPEC_BLEN (etype) - 8;
+  rlen = SPEC_BLEN (etype);
   aopPut (AOP (result), "a", offset++);
 
   while (1)
@@ -9077,12 +9223,19 @@ genUnpackBits (operand * result, char *rname, int ptype)
 
   if (rlen)
     {
-      emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen));
-      aopPut (AOP (result), "a", offset);
+      emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
+      aopPut (AOP (result), "a", offset++);
     }
 
-  return;
+finish:
+  if (offset < rsize)
+    {
+      rsize -=offset;
+      while (rsize--)
+        aopPut (AOP (result), zero, offset++);
+    }
 }
+#endif
 
 
 /*-----------------------------------------------------------------*/
@@ -9760,6 +9913,134 @@ genPackBits (sym_link * etype,
             operand * right,
             char *rname, int p_type)
 {
+  int offset = 0;      /* source byte offset */
+  int rlen = 0;                /* remaining bitfield length */
+  int blen;            /* bitfield length */
+  int bstr;            /* bitfield starting bit within byte */
+  int litval;          /* source literal value (if AOP_LIT) */
+  unsigned char mask;  /* bitmask within current byte */
+
+  D(emitcode (";     genPackBits",""));
+
+  blen = SPEC_BLEN (etype);
+  bstr = SPEC_BSTR (etype);
+
+  /* If the bitfield length is less than a byte */
+  if (blen < 8)
+    {
+      mask = ((unsigned char) (0xFF << (blen + bstr)) |
+             (unsigned char) (0xFF >> (8 - bstr)));
+
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          /* Case with a bitfield length <8 and literal source
+          */
+          litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+          litval <<= bstr;
+          litval &= (~mask) & 0xff;
+          emitPtrByteGet (rname, p_type, FALSE);
+          if ((mask|litval)!=0xff)
+            emitcode ("anl","a,#!constbyte", mask);
+          if (litval)
+            emitcode ("orl","a,#!constbyte", litval);
+        }
+      else
+        {
+          if ((blen==1) && (p_type!=GPOINTER))
+            {
+              /* Case with a bitfield length == 1 and no generic pointer
+              */
+              if (AOP_TYPE (right) == AOP_CRY)
+                emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
+              else
+                {
+                  MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+                  emitcode ("rrc","a");
+                }
+              emitPtrByteGet (rname, p_type, FALSE);
+              emitcode ("mov","acc.%d,c",bstr);
+            }
+          else
+            {
+              /* Case with a bitfield length < 8 and arbitrary source
+              */
+              MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+              /* shift and mask source value */
+              AccLsh (bstr);
+              emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
+
+             /* transfer A to B and get next byte */
+              emitPtrByteGet (rname, p_type, TRUE);
+
+              emitcode ("anl", "a,#!constbyte", mask);
+              emitcode ("orl", "a,b");
+              if (p_type == GPOINTER)
+                emitcode ("pop", "b");
+           }
+        }
+
+      emitPtrByteSet (rname, p_type, "a");
+      return;
+    }
+
+  /* Bit length is greater than 7 bits. In this case, copy  */
+  /* all except the partial byte at the end                 */
+  for (rlen=blen;rlen>=8;rlen-=8)
+    {
+      emitPtrByteSet (rname, p_type, 
+                      aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
+      if (rlen>8)
+        emitcode ("inc", "%s", rname);
+    }
+
+  /* If there was a partial byte at the end */
+  if (rlen)
+    {
+      mask = (((unsigned char) -1 << rlen) & 0xff);
+      
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          /* Case with partial byte and literal source
+          */
+          litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+          litval >>= (blen-rlen);
+          litval &= (~mask) & 0xff;
+          emitPtrByteGet (rname, p_type, FALSE);
+          if ((mask|litval)!=0xff)
+            emitcode ("anl","a,#!constbyte", mask);
+          if (litval)
+            emitcode ("orl","a,#!constbyte", litval);
+        }
+      else
+        {
+          /* Case with partial byte and arbitrary source
+          */
+          MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
+          emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
+
+         /* transfer A to B and get next byte */
+          emitPtrByteGet (rname, p_type, TRUE);
+
+          emitcode ("anl", "a,#!constbyte", mask);
+          emitcode ("orl", "a,b");
+          if (p_type == GPOINTER)
+            emitcode ("pop", "b");
+        }
+      emitPtrByteSet (rname, p_type, "a");
+    }
+
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* genPackBits - generates code for packed bit storage             */
+/*-----------------------------------------------------------------*/
+static void
+genPackBits (sym_link * etype,
+            operand * right,
+            char *rname, int p_type)
+{
+  int shCount = 0;
   int offset = 0;
   int rLen;
   int blen, bstr;
@@ -9774,12 +10055,17 @@ genPackBits (sym_link * etype,
   /* it exactly fits a byte then         */
   if (SPEC_BLEN (etype) <= 8)
     {
+      unsigned char mask = ((unsigned char) (0xFF << (blen + bstr)) |
+                            (unsigned char) (0xFF >> (8 - bstr)));
+      shCount = SPEC_BSTR (etype);
+      
       /* shift left acc */
-      AccLsh (SPEC_BSTR (etype));
+      AccLsh (shCount);
 
       if (SPEC_BLEN (etype) < 8)
        {                       /* if smaller than a byte */
 
+          emitcode ("anl", "a,#0x%02x", (~mask) & 0xff);
 
          switch (p_type)
            {
@@ -9801,9 +10087,7 @@ genPackBits (sym_link * etype,
              break;
            }
 
-         emitcode ("anl", "a,#!constbyte", (unsigned char)
-                   ((unsigned char) (0xFF << (blen + bstr)) |
-                    (unsigned char) (0xFF >> (8 - bstr))));
+         emitcode ("anl", "a,#!constbyte", mask);
          emitcode ("orl", "a,b");
          if (p_type == GPOINTER)
            emitcode ("pop", "b");
@@ -9872,6 +10156,9 @@ genPackBits (sym_link * etype,
   /* last last was not complete */
   if (rLen)
     {
+      emitcode ("anl", "a,#!constbyte",
+                (~(((unsigned char) -1 << rLen) & 0xff)) & 0xff);
+
       /* save the byte & read byte */
       switch (p_type)
        {
@@ -9893,7 +10180,7 @@ genPackBits (sym_link * etype,
          break;
        }
 
-      emitcode ("anl", "a,#!constbyte", ((unsigned char) -1 << rLen));
+      emitcode ("anl", "a,#!constbyte", (((unsigned char) -1 << rLen) & 0xff));
       emitcode ("orl", "a,b");
     }
 
@@ -9916,6 +10203,8 @@ genPackBits (sym_link * etype,
       break;
     }
 }
+#endif
+
 /*-----------------------------------------------------------------*/
 /* genDataPointerSet - remat pointer to data space                 */
 /*-----------------------------------------------------------------*/