X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fds390%2Fgen.c;h=436a490b7767c136ee758698d06a74da268e52a1;hb=d373426fcefbb83b34bbb0aa761966a147238700;hp=1686e093e38fa7383285b84f672376671b5ff31a;hpb=6d6039133e612284f032da8b1baaa1a5088b6765;p=fw%2Fsdcc diff --git a/src/ds390/gen.c b/src/ds390/gen.c index 1686e093..436a490b 100644 --- a/src/ds390/gen.c +++ b/src/ds390/gen.c @@ -438,6 +438,72 @@ pointerCode (sym_link * etype) } +/*-----------------------------------------------------------------*/ +/* leftRightUseAcc - returns size of accumulator use by operands */ +/*-----------------------------------------------------------------*/ +static int +leftRightUseAcc(iCode *ic) +{ + operand *op; + int size; + int accuseSize = 0; + int accuse = 0; + + if (!ic) + { + werror (E_INTERNAL_ERROR, __FILE__, __LINE__, + "null iCode pointer"); + return 0; + } + + if (ic->op == IFX) + { + op = IC_COND (ic); + if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse) + { + accuse = 1; + size = getSize (OP_SYMBOL (op)->type); + if (size>accuseSize) + accuseSize = size; + } + } + else if (ic->op == JUMPTABLE) + { + op = IC_JTCOND (ic); + if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse) + { + accuse = 1; + size = getSize (OP_SYMBOL (op)->type); + if (size>accuseSize) + accuseSize = size; + } + } + else + { + op = IC_LEFT (ic); + if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse) + { + accuse = 1; + size = getSize (OP_SYMBOL (op)->type); + if (size>accuseSize) + accuseSize = size; + } + op = IC_RIGHT (ic); + if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse) + { + accuse = 1; + size = getSize (OP_SYMBOL (op)->type); + if (size>accuseSize) + accuseSize = size; + } + } + + if (accuseSize) + return accuseSize; + else + return accuse; +} + /*-----------------------------------------------------------------*/ /* aopForSym - for a true symbol */ /*-----------------------------------------------------------------*/ @@ -446,6 +512,7 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2) { asmop *aop; memmap *space = SPEC_OCLS (sym->etype); + int accuse = leftRightUseAcc (ic); /* if already has one */ if (sym->aop) @@ -467,10 +534,10 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2) if (sym->onStack) { - if (_G.accInUse) + if (_G.accInUse || accuse) emitcode ("push", "acc"); - if (_G.bInUse) + if (_G.bInUse || (accuse>1)) emitcode ("push", "b"); emitcode ("mov", "a,_bp"); @@ -481,10 +548,10 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2) emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name); - if (_G.bInUse) + if (_G.bInUse || (accuse>1)) emitcode ("pop", "b"); - if (_G.accInUse) + if (_G.accInUse || accuse) emitcode ("pop", "acc"); } else @@ -543,10 +610,10 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2) emitcode("mov","dps,#0"); } } else { - if (_G.accInUse) + if (_G.accInUse || accuse) emitcode ("push", "acc"); - if (_G.bInUse) + if (_G.bInUse || (accuse>1)) emitcode ("push", "b"); emitcode ("mov", "a,_bpx"); @@ -573,10 +640,10 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2) emitcode ("mov", "dpl,b"); } - if (_G.bInUse) + if (_G.bInUse || (accuse>1)) emitcode ("pop", "b"); - if (_G.accInUse) + if (_G.accInUse || accuse) emitcode ("pop", "acc"); } sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR)); @@ -602,14 +669,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)); @@ -939,13 +1006,22 @@ aopOp (operand * op, iCode * ic, bool result, bool useDP2) aop->aopu.dptr = sym->dptr; return ; } - /* else spill location */ - if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) { - /* force a new aop if sizes differ */ - sym->usl.spillLoc->aop = NULL; - } - sym->aop = op->aop = aop = - aopForSym (ic, sym->usl.spillLoc, result, useDP2); + + if (sym->usl.spillLoc) + { + if (getSize(sym->type) != getSize(sym->usl.spillLoc->type)) + { + /* force a new aop if sizes differ */ + sym->usl.spillLoc->aop = NULL; + } + sym->aop = op->aop = aop = + aopForSym (ic, sym->usl.spillLoc, result, useDP2); + aop->size = getSize (sym->type); + return; + } + + /* else must be a dummy iTemp */ + sym->aop = op->aop = aop = newAsmop (AOP_DUMMY); aop->size = getSize (sym->type); return; } @@ -1115,6 +1191,8 @@ aopGet (asmop *aop, /* depending on type */ switch (aop->type) { + case AOP_DUMMY: + return zero; case AOP_R0: case AOP_R1: @@ -1316,6 +1394,10 @@ aopPut (asmop * aop, char *s, int offset) /* depending on where it is ofcourse */ switch (aop->type) { + case AOP_DUMMY: + MOVA (s); /* read s in case it was volatile */ + break; + case AOP_DIR: if (offset) { @@ -1607,47 +1689,6 @@ reAdjustPreg (asmop * aop) emitcode("nop", "; workaround for DS80C390 div bug."); \ } -/*-----------------------------------------------------------------*/ -/* genNotFloat - generates not for float operations */ -/*-----------------------------------------------------------------*/ -static void -genNotFloat (operand * op, operand * res) -{ - int size, offset; - symbol *tlbl; - - D (emitcode (";", "genNotFloat ");); - - /* we will put 127 in the first byte of - the result */ - aopPut (AOP (res), "#127", 0); - size = AOP_SIZE (op) - 1; - offset = 1; - - _startLazyDPSEvaluation (); - MOVA(aopGet(op->aop, offset++, FALSE, FALSE, NULL)); - - while (size--) - { - emitcode ("orl", "a,%s", - aopGet (op->aop, - offset++, FALSE, FALSE, - DP2_RESULT_REG)); - } - _endLazyDPSEvaluation (); - - tlbl = newiTempLabel (NULL); - aopPut (res->aop, one, 1); - emitcode ("jz", "!tlabel", (tlbl->key + 100)); - aopPut (res->aop, zero, 1); - emitcode ("", "!tlabeldef", (tlbl->key + 100)); - - size = res->aop->size - 2; - offset = 2; - /* put zeros in the rest */ - while (size--) - aopPut (res->aop, zero, offset++); -} /*-----------------------------------------------------------------*/ /* opIsGptr: returns non-zero if the passed operand is */ @@ -1797,7 +1838,6 @@ static void genNot (iCode * ic) { symbol *tlbl; - sym_link *optype = operandType (IC_LEFT (ic)); D (emitcode (";", "genNot ");); @@ -1814,13 +1854,6 @@ genNot (iCode * ic) goto release; } - /* if type float then do float */ - if (IS_FLOAT (optype)) - { - genNotFloat (IC_LEFT (ic), IC_RESULT (ic)); - goto release; - } - toBoolean (IC_LEFT (ic)); tlbl = newiTempLabel (NULL); @@ -1928,7 +1961,7 @@ genUminus (iCode * ic) /* assign asmops */ aopOp (IC_LEFT (ic), ic, FALSE, FALSE); - aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic))); + aopOp (IC_RESULT (ic), ic, TRUE, (AOP_TYPE(IC_LEFT (ic)) == AOP_DPTR)); /* if both in bit space then special case */ @@ -2631,9 +2664,9 @@ genCall (iCode * ic) } else { - _G.accInUse++; + _G.bInUse++; aopOp (IC_RESULT (ic), ic, FALSE, TRUE); - _G.accInUse--; + _G.bInUse--; assignResultValue (IC_RESULT (ic)); @@ -2879,9 +2912,6 @@ genFunction (iCode * ic) if (options.stack_probe) emitcode ("lcall","__stack_probe"); - /* if critical function then turn interrupts off */ - if (IFFUNC_ISCRITICAL (ftype)) - emitcode ("clr", "ea"); /* here we need to generate the equates for the register bank if required */ @@ -3160,6 +3190,17 @@ genFunction (iCode * ic) emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff)); emitcode ("mov", "_spx,a"); } + + /* if critical function then turn interrupts off */ + if (IFFUNC_ISCRITICAL (ftype)) + { + symbol *tlbl = newiTempLabel (NULL); + emitcode ("setb", "c"); + emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */ + emitcode ("clr", "c"); + emitcode ("", "%05d$:", (tlbl->key + 100)); + emitcode ("push", "psw"); /* save old ea via c in psw */ + } } @@ -3179,6 +3220,12 @@ genEndFunction (iCode * ic) return; } + if (IFFUNC_ISCRITICAL (sym->type)) + { + emitcode ("pop", "psw"); /* restore ea via c in psw */ + emitcode ("mov", "ea,c"); + } + if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) && (sym->stack || FUNC_HASSTACKPARM(sym->type))) { @@ -3323,9 +3370,6 @@ genEndFunction (iCode * ic) if (!inExcludeList ("acc")) emitcode ("pop", "acc"); - if (IFFUNC_ISCRITICAL (sym->type)) - emitcode ("setb", "ea"); - /* if debug then send end of function */ if (options.debug && currFunc) { _G.debugLine = 1; @@ -3343,9 +3387,6 @@ genEndFunction (iCode * ic) } else { - if (IFFUNC_ISCRITICAL (sym->type)) - emitcode ("setb", "ea"); - if (IFFUNC_CALLEESAVES(sym->type)) { int i; @@ -5619,6 +5660,7 @@ gencjneshort (operand * left, operand * right, symbol * lbl) if the right is in a pointer register and left is not */ if ((AOP_TYPE (left) == AOP_LIT) || + (AOP_TYPE (left) == AOP_IMMD) || (IS_AOP_PREG (right) && !IS_AOP_PREG (left))) { operand *t = right; @@ -5657,6 +5699,8 @@ gencjneshort (operand * left, operand * right, symbol * lbl) if the left is a pointer register & right is not */ else if (AOP_TYPE (right) == AOP_REG || AOP_TYPE (right) == AOP_DIR || + AOP_TYPE (right) == AOP_LIT || + AOP_TYPE (right) == AOP_IMMD || (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) || (IS_AOP_PREG (left) && !IS_AOP_PREG (right))) { @@ -6343,6 +6387,8 @@ genAnd (iCode * ic, iCode * ifx) { if (ifx) jmpTrueOrFalse (ifx, tlbl); + else + emitcode ("", "!tlabeldef", tlbl->key + 100); goto release; } } @@ -6433,6 +6479,8 @@ genAnd (iCode * ic, iCode * ifx) } else if (ifx) jmpTrueOrFalse (ifx, tlbl); + else + emitcode ("", "!tlabeldef", tlbl->key + 100); } else { @@ -6751,6 +6799,8 @@ genOr (iCode * ic, iCode * ifx) } else if (ifx) jmpTrueOrFalse (ifx, tlbl); + else + emitcode ("", "!tlabeldef", tlbl->key + 100); } else { @@ -7287,6 +7337,65 @@ genGetHbit (iCode * ic) freeAsmop (result, NULL, ic, TRUE); } +/*-----------------------------------------------------------------*/ +/* genSwap - generates code to swap nibbles or bytes */ +/*-----------------------------------------------------------------*/ +static void +genSwap (iCode * ic) +{ + operand *left, *result; + + D(emitcode ("; genSwap","")); + + left = IC_LEFT (ic); + result = IC_RESULT (ic); + aopOp (left, ic, FALSE, FALSE); + aopOp (result, ic, FALSE, AOP_USESDPTR(left)); + + _startLazyDPSEvaluation (); + switch (AOP_SIZE (left)) + { + case 1: /* swap nibbles in byte */ + MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL)); + emitcode ("swap", "a"); + aopPut (AOP (result), "a", 0); + break; + case 2: /* swap bytes in word */ + if (AOP_TYPE(left) == AOP_REG && sameRegs(AOP(left), AOP(result))) + { + MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL)); + aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0); + aopPut (AOP (result), "a", 1); + } + else if (operandsEqu (left, result)) + { + char * reg = "a"; + MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL)); + if (AOP_NEEDSACC (left) || AOP_NEEDSACC (result)) + { + emitcode ("mov", "b,a"); + reg = "b"; + _G.bInUse=1; + } + aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0); + aopPut (AOP (result), reg, 1); + _G.bInUse=0; + } + else + { + aopPut (AOP (result), aopGet (AOP (left), 1, FALSE, FALSE, NULL), 0); + aopPut (AOP (result), aopGet (AOP (left), 0, FALSE, FALSE, NULL), 1); + } + break; + default: + wassertl(FALSE, "unsupported SWAP operand size"); + } + _endLazyDPSEvaluation (); + + freeAsmop (left, NULL, ic, TRUE); + freeAsmop (result, NULL, ic, TRUE); +} + /*-----------------------------------------------------------------*/ /* AccRol - rotate left accumulator by known count */ /*-----------------------------------------------------------------*/ @@ -8646,7 +8755,7 @@ genRightShiftLiteral (operand * left, && (size != 2) && (size != 4)) { - D(emitcode (";", "genRightShiftLiteral wimping out");); + D(emitcode (";", "genRightShiftLiteral wimping out");); return FALSE; } @@ -8840,7 +8949,7 @@ static void genRightShift (iCode * ic) { operand *right, *left, *result; - sym_link *retype; + sym_link *letype; int size, offset; char *l; symbol *tlbl, *tlbl1; @@ -8849,9 +8958,9 @@ genRightShift (iCode * ic) /* if signed then we do it the hard way preserve the sign bit moving it inwards */ - retype = getSpec (operandType (IC_RESULT (ic))); + letype = getSpec (operandType (IC_LEFT (ic))); - if (!SPEC_USIGN (retype)) + if (!SPEC_USIGN (letype)) { genSignedRightShift (ic); return; @@ -8972,116 +9081,148 @@ release: freeAsmop (result, NULL, ic, TRUE); } + /*-----------------------------------------------------------------*/ -/* genUnpackBits - generates code for unpacking bits */ +/* 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 -genUnpackBits (operand * result, char *rname, int ptype) +emitPtrByteGet (char *rname, int p_type, bool preserveAinB) { - int shCnt; - int rlen; - sym_link *etype; - int offset = 0; - - D (emitcode (";", "genUnpackBits ");); - - etype = getSpec (operandType (result)); - - /* read the first byte */ - switch (ptype) + switch (p_type) { - - case POINTER: 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; } +} - /* 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)) +/*-----------------------------------------------------------------*/ +/* 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; - /* shift right acc */ - AccRsh (shCnt); + case PPOINTER: + MOVA (src); + emitcode ("movx", "@%s,a", rname); + break; + + case FPOINTER: + MOVA (src); + emitcode ("movx", "@dptr,a"); + break; - emitcode ("anl", "a,#!constbyte", - ((unsigned char) -1) >> (8 - SPEC_BLEN (etype))); - aopPut (AOP (result), "a", offset); - return; + case GPOINTER: + MOVA (src); + emitcode ("lcall", "__gptrput"); + break; } +} - /* bit field did not fit in a byte */ - rlen = SPEC_BLEN (etype) - 8; - 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; +/*-----------------------------------------------------------------*/ +/* 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 */ - case CPOINTER: - emitcode ("clr", "a"); - emitcode ("inc", "dptr"); - emitcode ("movc", "a,@a+dptr"); - break; + D(emitcode ("; genUnpackBits","")); - case GPOINTER: - emitcode ("inc", "dptr"); - emitcode ("lcall", "__gptrget"); - break; - } - - rlen -= 8; - /* if we are done */ - if (rlen < 8) - break; + 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) { - emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (rlen)); - aopPut (AOP (result), "a", offset); + emitPtrByteGet (rname, ptype, FALSE); + 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++); + } } @@ -9760,162 +9901,125 @@ genPackBits (sym_link * etype, operand * right, char *rname, int p_type) { - int offset = 0; - int rLen; - int blen, bstr; - char *l; + 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); - 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) - { - /* shift left acc */ - AccLsh (SPEC_BSTR (etype)); - - if (SPEC_BLEN (etype) < 8) - { /* if smaller than a 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) - ((unsigned char) (0xFF << (blen + bstr)) | - (unsigned char) (0xFF >> (8 - bstr)))); - emitcode ("orl", "a,b"); - if (p_type == GPOINTER) - emitcode ("pop", "b"); - } - } - - switch (p_type) + /* If the bitfield length is less than a byte */ + if (blen < 8) { - case POINTER: - emitcode ("mov", "@%s,a", rname); - break; + mask = ((unsigned char) (0xFF << (blen + bstr)) | + (unsigned char) (0xFF >> (8 - bstr))); - case FPOINTER: - emitcode ("movx", "@dptr,a"); - break; + 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"); + } + } - case GPOINTER: - emitcode ("lcall", "__gptrput"); - break; + emitPtrByteSet (rname, p_type, "a"); + return; } - /* 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) + /* 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) { - - 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); + emitPtrByteSet (rname, p_type, + aopGet (AOP (right), offset++, FALSE, TRUE, NULL) ); + if (rlen>8) + emitcode ("inc", "%s", rname); } - MOVA (l); - - /* last last was not complete */ - if (rLen) + /* If there was a partial byte at the end */ + if (rlen) { - /* 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)); - emitcode ("orl", "a,b"); + 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 (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; - } -} /*-----------------------------------------------------------------*/ /* genDataPointerSet - remat pointer to data space */ /*-----------------------------------------------------------------*/ @@ -11014,11 +11118,11 @@ genCast (iCode * ic) return; aopOp (right, ic, FALSE, FALSE); - aopOp (result, ic, FALSE, AOP_USESDPTR(right)); + aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR)); /* 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 */ @@ -12610,36 +12714,121 @@ static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *na static void genDummyRead (iCode * ic) { - operand *right; + operand *op; int size, offset; D(emitcode("; genDummyRead","")); - right = IC_RIGHT (ic); + op = IC_RIGHT (ic); + if (op && IS_SYMOP (op)) + { + aopOp (op, ic, FALSE, FALSE); - aopOp (right, ic, FALSE, FALSE); + /* if the result is a bit */ + if (AOP_TYPE (op) == AOP_CRY) + emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir); + else + { + /* bit variables done */ + /* general case */ + size = AOP_SIZE (op); + offset = 0; + while (size--) + { + MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE)); + offset++; + } + } - /* if the result is a bit */ - if (AOP_TYPE (right) == AOP_CRY) - { - emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir); - goto release; + freeAsmop (op, NULL, ic, TRUE); } - /* bit variables done */ - /* general case */ - size = AOP_SIZE (right); - offset = 0; - while (size--) + op = IC_LEFT (ic); + if (op && IS_SYMOP (op)) { - emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE)); - offset++; + aopOp (op, ic, FALSE, FALSE); + + /* if the result is a bit */ + if (AOP_TYPE (op) == AOP_CRY) + emitcode ("mov", "c,%s", AOP (op)->aopu.aop_dir); + else + { + /* bit variables done */ + /* general case */ + size = AOP_SIZE (op); + offset = 0; + while (size--) + { + MOVA (aopGet (AOP (op), offset, FALSE, FALSE, FALSE)); + offset++; + } + } + + freeAsmop (op, NULL, ic, TRUE); } + +} -release: - freeAsmop (right, NULL, ic, TRUE); +/*-----------------------------------------------------------------*/ +/* genCritical - generate code for start of a critical sequence */ +/*-----------------------------------------------------------------*/ +static void +genCritical (iCode *ic) +{ + symbol *tlbl = newiTempLabel (NULL); + + D(emitcode("; genCritical","")); + + if (IC_RESULT (ic)) + aopOp (IC_RESULT (ic), ic, TRUE, FALSE); + + emitcode ("setb", "c"); + emitcode ("jbc", "ea,%05d$", (tlbl->key + 100)); /* atomic test & clear */ + emitcode ("clr", "c"); + emitcode ("", "%05d$:", (tlbl->key + 100)); + + if (IC_RESULT (ic)) + outBitC (IC_RESULT (ic)); /* save old ea in an operand */ + else + emitcode ("push", "psw"); /* save old ea via c in psw on top of stack*/ + + if (IC_RESULT (ic)) + freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); } +/*-----------------------------------------------------------------*/ +/* genEndCritical - generate code for end of a critical sequence */ +/*-----------------------------------------------------------------*/ +static void +genEndCritical (iCode *ic) +{ + D(emitcode("; genEndCritical","")); + + if (IC_RIGHT (ic)) + { + aopOp (IC_RIGHT (ic), ic, FALSE, FALSE); + if (AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY) + { + emitcode ("mov", "c,%s", IC_RIGHT (ic)->aop->aopu.aop_dir); + emitcode ("mov", "ea,c"); + } + else + { + MOVA (aopGet (AOP (IC_RIGHT (ic)), 0, FALSE, FALSE, FALSE)); + emitcode ("rrc", "a"); + emitcode ("mov", "ea,c"); + } + freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE); + } + else + { + emitcode ("pop", "psw"); /* restore ea via c in psw on top of stack */ + emitcode ("mov", "ea,c"); + } +} + + + /*-----------------------------------------------------------------*/ /* genBuiltIn - calls the appropriate function to generating code */ /* for a built in function */ @@ -13013,6 +13202,18 @@ gen390Code (iCode * lic) genDummyRead (ic); break; + case CRITICAL: + genCritical (ic); + break; + + case ENDCRITICAL: + genEndCritical (ic); + break; + + case SWAP: + genSwap (ic); + break; + #if 0 // obsolete, and buggy for != xdata case ARRAYINIT: genArrayInit(ic);