+
+/*-----------------------------------------------------------------*/
+/* genPackBits - generates code for packed bit storage */
+/*-----------------------------------------------------------------*/
+static void
+genPackBits (sym_link * etype,
+ operand * right,
+ int pair,
+ iCode *ic)
+{
+ 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 */
+ int extraPair; /* a tempory register */
+ bool needPopExtra=0; /* need to restore original value of temp reg */
+
+ emitDebug ("; 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;
+ emit2 ("ld a,!*pair", _pairs[pair].name);
+ if ((mask|litval)!=0xff)
+ emit2 ("and a,!immedbyte", mask);
+ if (litval)
+ emit2 ("or a,!immedbyte", litval);
+ emit2 ("ld !*pair,a", _pairs[pair].name);
+ return;
+ }
+ else
+ {
+ /* Case with a bitfield length <8 and arbitrary source
+ */
+ _moveA (aopGet (AOP (right), 0, FALSE));
+ /* shift and mask source value */
+ AccLsh (bstr);
+ emit2 ("and a,!immedbyte", (~mask) & 0xff);
+
+ extraPair = getFreePairId(ic);
+ if (extraPair == PAIR_INVALID)
+ {
+ extraPair = PAIR_BC;
+ if (getPairId (AOP (right)) != PAIR_BC
+ || !isLastUse (ic, right))
+ {
+ _push (extraPair);
+ needPopExtra = 1;
+ }
+ }
+ emit2 ("ld %s,a", _pairs[extraPair].l);
+ emit2 ("ld a,!*pair", _pairs[pair].name);
+
+ emit2 ("and a,!immedbyte", mask);
+ emit2 ("or a,%s", _pairs[extraPair].l);
+ emit2 ("ld !*pair,a", _pairs[pair].name);
+ if (needPopExtra)
+ _pop (extraPair);
+ 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)
+ {
+ emit2 ("ld a,%s", aopGet (AOP (right), offset++, FALSE) );
+ emit2 ("ld !*pair,a", _pairs[pair].name);
+ if (rlen>8)
+ {
+ emit2 ("inc %s", _pairs[pair].name);
+ _G.pairs[pair].offset++;
+ }
+ }
+
+ /* 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;
+ emit2 ("ld a,!*pair", _pairs[pair].name);
+ if ((mask|litval)!=0xff)
+ emit2 ("and a,!immedbyte", mask);
+ if (litval)
+ emit2 ("or a,!immedbyte", litval);
+ }
+ else
+ {
+ /* Case with partial byte and arbitrary source
+ */
+ _moveA (aopGet (AOP (right), offset++, FALSE));
+ emit2 ("and a,!immedbyte", (~mask) & 0xff);
+
+ extraPair = getFreePairId(ic);
+ if (extraPair == PAIR_INVALID)
+ {
+ extraPair = getPairId (AOP (right));
+ if (!isLastUse (ic, right) || (extraPair == PAIR_INVALID))
+ extraPair = PAIR_BC;
+
+ if (getPairId (AOP (right)) != PAIR_BC
+ || !isLastUse (ic, right))
+ {
+ _push (extraPair);
+ needPopExtra = 1;
+ }
+ }
+ emit2 ("ld %s,a", _pairs[extraPair].l);
+ emit2 ("ld a,!*pair", _pairs[pair].name);
+
+ emit2 ("and a,!immedbyte", mask);
+ emit2 ("or a,%s", _pairs[extraPair].l);
+ if (needPopExtra)
+ _pop (extraPair);
+
+ }
+ emit2 ("ld !*pair,a", _pairs[pair].name);
+ }
+}
+
+