From c4864c92486eda75766c5a0d29fe7edd07147e74 Mon Sep 17 00:00:00 2001 From: epetrich Date: Mon, 18 Aug 2003 05:35:47 +0000 Subject: [PATCH] Made bitfield a distinct type from bit so that bitfields convert as per ANSI C and bits retain their traditional boolean style behaviour. Implemented bitfield support in the z80 port. * src/SDCCsymt.h, * src/SDCCsymt.c, * src/SDCCast.c, * src/cdbFile.c, * src/mcs51/gen.c, * src/ds390/gen.c: bit v bitfield split * src/z80/gen.c: New support for bitfields * support/regression/tests/bitfields.c: reenabled z80, added more tests git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2836 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 17 ++ src/SDCCast.c | 3 + src/SDCCsymt.c | 26 ++- src/SDCCsymt.h | 8 +- src/cdbFile.c | 1 + src/ds390/gen.c | 298 +-------------------------- src/mcs51/gen.c | 4 +- src/z80/gen.c | 284 ++++++++++++++++++++++++- support/regression/tests/bitfields.c | 50 ++++- 9 files changed, 373 insertions(+), 318 deletions(-) diff --git a/ChangeLog b/ChangeLog index 54c16bdf..e534f0fd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2003-08-18 Erik Petrich + + Made bitfield a distinct type from bit so that bitfields + convert as per ANSI C and bits retain their traditional + boolean style behaviour. Implemented bitfield support in + the z80 port. + + * src/SDCCsymt.h, + * src/SDCCsymt.c, + * src/SDCCast.c, + * src/cdbFile.c, + * src/mcs51/gen.c, + * src/ds390/gen.c: bit v bitfield split + * src/z80/gen.c: New support for bitfields + * support/regression/tests/bitfields.c: reenabled z80, + added more tests + 2003-08-17 Frieder Ferlemann Rules 246.x, 247.x relate to bitfields, the others speed up diff --git a/src/SDCCast.c b/src/SDCCast.c index 5741a4df..c50f127d 100644 --- a/src/SDCCast.c +++ b/src/SDCCast.c @@ -2994,6 +2994,9 @@ decorateType (ast * tree) case V_STRUCT: typeofv = TYPEOF_STRUCT; break; + case V_BITFIELD: + typeofv = TYPEOF_BITFIELD; + break; case V_BIT: typeofv = TYPEOF_BIT; break; diff --git a/src/SDCCsymt.c b/src/SDCCsymt.c index 3ba40fc6..21341726 100644 --- a/src/SDCCsymt.c +++ b/src/SDCCsymt.c @@ -48,6 +48,7 @@ char *nounName(sym_link *sl) { case V_VOID: return "void"; case V_STRUCT: return "struct"; case V_LABEL: return "label"; + case V_BITFIELD: return "bitfield"; case V_BIT: return "bit"; case V_SBIT: return "sbit"; case V_DOUBLE: return "double"; @@ -754,8 +755,9 @@ getSize (sym_link * p) case V_LABEL: return 0; case V_SBIT: - return BITSIZE; case V_BIT: + return BITSIZE; + case V_BITFIELD: return ((SPEC_BLEN (p) / 8) + (SPEC_BLEN (p) % 8 ? 1 : 0)); default: return 0; @@ -818,8 +820,9 @@ bitsForType (sym_link * p) case V_LABEL: return 0; case V_SBIT: - return 1; case V_BIT: + return 1; + case V_BITFIELD: return SPEC_BLEN (p); default: return 0; @@ -1076,7 +1079,7 @@ compStructSize (int su, structdef * sdef) if (loop->bitVar) { /* change it to a unsigned bit */ - SPEC_NOUN (loop->etype) = V_BIT; + SPEC_NOUN (loop->etype) = V_BITFIELD; SPEC_USIGN (loop->etype) = 1; SPEC_BLEN (loop->etype) = loop->bitVar; @@ -1256,6 +1259,7 @@ checkSClass (symbol * sym, int isProto) if ((IS_ARRAY (sym->type) || IS_PTR (sym->type)) && (SPEC_NOUN (sym->etype) == V_BIT || SPEC_NOUN (sym->etype) == V_SBIT || + SPEC_NOUN (sym->etype) == V_BITFIELD || SPEC_SCLS (sym->etype) == S_SFR)) werror (E_BIT_ARRAY, sym->name); @@ -1985,6 +1989,7 @@ void printTypeChain (sym_link * start, FILE * of) { int nlr = 0; + value *args; sym_link * type, * search; STORAGE_CLASS scls; @@ -2044,6 +2049,15 @@ printTypeChain (sym_link * start, FILE * of) fprintf (of, "function %s %s", (IFFUNC_ISBUILTIN(type) ? "__builtin__" : " "), (IFFUNC_ISJAVANATIVE(type) ? "_JavaNative" : " ")); + fprintf (of, "( "); + for (args = FUNC_ARGS(type); + args; + args=args->next) { + printTypeChain(args->type, of); + if (args->next) + fprintf(of, ", "); + } + fprintf (of, ") "); break; case GPOINTER: fprintf (of, "generic* "); @@ -2115,7 +2129,11 @@ printTypeChain (sym_link * start, FILE * of) break; case V_BIT: - fprintf (of, "bit {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type)); + fprintf (of, "bit"); + break; + + case V_BITFIELD: + fprintf (of, "bitfield {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type)); break; case V_DOUBLE: diff --git a/src/SDCCsymt.h b/src/SDCCsymt.h index 3c8bf447..c41303ed 100644 --- a/src/SDCCsymt.h +++ b/src/SDCCsymt.h @@ -42,6 +42,7 @@ enum { TYPEOF_LONG, TYPEOF_FLOAT, TYPEOF_BIT, + TYPEOF_BITFIELD, TYPEOF_SBIT, TYPEOF_SFR, TYPEOF_VOID, @@ -98,6 +99,7 @@ typedef enum V_STRUCT, V_LABEL, V_BIT, + V_BITFIELD, V_SBIT, V_DOUBLE } @@ -444,10 +446,12 @@ extern sym_link *validateLink(sym_link *l, x->select.d.ptr_volatile) #define IS_INTEGRAL(x) (IS_SPEC(x) && (x->select.s.noun == V_INT || \ x->select.s.noun == V_CHAR || \ + x->select.s.noun == V_BITFIELD || \ x->select.s.noun == V_BIT || \ x->select.s.noun == V_SBIT )) -#define IS_BITFIELD(x) (IS_SPEC(x) && (x->select.s.noun == V_BIT)) -#define IS_BITVAR(x) (IS_SPEC(x) && (x->select.s.noun == V_BIT || \ +#define IS_BITFIELD(x) (IS_SPEC(x) && (x->select.s.noun == V_BITFIELD)) +#define IS_BITVAR(x) (IS_SPEC(x) && (x->select.s.noun == V_BITFIELD || \ + x->select.s.noun == V_BIT || \ x->select.s.noun == V_SBIT )) #define IS_FLOAT(x) (IS_SPEC(x) && x->select.s.noun == V_FLOAT) #define IS_ARITHMETIC(x) (IS_INTEGRAL(x) || IS_FLOAT(x)) diff --git a/src/cdbFile.c b/src/cdbFile.c index d4a34520..ea9e5559 100644 --- a/src/cdbFile.c +++ b/src/cdbFile.c @@ -338,6 +338,7 @@ void cdbTypeInfo (sym_link * type) case V_SBIT: fprintf (cdbFilePtr, "SX"); break; case V_BIT: + case V_BITFIELD: fprintf (cdbFilePtr, "SB%d$%d", SPEC_BSTR (type), SPEC_BLEN (type)); break; diff --git a/src/ds390/gen.c b/src/ds390/gen.c index 9eecde6d..419896b1 100644 --- a/src/ds390/gen.c +++ b/src/ds390/gen.c @@ -9115,127 +9115,6 @@ finish: aopPut (AOP (result), zero, offset++); } } -#if 0 -/*-----------------------------------------------------------------*/ -/* genUnpackBits - generates code for unpacking bits */ -/*-----------------------------------------------------------------*/ -static void -genUnpackBits (operand * result, char *rname, int ptype) -{ - int shCnt; - 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) - { - - case POINTER: - case IPOINTER: - emitcode ("mov", "a,@%s", rname); - break; - - case PPOINTER: - emitcode ("movx", "a,@%s", rname); - break; - - case FPOINTER: - emitcode ("movx", "a,@dptr"); - break; - - case CPOINTER: - emitcode ("clr", "a"); - emitcode ("movc", "a,@a+dptr"); - break; - - case GPOINTER: - emitcode ("lcall", "__gptrget"); - break; - } - - /* if we have bitdisplacement then it fits */ - /* into this byte completely or if length is */ - /* less than a byte */ - if (((shCnt = SPEC_BSTR (etype)) != 0) || (SPEC_BLEN (etype) <= 8)) - { - - /* shift right acc */ - AccRsh (shCnt); - - emitcode ("anl", "a,#!constbyte", - ((unsigned char) -1) >> (8 - SPEC_BLEN (etype))); - aopPut (AOP (result), "a", offset++); - goto finish; - } - - /* bit field did not fit in a byte */ - rlen = SPEC_BLEN (etype); - aopPut (AOP (result), "a", offset++); - - while (1) - { - - switch (ptype) - { - case POINTER: - case IPOINTER: - emitcode ("inc", "%s", rname); - emitcode ("mov", "a,@%s", rname); - break; - - case PPOINTER: - emitcode ("inc", "%s", rname); - emitcode ("movx", "a,@%s", rname); - break; - - case FPOINTER: - emitcode ("inc", "dptr"); - emitcode ("movx", "a,@dptr"); - break; - - case CPOINTER: - emitcode ("clr", "a"); - emitcode ("inc", "dptr"); - emitcode ("movc", "a,@a+dptr"); - break; - - case GPOINTER: - emitcode ("inc", "dptr"); - emitcode ("lcall", "__gptrget"); - break; - } - - rlen -= 8; - /* if we are done */ - if (rlen < 8) - break; - - aopPut (AOP (result), "a", offset++); - - } - - if (rlen) - { - 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++); - } -} -#endif /*-----------------------------------------------------------------*/ @@ -10031,179 +9910,6 @@ genPackBits (sym_link * etype, } -#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; - char *l; - - blen = SPEC_BLEN (etype); - bstr = SPEC_BSTR (etype); - - MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL)); - - /* if the bit lenth is less than or */ - /* 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 (shCount); - - if (SPEC_BLEN (etype) < 8) - { /* if smaller than a byte */ - - emitcode ("anl", "a,#0x%02x", (~mask) & 0xff); - - switch (p_type) - { - case POINTER: - emitcode ("mov", "b,a"); - emitcode ("mov", "a,@%s", rname); - break; - - case FPOINTER: - emitcode ("mov", "b,a"); - emitcode ("movx", "a,@dptr"); - break; - - case GPOINTER: - emitcode ("push", "b"); - emitcode ("push", "acc"); - emitcode ("lcall", "__gptrget"); - emitcode ("pop", "b"); - break; - } - - emitcode ("anl", "a,#!constbyte", mask); - emitcode ("orl", "a,b"); - if (p_type == GPOINTER) - emitcode ("pop", "b"); - } - } - - switch (p_type) - { - case POINTER: - emitcode ("mov", "@%s,a", rname); - break; - - case FPOINTER: - emitcode ("movx", "@dptr,a"); - break; - - case GPOINTER: - emitcode ("lcall", "__gptrput"); - break; - } - - /* if we r done */ - if (SPEC_BLEN (etype) <= 8) - return; - - emitcode ("inc", "%s", rname); - rLen = SPEC_BLEN (etype); - - /* now generate for lengths greater than one byte */ - while (1) - { - - l = aopGet (AOP (right), offset++, FALSE, TRUE, NULL); - - rLen -= 8; - if (rLen < 8) - break; - - switch (p_type) - { - case POINTER: - if (*l == '@') - { - MOVA (l); - emitcode ("mov", "@%s,a", rname); - } - else - emitcode ("mov", "@%s,%s", rname, l); - break; - - case FPOINTER: - MOVA (l); - emitcode ("movx", "@dptr,a"); - break; - - case GPOINTER: - MOVA (l); - emitcode ("lcall", "__gptrput"); - break; - } - emitcode ("inc", "%s", rname); - } - - MOVA (l); - - /* 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) - { - case POINTER: - emitcode ("mov", "b,a"); - emitcode ("mov", "a,@%s", rname); - break; - - case FPOINTER: - emitcode ("mov", "b,a"); - emitcode ("movx", "a,@dptr"); - break; - - case GPOINTER: - emitcode ("push", "b"); - emitcode ("push", "acc"); - emitcode ("lcall", "__gptrget"); - emitcode ("pop", "b"); - break; - } - - emitcode ("anl", "a,#!constbyte", (((unsigned char) -1 << rLen) & 0xff)); - emitcode ("orl", "a,b"); - } - - if (p_type == GPOINTER) - emitcode ("pop", "b"); - - switch (p_type) - { - - case POINTER: - emitcode ("mov", "@%s,a", rname); - break; - - case FPOINTER: - emitcode ("movx", "@dptr,a"); - break; - - case GPOINTER: - emitcode ("lcall", "__gptrput"); - break; - } -} -#endif /*-----------------------------------------------------------------*/ /* genDataPointerSet - remat pointer to data space */ @@ -11306,8 +11012,8 @@ genCast (iCode * ic) aopOp (result, ic, FALSE, AOP_USESDPTR(right)); /* if the result is a bit */ - // if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */ - if (IS_BITVAR(OP_SYMBOL(result)->type)) + if (IS_BITVAR (OP_SYMBOL (result)->type) + && !IS_BITFIELD (OP_SYMBOL (result)->type) ) { /* if the right size is a literal then we know what the value is */ diff --git a/src/mcs51/gen.c b/src/mcs51/gen.c index 1034905e..7e1494c8 100644 --- a/src/mcs51/gen.c +++ b/src/mcs51/gen.c @@ -8613,7 +8613,9 @@ genCast (iCode * ic) aopOp (result, ic, FALSE); /* if the result is a bit (and not a bitfield) */ - if (AOP_TYPE (result) == AOP_CRY) + // if (AOP_TYPE (result) == AOP_CRY) + if (IS_BITVAR (OP_SYMBOL (result)->type) + && !IS_BITFIELD (OP_SYMBOL (result)->type) ) { /* if the right size is a literal then we know what the value is */ diff --git a/src/z80/gen.c b/src/z80/gen.c index 7231edf2..6e791307 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -5469,6 +5469,7 @@ AccRol (int shCount) { shCount &= 0x0007; // shCount : 0..7 +#if 0 switch (shCount) { case 0: @@ -5504,6 +5505,43 @@ AccRol (int shCount) emit2 ("srl a"); break; } +#else + switch (shCount) + { + case 0: + break; + case 1: + emit2 ("rlca"); + break; + case 2: + emit2 ("rlca"); + emit2 ("rlca"); + break; + case 3: + emit2 ("rlca"); + emit2 ("rlca"); + emit2 ("rlca"); + break; + case 4: + emit2 ("rlca"); + emit2 ("rlca"); + emit2 ("rlca"); + emit2 ("rlca"); + break; + case 5: + emit2 ("rrca"); + emit2 ("rrca"); + emit2 ("rrca"); + break; + case 6: + emit2 ("rrca"); + emit2 ("rrca"); + break; + case 7: + emit2 ("rrca"); + break; + } +#endif } /*-----------------------------------------------------------------*/ @@ -6015,6 +6053,82 @@ genRightShift (iCode * ic) freeAsmop (result, NULL, ic); } + +/*-----------------------------------------------------------------*/ +/* genUnpackBits - generates code for unpacking bits */ +/*-----------------------------------------------------------------*/ +static void +genUnpackBits (operand * result, int pair) +{ + 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 */ + + emitDebug ("; 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) + { + emit2 ("ld a,!*pair", _pairs[pair].name); + AccRsh (bstr); + emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - blen)); + aopPut (AOP (result), "a", offset++); + goto finish; + } + + /* TODO: what if pair == PAIR_DE ? */ + if (getPairId (AOP (result)) == PAIR_HL) + { + wassertl (rsize == 2, "HL must be of size 2"); + emit2 ("ld a,!*hl"); + emit2 ("inc hl"); + emit2 ("ld h,!*hl"); + emit2 ("ld l,a"); + emit2 ("ld a,h"); + emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (16 - blen)); + emit2 ("ld h,a"); + spillPair (PAIR_HL); + return; + } + + /* Bit field did not fit in a byte. Copy all + but the partial byte at the end. */ + for (rlen=blen;rlen>=8;rlen-=8) + { + emit2 ("ld a,!*pair", _pairs[pair].name); + aopPut (AOP (result), "a", offset++); + if (rlen>8) + { + emit2 ("inc %s", _pairs[pair].name); + _G.pairs[pair].offset++; + } + } + + /* Handle the partial byte at the end */ + if (rlen) + { + emit2 ("ld a,!*pair", _pairs[pair].name); + emit2 ("and a,!immedbyte", ((unsigned char) -1) >> (8 - rlen)); + aopPut (AOP (result), "a", offset++); + } + +finish: + if (offset < rsize) + { + rsize -= offset; + while (rsize--) + aopPut (AOP (result), "!zero", offset++); + } +} + /*-----------------------------------------------------------------*/ /* genGenPointerGet - get value from generic pointer space */ /*-----------------------------------------------------------------*/ @@ -6034,7 +6148,7 @@ genGenPointerGet (operand * left, size = AOP_SIZE (result); - if (isPair (AOP (left)) && size == 1) + if (isPair (AOP (left)) && size == 1 && !IS_BITVAR (retype)) { /* Just do it */ if (isPtrPair (AOP (left))) @@ -6052,7 +6166,7 @@ genGenPointerGet (operand * left, goto release; } - if (getPairId (AOP (left)) == PAIR_IY) + if (getPairId (AOP (left)) == PAIR_IY && !IS_BITVAR (retype)) { /* Just do it */ offset = 0; @@ -6075,7 +6189,10 @@ genGenPointerGet (operand * left, /* if bit then unpack */ if (IS_BITVAR (retype)) { - wassert (0); + genUnpackBits (result, pair); + freeAsmop (left, NULL, ic); + goto release; + //wassert (0); } else if (getPairId (AOP (result)) == PAIR_HL) { @@ -6175,6 +6292,149 @@ isRegOrLit (asmop * aop) return FALSE; } + +/*-----------------------------------------------------------------*/ +/* 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); + } +} + + /*-----------------------------------------------------------------*/ /* genGenPointerSet - stores the value into a pointer location */ /*-----------------------------------------------------------------*/ @@ -6184,7 +6444,9 @@ genGenPointerSet (operand * right, { int size, offset; sym_link *retype = getSpec (operandType (right)); + sym_link *letype = getSpec (operandType (result)); PAIR_ID pairId = PAIR_HL; + bool isBitvar; aopOp (result, ic, FALSE, FALSE); aopOp (right, ic, FALSE, FALSE); @@ -6194,8 +6456,11 @@ genGenPointerSet (operand * right, size = AOP_SIZE (right); + isBitvar = IS_BITVAR(retype) || IS_BITVAR(letype); + emitDebug("; isBitvar = %d", isBitvar); + /* Handle the exceptions first */ - if (isPair (AOP (result)) && size == 1) + if (isPair (AOP (result)) && size == 1 && !isBitvar) { /* Just do it */ const char *l = aopGet (AOP (right), 0, FALSE); @@ -6212,7 +6477,7 @@ genGenPointerSet (operand * right, goto release; } - if ( getPairId( AOP (result)) == PAIR_IY) + if ( getPairId( AOP (result)) == PAIR_IY && !isBitvar) { /* Just do it */ const char *l = aopGet (AOP (right), 0, FALSE); @@ -6233,7 +6498,8 @@ genGenPointerSet (operand * right, } goto release; } - else if (getPairId (AOP (result)) == PAIR_HL && !isLastUse (ic, result)) + else if (getPairId (AOP (result)) == PAIR_HL && !isLastUse (ic, result) + && !isBitvar) { offset = 0; @@ -6275,9 +6541,11 @@ genGenPointerSet (operand * right, freeAsmop (result, NULL, ic); /* if bit then unpack */ - if (IS_BITVAR (retype)) + if (isBitvar) { - wassert (0); + genPackBits ((IS_BITVAR (retype) ? retype : letype), right, pairId, ic); + goto release; + //wassert (0); } else { diff --git a/support/regression/tests/bitfields.c b/support/regression/tests/bitfields.c index fb106afd..cf7d004b 100644 --- a/support/regression/tests/bitfields.c +++ b/support/regression/tests/bitfields.c @@ -126,7 +126,6 @@ testBitfieldSizeof(void) void testBitfieldsSingleBitLiteral(void) { -#if !defined(SDCC_z80) && !defined(SDCC_gbz80) size2b_bf.b0 = 0; size2b_bf.b1 = 0; size2b_bf.b2 = 0; @@ -174,13 +173,11 @@ testBitfieldsSingleBitLiteral(void) ASSERT(size2b_bf.b7==0); ASSERT(size2b_bf.b8==0); ASSERT(size2b_bf.b9==1); -#endif } void testBitfieldsSingleBit(void) { -#if !defined(SDCC_z80) && !defined(SDCC_gbz80) volatile unsigned char c; c = 0; @@ -233,13 +230,11 @@ testBitfieldsSingleBit(void) ASSERT(size2b_bf.b7==0); ASSERT(size2b_bf.b8==0); ASSERT(size2b_bf.b9==1); -#endif } void -testBitfieldsMultibit(void) +testBitfieldsMultibitLiteral(void) { -#if !defined(SDCC_z80) && !defined(SDCC_gbz80) size2c_bf.b0 = 0xff; /* should truncate to 0x0f */ size2c_bf.b1 = 0; ASSERT(size2c_bf.b0==0x0f); @@ -269,7 +264,48 @@ testBitfieldsMultibit(void) size2d_bf.b1 = 5; ASSERT(size2d_bf.b0==0x0a46); ASSERT(size2d_bf.b1==5); -#endif +} + +void +testBitfieldsMultibit(void) +{ + volatile int allones = 0xffff; + volatile int zero = 0; + volatile int x; + + size2c_bf.b0 = allones; /* should truncate to 0x0f */ + size2c_bf.b1 = zero; + ASSERT(size2c_bf.b0==0x0f); + ASSERT(size2c_bf.b1==0); + + size2c_bf.b1 = allones; /* should truncate to 0x1f */ + size2c_bf.b0 = zero; + ASSERT(size2c_bf.b0==0); + ASSERT(size2c_bf.b1==0x1f); + + size2d_bf.b0 = allones; /* should truncate to 0x0fff */ + size2d_bf.b1 = zero; + ASSERT(size2d_bf.b0==0x0fff); + ASSERT(size2d_bf.b1==0); + + size2d_bf.b1 = allones; /* should truncate to 0x07 */ + size2d_bf.b0 = zero; + ASSERT(size2d_bf.b0==0); + ASSERT(size2d_bf.b1==0x07); + + x = 0x0321; + size2d_bf.b0 = x; + x = 1; + size2d_bf.b1 = x; + ASSERT(size2d_bf.b0==0x0321); + ASSERT(size2d_bf.b1==1); + + x = 0x0a46; + size2d_bf.b0 = x; + x = 5; + size2d_bf.b1 = x; + ASSERT(size2d_bf.b0==0x0a46); + ASSERT(size2d_bf.b1==5); } void -- 2.47.2