oops, needed dname==TRUE in my last update
[fw/sdcc] / src / ds390 / gen.c
index d417b07fc9afe1de751f7ed6112b74f7b547de3f..9eecde6d7f0920b285ae3c8ab1fca8cd3d59b8fd 100644 (file)
@@ -518,14 +518,20 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
        if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
            if (useDP2) {
                if (options.model == MODEL_FLAT24)
-                   emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
-               TR_DPTR("#2");
+               {
+                   emitcode ("mov", "dpx1,#!constbyte",
+                             (options.stack_loc >> 16) & 0xff);
+               }
                emitcode ("mov", "dph1,_bpx+1");
+               
                emitcode ("mov", "dpl1,_bpx");
                emitcode ("mov","dps,#1");
            } else {
                if (options.model == MODEL_FLAT24)
-                   emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
+               {
+                   emitcode ("mov", "dpx,#!constbyte",
+                             (options.stack_loc >> 16) & 0xff);
+               }
                emitcode ("mov", "dph,_bpx+1");
                emitcode ("mov", "dpl,_bpx");
            }
@@ -551,13 +557,18 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
            emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
            if (useDP2) {
                if (options.model == MODEL_FLAT24)
-                   emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
-               TR_DPTR("#2");
+               {
+                   emitcode ("mov", "dpx1,#!constbyte",
+                             (options.stack_loc >> 16) & 0xff);
+               }
                emitcode ("mov", "dph1,a");
                emitcode ("mov", "dpl1,b");
            } else {
                if (options.model == MODEL_FLAT24)
-                   emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
+               {
+                   emitcode ("mov", "dpx,#!constbyte",
+                             (options.stack_loc >> 16) & 0xff);
+               }
                emitcode ("mov", "dph,a");
                emitcode ("mov", "dpl,b");
            }
@@ -591,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));
@@ -2034,8 +2045,8 @@ saveRegisters (iCode * lic)
 
   /* if the registers have been saved already then
      do nothing */
-  if (ic->regsSaved || 
-      (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))))
+  if (ic->regsSaved 
+      || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
     return ;
 
   /* special case if DPTR alive across a function call then must save it 
@@ -2510,6 +2521,18 @@ static void genSend(set *sendSet)
     }
 }
 
+static void
+adjustEsp(const char *reg)
+{
+    emitcode ("anl","%s,#3", reg);
+    if (TARGET_IS_DS400)
+    {
+       emitcode ("orl","%s,#!constbyte",
+                 reg,
+                 (options.stack_loc >> 8) & 0xff);
+    }
+}
+
 /*-----------------------------------------------------------------*/
 /* genCall - generates a call statement                            */
 /*-----------------------------------------------------------------*/
@@ -2526,7 +2549,7 @@ genCall (iCode * ic)
      the same register bank then we need to save the
      destination registers on the stack */
   dtype = operandType (IC_LEFT (ic));
-  if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
+  if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
       IFFUNC_ISISR (currFunc->type))
   {
@@ -2635,7 +2658,7 @@ genCall (iCode * ic)
              emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
              emitcode ("mov","sp,a");
              emitcode ("mov","a,esp");
-             emitcode ("anl","a,#3");
+             adjustEsp("a");
              emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
              emitcode ("mov","esp,a");   
              UNPROTECT_SP;
@@ -2682,7 +2705,7 @@ genPcall (iCode * ic)
      the same register bank then we need to save the
      destination registers on the stack */
   dtype = operandType (IC_LEFT (ic));
-  if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
+  if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
       IFFUNC_ISISR (currFunc->type) &&
       (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
     saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
@@ -2753,7 +2776,7 @@ genPcall (iCode * ic)
              emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
              emitcode ("mov","sp,a");
              emitcode ("mov","a,esp");
-             emitcode ("anl","a,#3");
+             adjustEsp("a");
              emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
              emitcode ("mov","esp,a");   
              UNPROTECT_SP;
@@ -2809,22 +2832,22 @@ resultRemat (iCode * ic)
 /*-----------------------------------------------------------------*/
 /* inExcludeList - return 1 if the string is in exclude Reg list   */
 /*-----------------------------------------------------------------*/
+static int
+regsCmp(void *p1, void *p2)
+{
+  return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
+}
+
 static bool
 inExcludeList (char *s)
 {
-  int i = 0;
+  const char *p = setFirstItem(options.excludeRegsSet);
 
-  if (options.excludeRegs[i] &&
-      STRCASECMP (options.excludeRegs[i], "none") == 0)
+  if (p == NULL || STRCASECMP(p, "none") == 0)
     return FALSE;
 
-  for (i = 0; options.excludeRegs[i]; i++)
-    {
-      if (options.excludeRegs[i] &&
-         STRCASECMP (s, options.excludeRegs[i]) == 0)
-       return TRUE;
-    }
-  return FALSE;
+
+  return isinSetWith(options.excludeRegsSet, s, regsCmp);
 }
 
 /*-----------------------------------------------------------------*/
@@ -3080,7 +3103,7 @@ genFunction (iCode * ic)
          emitcode ("push","_bpx+1");
          emitcode ("mov","_bpx,%s",spname);
          emitcode ("mov","_bpx+1,esp");
-         emitcode ("anl","_bpx+1,#3");
+         adjustEsp("_bpx+1");
       } else {
          if (options.useXstack) {
              emitcode ("mov", "r0,%s", spname);
@@ -3109,7 +3132,7 @@ genFunction (iCode * ic)
              emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
              emitcode ("mov","sp,a");
              emitcode ("mov","a,esp");
-             emitcode ("anl","a,#3");
+             adjustEsp("a");
              emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
              emitcode ("mov","esp,a");
              UNPROTECT_SP;
@@ -3812,11 +3835,21 @@ bool aopOp3(iCode * ic)
 //            AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
 //            AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
 //            AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
-//      );      
-
+//      );
     
-    // Right uses DPTR unless left or result is an AOP_STR.
-    aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
+    // Right uses DPTR unless left or result is an AOP_STR; however,
+    // if right is an AOP_STR, it must use DPTR regardless.
+    if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
+     && !AOP_IS_STR(IC_RIGHT(ic)))
+    {
+       useDp2 = TRUE;
+    }
+    else
+    {
+       useDp2 = FALSE;
+    }
+       
+    aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
     
     // if the right used DPTR, left MUST use DPTR2.
     // if the right used DPTR2, left MUST use DPTR.
@@ -3967,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 {
@@ -4553,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
@@ -4634,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;
@@ -4977,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);
@@ -5234,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;
                        } 
@@ -7896,8 +7929,6 @@ shiftR2Left2Result (operand * left, int offl,
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
 /*-----------------------------------------------------------------*/
 /* shiftLLeftOrResult - shift left one byte from left, or to result */
 /*-----------------------------------------------------------------*/
@@ -7914,7 +7945,6 @@ shiftLLeftOrResult (operand * left, int offl,
   /* back to result */
   aopPut (AOP (result), "a", offr);
 }
-#endif
 
 #if 0
 //REMOVE ME!!!
@@ -8449,8 +8479,6 @@ genrshTwo (operand * result, operand * left,
 }
 #endif
 
-#if 0
-//REMOVE ME!!!
 /*-----------------------------------------------------------------*/
 /* shiftRLong - shift right one long from left to result           */
 /* offl = LSB or MSB16                                             */
@@ -8466,7 +8494,7 @@ shiftRLong (operand * left, int offl,
     werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
   }
 
-  MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
+  MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
   
   if (offl==MSB16) {
     // shift is > 8
@@ -8474,7 +8502,7 @@ shiftRLong (operand * left, int offl,
       emitcode ("rlc", "a");
       emitcode ("subb", "a,acc");
       emitcode ("xch", "a,%s",
-               aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
+               aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
     } else {
       aopPut (AOP(result), zero, MSB32);
     }
@@ -8490,34 +8518,31 @@ shiftRLong (operand * left, int offl,
 
   if (isSameRegs && offl==MSB16) {
     emitcode ("xch",
-             "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
+             "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
   } else {
     aopPut (AOP (result), "a", MSB32);
-    MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
+    MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
   }
 
   emitcode ("rrc", "a");
   if (isSameRegs && offl==1) {
     emitcode ("xch", "a,%s",
-             aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
+             aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
   } else {
     aopPut (AOP (result), "a", MSB24);
-    MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
+    MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
   }
   emitcode ("rrc", "a");
   aopPut (AOP (result), "a", MSB16 - offl);
 
   if (offl == LSB)
     {
-      MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
+      MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
       emitcode ("rrc", "a");
       aopPut (AOP (result), "a", LSB);
     }
 }
-#endif
 
-#if 0
-//REMOVE ME!!!
 /*-----------------------------------------------------------------*/
 /* genrshFour - shift four byte by a known amount != 0             */
 /*-----------------------------------------------------------------*/
@@ -8525,22 +8550,24 @@ static void
 genrshFour (operand * result, operand * left,
            int shCount, int sign)
 {
-  D (emitcode (";", "genrshFour");
-    );
+  D (emitcode (";", "genrshFour"););
 
   /* if shifting more that 3 bytes */
   if (shCount >= 24)
     {
       shCount -= 24;
+      _startLazyDPSEvaluation();
       if (shCount)
        shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
       else
        movLeft2Result (left, MSB32, result, LSB, sign);
       addSign (result, MSB16, sign);
+      _endLazyDPSEvaluation();
     }
   else if (shCount >= 16)
     {
       shCount -= 16;
+      _startLazyDPSEvaluation();
       if (shCount)
        shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
       else
@@ -8549,12 +8576,16 @@ genrshFour (operand * result, operand * left,
          movLeft2Result (left, MSB32, result, MSB16, sign);
        }
       addSign (result, MSB24, sign);
+      _endLazyDPSEvaluation();
     }
   else if (shCount >= 8)
     {
       shCount -= 8;
+      _startLazyDPSEvaluation();
       if (shCount == 1)
-       shiftRLong (left, MSB16, result, sign);
+       {
+           shiftRLong (left, MSB16, result, sign);
+       }
       else if (shCount == 0)
        {
          movLeft2Result (left, MSB16, result, LSB, 0);
@@ -8570,9 +8601,11 @@ genrshFour (operand * result, operand * left,
          shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
          addSign (result, MSB32, sign);
        }
+       _endLazyDPSEvaluation();
     }
   else
-    {                          /* 1 <= shCount <= 7 */
+    {  
+       /* 1 <= shCount <= 7 */
       if (shCount <= 2)
        {
          shiftRLong (left, LSB, result, sign);
@@ -8587,7 +8620,6 @@ genrshFour (operand * result, operand * left,
        }
     }
 }
-#endif
 
 #ifdef BETTER_LITERAL_SHIFT
 /*-----------------------------------------------------------------*/
@@ -8611,7 +8643,8 @@ genRightShiftLiteral (operand * left,
   if ((shCount != 0)
    && (shCount < (size * 8))
    && (size != 1)
-   && (size != 2))
+   && (size != 2)
+   && (size != 4))
   {
       D(emitcode (";", "genRightShiftLiteral wimping out"););  
       return FALSE;
@@ -8660,7 +8693,7 @@ genRightShiftLiteral (operand * left,
        case 2:
          genrshTwo (result, left, shCount, sign);
          break;
-#if 0
+#if 1
        case 4:
          genrshFour (result, left, shCount, sign);
          break;
@@ -8939,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               */
 /*-----------------------------------------------------------------*/
@@ -8946,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)
@@ -8992,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)
@@ -9044,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
 
 
 /*-----------------------------------------------------------------*/
@@ -9727,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;
@@ -9741,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)
            {
@@ -9768,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");
@@ -9839,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)
        {
@@ -9860,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");
     }
 
@@ -9883,6 +10203,8 @@ genPackBits (sym_link * etype,
       break;
     }
 }
+#endif
+
 /*-----------------------------------------------------------------*/
 /* genDataPointerSet - remat pointer to data space                 */
 /*-----------------------------------------------------------------*/
@@ -10499,6 +10821,8 @@ genAddrOf (iCode * ic)
       /* if 10 bit stack */
       if (options.stack10bit) {
          char buff[10];
+         int  offset;
+         
          tsprintf(buff, sizeof(buff), 
                   "#!constbyte",(options.stack_loc >> 16) & 0xff);
          /* if it has an offset then we need to compute it */
@@ -10517,9 +10841,13 @@ genAddrOf (iCode * ic)
                                             ((char) sym->stack )) & 0xff);
              emitcode ("mov", "b,a");
              emitcode ("mov", "a,_bpx+1");
-             emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ? 
-                                             ((short) (sym->stack - _G.nRegsSaved)) :
-                                             ((short) sym->stack )) >> 8) & 0xff);
+             
+             offset = (((sym->stack < 0) ? 
+                        ((short) (sym->stack - _G.nRegsSaved)) :
+                        ((short) sym->stack )) >> 8) & 0xff;
+         
+             emitcode ("addc","a,#!constbyte", offset);
+
              aopPut (AOP (IC_RESULT (ic)), "b", 0);
              aopPut (AOP (IC_RESULT (ic)), "a", 1);
              aopPut (AOP (IC_RESULT (ic)), buff, 2);
@@ -10593,6 +10921,7 @@ release:
 
 }
 
+#if 0 // obsolete, and buggy for != xdata
 /*-----------------------------------------------------------------*/
 /* genArrayInit - generates code for address of                       */
 /*-----------------------------------------------------------------*/
@@ -10701,6 +11030,7 @@ genArrayInit (iCode * ic)
     
     freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* genFarFarAssign - assignment when both are in far space         */
@@ -11150,7 +11480,7 @@ genCast (iCode * ic)
   /* also, if the source is a bit, we don't need to sign extend, because
    * it can't possibly have set the sign bit.
    */
-  if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
+  if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
     {
       while (size--)
        {
@@ -12563,6 +12893,42 @@ static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *na
        }
 }
 
+/*-----------------------------------------------------------------*/
+/* genDummyRead - generate code for dummy read of volatiles        */
+/*-----------------------------------------------------------------*/
+static void
+genDummyRead (iCode * ic)
+{
+  operand *right;
+  int size, offset;
+
+  D(emitcode(";     genDummyRead",""));
+
+  right = IC_RIGHT (ic);
+
+  aopOp (right, ic, FALSE, FALSE);
+
+  /* if the result is a bit */
+  if (AOP_TYPE (right) == AOP_CRY)
+    {
+      emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
+      goto release;
+    }
+
+  /* bit variables done */
+  /* general case */
+  size = AOP_SIZE (right);
+  offset = 0;
+  while (size--)
+    {
+      emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
+      offset++;
+    }
+
+release:
+  freeAsmop (right, NULL, ic, TRUE);
+}
+
 /*-----------------------------------------------------------------*/
 /* genBuiltIn - calls the appropriate function to  generating code */
 /* for a built in function                                        */
@@ -12932,9 +13298,15 @@ gen390Code (iCode * lic)
          else addSet (&_G.sendSet, ic);
          break;
 
+       case DUMMY_READ_VOLATILE:
+         genDummyRead (ic);
+         break;
+
+#if 0 // obsolete, and buggy for != xdata
        case ARRAYINIT:
            genArrayInit(ic);
            break;
+#endif
            
        default:
          ic = ic;