X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fds390%2Fgen.c;h=e5670acc03530c9791114e466cfdc17316beaeed;hb=353ff1ac97be2a4c6fb07f88607dffaebe20590e;hp=436a490b7767c136ee758698d06a74da268e52a1;hpb=d373426fcefbb83b34bbb0aa761966a147238700;p=fw%2Fsdcc diff --git a/src/ds390/gen.c b/src/ds390/gen.c index 436a490b..e5670acc 100644 --- a/src/ds390/gen.c +++ b/src/ds390/gen.c @@ -31,6 +31,7 @@ #include #include "common.h" +#include "main.h" #include "ralloc.h" #include "gen.h" #include "SDCCglobl.h" @@ -79,6 +80,7 @@ static struct short dptrInUse; short dptr1InUse; set *sendSet; + iCode *current_iCode; } _G; @@ -130,6 +132,9 @@ static unsigned char SRMask[] = emitcode ("","!tlabeldef",lbl->key+100); \ }} +static int _currentDPS; /* Current processor DPS. */ +static int _desiredDPS; /* DPS value compiler thinks we should be using. */ +static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */ /*-----------------------------------------------------------------*/ /* emitcode - writes the code into a file : for now it is simple */ @@ -177,6 +182,8 @@ emitcode (char *inst, char *fmt,...) lineCurr->isInline = _G.inLine; lineCurr->isDebug = _G.debugLine; + lineCurr->ic = _G.current_iCode; + lineCurr->aln = ds390newAsmLineNode(_currentDPS); va_end (ap); } @@ -310,9 +317,6 @@ newAsmop (short type) return aop; } -static int _currentDPS; /* Current processor DPS. */ -static int _desiredDPS; /* DPS value compiler thinks we should be using. */ -static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */ /*-----------------------------------------------------------------*/ /* genSetDPTR: generate code to select which DPTR is in use (zero */ @@ -516,7 +520,13 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2) /* if already has one */ if (sym->aop) - return sym->aop; + { + if ((sym->aop->type == AOP_DPTR && useDP2) + || (sym->aop->type == AOP_DPTR2 && !useDP2)) + sym->aop = NULL; + else + return sym->aop; + } /* assign depending on the storage class */ /* if it is on the stack or indirectly addressable */ @@ -862,6 +872,14 @@ operandsEqu (operand * op1, operand * op2) (sym2->usl.spillLoc == sym1)) return TRUE; + /* are they spilt to the same location */ + if (IS_ITEMP (op2) && + IS_ITEMP (op1) && + sym2->isspilt && + sym1->isspilt && + (sym1->usl.spillLoc == sym2->usl.spillLoc)) + return TRUE; + return FALSE; } @@ -921,13 +939,23 @@ aopOp (operand * op, iCode * ic, bool result, bool useDP2) /* if already has a asmop then continue */ if (op->aop) - return; + { + if ((op->aop->type == AOP_DPTR && useDP2) + || (op->aop->type == AOP_DPTR2 && !useDP2)) + op->aop = NULL; + else + return; + } /* if the underlying symbol has a aop */ if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) { op->aop = OP_SYMBOL (op)->aop; - return; + if ((op->aop->type == AOP_DPTR && useDP2) + || (op->aop->type == AOP_DPTR2 && !useDP2)) + op->aop = NULL; + else + return; } /* if this is a true symbol */ @@ -2651,9 +2679,16 @@ genCall (iCode * ic) if (size > 1) { emitcode ("mov", "b,%s", fReturn[1]); + _G.bInUse++; } + _G.accInUse++; aopOp (IC_RESULT (ic), ic, FALSE, FALSE); + _G.accInUse--; + + if (size > 1) + _G.bInUse--; + aopPut (AOP (IC_RESULT (ic)), "a", 0); if (size > 1) @@ -2982,12 +3017,10 @@ genFunction (iCode * ic) /* save the registers used */ for (i = 0; i < sym->regsUsed->size; i++) { - if (bitVectBitValue (sym->regsUsed, i) || - (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX))) + if (bitVectBitValue (sym->regsUsed, i)) emitcode ("push", "%s", ds390_regWithIdx (i)->dname); } } - } else { @@ -3107,8 +3140,7 @@ genFunction (iCode * ic) /* save the registers used */ for (i = 0; i < sym->regsUsed->size; i++) { - if (bitVectBitValue (sym->regsUsed, i) || - (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX))) + if (bitVectBitValue (sym->regsUsed, i)) { emitcode ("push", "%s", ds390_regWithIdx (i)->dname); _G.nRegsSaved++; @@ -3211,6 +3243,11 @@ static void genEndFunction (iCode * ic) { symbol *sym = OP_SYMBOL (IC_LEFT (ic)); + lineNode *lnp = lineCurr; + bitVect *regsUsed; + bitVect *regsUsedPrologue; + bitVect *regsUnneeded; + int idx; D (emitcode (";", "genEndFunction ");); @@ -3302,12 +3339,10 @@ genEndFunction (iCode * ic) /* save the registers used */ for (i = sym->regsUsed->size; i >= 0; i--) { - if (bitVectBitValue (sym->regsUsed, i) || - (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX))) + if (bitVectBitValue (sym->regsUsed, i)) emitcode ("pop", "%s", ds390_regWithIdx (i)->dname); } } - } else { @@ -3397,12 +3432,10 @@ genEndFunction (iCode * ic) /* save the registers used */ for (i = sym->regsUsed->size; i >= 0; i--) { - if (bitVectBitValue (sym->regsUsed, i) || - (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX))) + if (bitVectBitValue (sym->regsUsed, i)) emitcode ("pop", "%s", ds390_regWithIdx (i)->dname); } } - } /* if debug then send end of function */ @@ -3422,6 +3455,111 @@ genEndFunction (iCode * ic) emitcode ("ret", ""); } + if (!port->peep.getRegsRead || !port->peep.getRegsWritten) + return; + + /* If this was an interrupt handler using bank 0 that called another */ + /* function, then all registers must be saved; nothing to optimized. */ + if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type) + && !FUNC_REGBANK(sym->type)) + return; + + /* There are no push/pops to optimize if not callee-saves or ISR */ + if (!(FUNC_CALLEESAVES (sym->type) || FUNC_ISISR (sym->type))) + return; + + /* If there were stack parameters, we cannot optimize without also */ + /* fixing all of the stack offsets; this is too dificult to consider. */ + if (FUNC_HASSTACKPARM(sym->type)) + return; + + /* Compute the registers actually used */ + regsUsed = newBitVect (ds390_nRegs); + regsUsedPrologue = newBitVect (ds390_nRegs); + while (lnp) + { + if (lnp->ic && lnp->ic->op == FUNCTION) + regsUsedPrologue = bitVectUnion (regsUsedPrologue, port->peep.getRegsWritten(lnp)); + else + regsUsed = bitVectUnion (regsUsed, port->peep.getRegsWritten(lnp)); + + if (lnp->ic && lnp->ic->op == FUNCTION && lnp->prev + && lnp->prev->ic && lnp->prev->ic->op == ENDFUNCTION) + break; + if (!lnp->prev) + break; + lnp = lnp->prev; + } + + if (bitVectBitValue (regsUsedPrologue, DPS_IDX) + && !bitVectBitValue (regsUsed, DPS_IDX)) + { + bitVectUnSetBit (regsUsedPrologue, DPS_IDX); + } + + if (bitVectBitValue (regsUsedPrologue, CND_IDX) + && !bitVectBitValue (regsUsed, CND_IDX)) + { + regsUsed = bitVectUnion (regsUsed, regsUsedPrologue); + if (IFFUNC_ISISR (sym->type) && !FUNC_REGBANK(sym->type) + && !sym->stack) + bitVectUnSetBit (regsUsed, CND_IDX); + } + else + regsUsed = bitVectUnion (regsUsed, regsUsedPrologue); + + /* If this was an interrupt handler that called another function */ + /* function, then assume working registers may be modified by it. */ + if (IFFUNC_ISISR (sym->type) && IFFUNC_HASFCALL(sym->type)) + { + regsUsed = bitVectSetBit (regsUsed, AP_IDX); + regsUsed = bitVectSetBit (regsUsed, DPX1_IDX); + regsUsed = bitVectSetBit (regsUsed, DPL1_IDX); + regsUsed = bitVectSetBit (regsUsed, DPH1_IDX); + regsUsed = bitVectSetBit (regsUsed, DPX_IDX); + regsUsed = bitVectSetBit (regsUsed, DPL_IDX); + regsUsed = bitVectSetBit (regsUsed, DPH_IDX); + regsUsed = bitVectSetBit (regsUsed, DPS_IDX); + regsUsed = bitVectSetBit (regsUsed, B_IDX); + regsUsed = bitVectSetBit (regsUsed, A_IDX); + regsUsed = bitVectSetBit (regsUsed, CND_IDX); + } + + /* Remove the unneeded push/pops */ + regsUnneeded = newBitVect (ds390_nRegs); + while (lnp) + { + if (lnp->ic && (lnp->ic->op == FUNCTION || lnp->ic->op == ENDFUNCTION)) + { + if (!strncmp(lnp->line, "push", 4)) + { + idx = bitVectFirstBit (port->peep.getRegsRead(lnp)); + if (idx>=0 && !bitVectBitValue (regsUsed, idx)) + { + connectLine (lnp->prev, lnp->next); + regsUnneeded = bitVectSetBit (regsUnneeded, idx); + } + } + if (!strncmp(lnp->line, "pop", 3) || !strncmp(lnp->line, "mov", 3)) + { + idx = bitVectFirstBit (port->peep.getRegsWritten(lnp)); + if (idx>=0 && !bitVectBitValue (regsUsed, idx)) + { + connectLine (lnp->prev, lnp->next); + regsUnneeded = bitVectSetBit (regsUnneeded, idx); + } + } + } + lnp = lnp->next; + } + + for (idx = 0; idx < regsUnneeded->size; idx++) + if (bitVectBitValue (regsUnneeded, idx)) + emitcode ("", ";\teliminated unneeded push/pop %s", ds390_regWithIdx (idx)->dname); + + freeBitVect (regsUnneeded); + freeBitVect (regsUsed); + freeBitVect (regsUsedPrologue); } /*-----------------------------------------------------------------*/ @@ -3863,7 +4001,7 @@ bool aopOp3(iCode * ic) { bool dp1InUse, dp2InUse; bool useDp2; - + // First, generate the right opcode. DPTR may be used if neither left nor result are // of type AOP_STR. @@ -3919,16 +4057,34 @@ bool aopOp3(iCode * ic) } aopOp(IC_LEFT(ic), ic, FALSE, useDp2); - + + // We've op'd the left & right. So, if left or right are the same operand as result, // we know aopOp will succeed, and we can just do it & bail. - if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) || - isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic))) - { + if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic))) + { + aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic))); + return TRUE; + } + if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic))) + { // D(emitcode(";", "aopOp3: (left | right) & result equal");); - aopOp(IC_RESULT(ic),ic,TRUE, FALSE); + aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic))); return TRUE; - } + } + + // Operands may be equivalent (but not equal) if they share a spill location. If + // so, use the same DPTR or DPTR2. + if (operandsEqu (IC_LEFT(ic), IC_RESULT(ic))) + { + aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic))); + return TRUE; + } + if (operandsEqu (IC_RIGHT(ic), IC_RESULT(ic))) + { + aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_RIGHT (ic))); + return TRUE; + } // Note which dptrs are currently in use. dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic)); @@ -4566,9 +4722,11 @@ genMultOneByte (operand * left, operand * result, iCode * ic) { - sym_link *opetype = operandType (result); + int size; symbol *lbl; - + bool runtimeSign, compiletimeSign; + bool lUnsigned, rUnsigned; + /* (if two literals: the value is computed before) */ /* if one literal, literal on the right */ @@ -4580,105 +4738,197 @@ genMultOneByte (operand * left, emitcode (";", "swapped left and right"); } - if (SPEC_USIGN(opetype) - // ignore the sign of left and right, what else can we do? - || (SPEC_USIGN(operandType(left)) && - SPEC_USIGN(operandType(right)))) { - // just an unsigned 8*8=8/16 multiply - //emitcode (";","unsigned"); - emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL)); - MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL)); - emitcode ("mul", "ab"); - - _G.accInUse++; _G.bInUse++; - aopOp(result, ic, TRUE, FALSE); - - if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) - { - // this should never happen - fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", - AOP_SIZE(result), __FILE__, lineno); - exit (1); - } - - aopPut (AOP (result), "a", 0); - _G.accInUse--; _G.bInUse--; - if (AOP_SIZE(result)==2) + /* (if two literals: the value is computed before) */ + /* if one literal, literal on the right */ + if (AOP_TYPE (left) == AOP_LIT) { - aopPut (AOP (result), "b", 1); + operand *t = right; + right = left; + left = t; + /* emitcode (";", "swapped left and right"); */ + } + /* if no literal, unsigned on the right: shorter code */ + if ( AOP_TYPE (right) != AOP_LIT + && SPEC_USIGN (getSpec (operandType (left)))) + { + operand *t = right; + right = left; + left = t; } - return; - } - // we have to do a signed multiply + lUnsigned = SPEC_USIGN (getSpec (operandType (left))); + rUnsigned = SPEC_USIGN (getSpec (operandType (right))); - emitcode (";", "signed"); - emitcode ("clr", "F0"); // reset sign flag - MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL)); + if ((lUnsigned && rUnsigned) +/* sorry, I don't know how to get size + without calling aopOp (result,...); + see Feature Request */ + /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's + no need to take care about the signedness! */ + { + /* just an unsigned 8 * 8 = 8 multiply + or 8u * 8u = 16u */ + /* emitcode (";","unsigned"); */ + emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL)); + MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL)); + emitcode ("mul", "ab"); + + _G.accInUse++; _G.bInUse++; + aopOp (result, ic, TRUE, FALSE); + size = AOP_SIZE (result); + + if (size < 1 || size > 2) + { + /* this should never happen */ + fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", + size, __FILE__, lineno); + exit (1); + } + + aopPut (AOP (result), "a", 0); + _G.accInUse--; _G.bInUse--; + if (size == 2) + aopPut (AOP (result), "b", 1); + return; + } - lbl=newiTempLabel(NULL); - emitcode ("jnb", "acc.7,!tlabel", lbl->key+100); - // left side is negative, 8-bit two's complement, this fails for -128 - emitcode ("setb", "F0"); // set sign flag - emitcode ("cpl", "a"); - emitcode ("inc", "a"); + /* we have to do a signed multiply */ + /* emitcode (";", "signed"); */ + + /* now sign adjust for both left & right */ - emitcode ("", "!tlabeldef", lbl->key+100); + /* let's see what's needed: */ + /* apply negative sign during runtime */ + runtimeSign = FALSE; + /* negative sign from literals */ + compiletimeSign = FALSE; - /* if literal */ - if (AOP_TYPE(right)==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 - emitcode ("mov", "b,#!constbyte", -val); - } else { - emitcode ("mov", "b,#!constbyte", val); + if (!lUnsigned) + { + if (AOP_TYPE(left) == AOP_LIT) + { + /* signed literal */ + signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit); + if (val < 0) + compiletimeSign = TRUE; + } + else + /* signed but not literal */ + runtimeSign = TRUE; } - } else { - lbl=newiTempLabel(NULL); - emitcode ("mov", "b,a"); - emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL)); - emitcode ("jnb", "acc.7,!tlabel", lbl->key+100); - // right side is negative, 8-bit two's complement - emitcode ("cpl", "F0"); // complement sign flag - emitcode ("cpl", "a"); - emitcode ("inc", "a"); - emitcode ("", "!tlabeldef", lbl->key+100); - } + + if (!rUnsigned) + { + if (AOP_TYPE(right) == AOP_LIT) + { + /* signed literal */ + signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit); + if (val < 0) + compiletimeSign ^= TRUE; + } + else + /* signed but not literal */ + runtimeSign = TRUE; + } + + /* initialize F0, which stores the runtime sign */ + if (runtimeSign) + { + if (compiletimeSign) + emitcode ("setb", "F0"); /* set sign flag */ + else + emitcode ("clr", "F0"); /* reset sign flag */ + } + + /* save the signs of the operands */ + if (AOP_TYPE(right) == AOP_LIT) + { + signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit); + + if (!rUnsigned && val < 0) + emitcode ("mov", "b,#!constbyte", -val); + else + emitcode ("mov", "b,#!constbyte", (unsigned char) val); + } + else /* ! literal */ + { + if (rUnsigned) /* emitcode (";", "signed"); */ + emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL)); + else + { + MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL)); + lbl = newiTempLabel (NULL); + emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100); + emitcode ("cpl", "F0"); /* complement sign flag */ + emitcode ("cpl", "a"); /* 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "!tlabeldef", lbl->key + 100); + emitcode ("mov", "b,a"); + } + } + + if (AOP_TYPE(left) == AOP_LIT) + { + signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit); + + if (!lUnsigned && val < 0) + emitcode ("mov", "a,#!constbyte", -val); + else + emitcode ("mov", "a,#!constbyte", (unsigned char) val); + } + else /* ! literal */ + { + if (lUnsigned) /* emitcode (";", "signed"); */ + + emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL)); + else + { + MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL)); + lbl = newiTempLabel (NULL); + emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100); + emitcode ("cpl", "F0"); /* complement sign flag */ + emitcode ("cpl", "a"); /* 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "!tlabeldef", lbl->key + 100); + } + } + + /* now the multiplication */ emitcode ("mul", "ab"); - _G.accInUse++;_G.bInUse++; aopOp(result, ic, TRUE, FALSE); - - if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) - { - // this should never happen + size = AOP_SIZE (result); + + if (size < 1 || size > 2) + { + /* this should never happen */ fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", - AOP_SIZE(result), __FILE__, lineno); + size, __FILE__, lineno); exit (1); - } + } - lbl=newiTempLabel(NULL); - emitcode ("jnb", "F0,!tlabel", lbl->key+100); - // only ONE op was negative, we have to do a 8/16-bit two's complement - emitcode ("cpl", "a"); // lsb - if (AOP_SIZE(result)==1) { - emitcode ("inc", "a"); - } else { - emitcode ("add", "a,#1"); - emitcode ("xch", "a,b"); - emitcode ("cpl", "a"); // msb - emitcode ("addc", "a,#0"); - emitcode ("xch", "a,b"); - } - - emitcode ("", "!tlabeldef", lbl->key+100); + if (runtimeSign || compiletimeSign) + { + lbl = newiTempLabel (NULL); + if (runtimeSign) + emitcode ("jnb", "F0,!tlabel", lbl->key + 100); + emitcode ("cpl", "a"); /* lsb 2's complement */ + if (size != 2) + emitcode ("inc", "a"); /* inc doesn't set carry flag */ + else + { + emitcode ("add", "a,#1"); /* this sets carry flag */ + emitcode ("xch", "a,b"); + emitcode ("cpl", "a"); /* msb 2's complement */ + emitcode ("addc", "a,#0"); + emitcode ("xch", "a,b"); + } + emitcode ("", "!tlabeldef", lbl->key + 100); + } aopPut (AOP (result), "a", 0); _G.accInUse--;_G.bInUse--; - if (AOP_SIZE(result)==2) { + if (size == 2) aopPut (AOP (result), "b", 1); - } } /*-----------------------------------------------------------------*/ @@ -4917,94 +5167,182 @@ genDivOneByte (operand * left, operand * result, iCode * ic) { - sym_link *opetype = operandType (result); + bool lUnsigned, rUnsigned; + bool runtimeSign, compiletimeSign; char *l; symbol *lbl; int size, offset; offset = 1; + lUnsigned = SPEC_USIGN (getSpec (operandType (left))); + rUnsigned = SPEC_USIGN (getSpec (operandType (right))); + /* signed or unsigned */ - if (SPEC_USIGN (opetype)) + if (lUnsigned && rUnsigned) { - /* unsigned is easy */ - LOAD_AB_FOR_DIV (left, right, l); - emitcode ("div", "ab"); + /* unsigned is easy */ + LOAD_AB_FOR_DIV (left, right, l); + emitcode ("div", "ab"); - _G.accInUse++; - aopOp(result, ic, TRUE, FALSE); - aopPut (AOP (result), "a", 0); - _G.accInUse--; + _G.accInUse++; + aopOp (result, ic, TRUE, FALSE); + aopPut (AOP (result), "a", 0); + _G.accInUse--; - size = AOP_SIZE (result) - 1; - - while (size--) - { - aopPut (AOP (result), zero, offset++); - } + size = AOP_SIZE (result) - 1; + + while (size--) + aopPut (AOP (result), zero, offset++); return; } /* signed is a little bit more difficult */ - /* save the signs of the operands */ - MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL)); - emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE)); - emitcode ("push", "acc"); /* save it on the stack */ - /* now sign adjust for both left & right */ - MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL)); - lbl = newiTempLabel (NULL); - emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100)); - emitcode ("cpl", "a"); - emitcode ("inc", "a"); - emitcode ("", "!tlabeldef", (lbl->key + 100)); - emitcode ("mov", "b,a"); - /* sign adjust left side */ - MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL)); + /* let's see what's needed: */ + /* apply negative sign during runtime */ + runtimeSign = FALSE; + /* negative sign from literals */ + compiletimeSign = FALSE; - lbl = newiTempLabel (NULL); - emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100)); - emitcode ("cpl", "a"); - emitcode ("inc", "a"); - emitcode ("", "!tlabeldef", (lbl->key + 100)); + if (!lUnsigned) + { + if (AOP_TYPE(left) == AOP_LIT) + { + /* signed literal */ + signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit); + if (val < 0) + compiletimeSign = TRUE; + } + else + /* signed but not literal */ + runtimeSign = TRUE; + } + + if (!rUnsigned) + { + if (AOP_TYPE(right) == AOP_LIT) + { + /* signed literal */ + signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit); + if (val < 0) + compiletimeSign ^= TRUE; + } + else + /* signed but not literal */ + runtimeSign = TRUE; + } + + /* initialize F0, which stores the runtime sign */ + if (runtimeSign) + { + if (compiletimeSign) + emitcode ("setb", "F0"); /* set sign flag */ + else + emitcode ("clr", "F0"); /* reset sign flag */ + } + + /* save the signs of the operands */ + if (AOP_TYPE(right) == AOP_LIT) + { + signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit); + + if (!rUnsigned && val < 0) + emitcode ("mov", "b,#0x%02x", -val); + else + emitcode ("mov", "b,#0x%02x", (unsigned char) val); + } + else /* ! literal */ + { + if (rUnsigned) + emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL)); + else + { + MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL)); + lbl = newiTempLabel (NULL); + emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100); + emitcode ("cpl", "F0"); /* complement sign flag */ + emitcode ("cpl", "a"); /* 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "!tlabeldef", lbl->key + 100); + emitcode ("mov", "b,a"); + } + } + + if (AOP_TYPE(left) == AOP_LIT) + { + signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit); + if (!lUnsigned && val < 0) + emitcode ("mov", "a,#0x%02x", -val); + else + emitcode ("mov", "a,#0x%02x", (unsigned char) val); + } + else /* ! literal */ + { + if (lUnsigned) + emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL)); + else + { + MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL)); + lbl = newiTempLabel (NULL); + emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100); + emitcode ("cpl", "F0"); /* complement sign flag */ + emitcode ("cpl", "a"); /* 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "!tlabeldef", lbl->key + 100); + } + } + /* now the division */ emitcode ("nop", "; workaround for DS80C390 div bug."); emitcode ("div", "ab"); - /* we are interested in the lower order - only */ - emitcode ("mov", "b,a"); - lbl = newiTempLabel (NULL); - emitcode ("pop", "acc"); - /* if there was an over flow we don't - adjust the sign of the result */ - emitcode ("jb", "ov,!tlabel", (lbl->key + 100)); - emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100)); - CLRC; - emitcode ("clr", "a"); - emitcode ("subb", "a,b"); - emitcode ("mov", "b,a"); - emitcode ("", "!tlabeldef", (lbl->key + 100)); - - /* now we are done */ - _G.accInUse++; _G.bInUse++; - aopOp(result, ic, TRUE, FALSE); - - aopPut (AOP (result), "b", 0); - - size = AOP_SIZE (result) - 1; - - if (size > 0) + + if (runtimeSign || compiletimeSign) { - emitcode ("mov", "c,b.7"); - emitcode ("subb", "a,acc"); + lbl = newiTempLabel (NULL); + if (runtimeSign) + emitcode ("jnb", "F0,!tlabel", lbl->key + 100); + emitcode ("cpl", "a"); /* lsb 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "!tlabeldef", lbl->key + 100); + + _G.accInUse++; _G.bInUse++; + aopOp (result, ic, TRUE, FALSE); + size = AOP_SIZE (result) - 1; + + if (size > 0) + { + /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1) + then the result will be in b, a */ + emitcode ("mov", "b,a"); /* 1 */ + /* msb is 0x00 or 0xff depending on the sign */ + if (runtimeSign) + { + emitcode ("mov", "c,F0"); + emitcode ("subb", "a,acc"); + emitcode ("xch", "a,b"); /* 2 */ + while (size--) + aopPut (AOP (result), "b", offset++); /* write msb's */ + } + else /* compiletimeSign */ + while (size--) + aopPut (AOP (result), "#0xff", offset++); /* write msb's */ + } + aopPut (AOP (result), "a", 0); /* 3: write lsb */ } - while (size--) + else { - aopPut (AOP (result), "a", offset++); + _G.accInUse++; _G.bInUse++; + aopOp(result, ic, TRUE, FALSE); + size = AOP_SIZE (result) - 1; + + aopPut (AOP (result), "a", 0); + while (size--) + aopPut (AOP (result), zero, offset++); } - _G.accInUse--; _G.bInUse--; + _G.accInUse--; _G.bInUse--; } @@ -5200,70 +5538,146 @@ genModOneByte (operand * left, operand * result, iCode * ic) { - sym_link *opetype = operandType (result); + bool lUnsigned, rUnsigned; + bool runtimeSign, compiletimeSign; char *l; symbol *lbl; + int size, offset; + offset = 1; + lUnsigned = SPEC_USIGN (getSpec (operandType (left))); + rUnsigned = SPEC_USIGN (getSpec (operandType (right))); + /* signed or unsigned */ - if (SPEC_USIGN (opetype)) + if (lUnsigned && rUnsigned) { /* unsigned is easy */ LOAD_AB_FOR_DIV (left, right, l); emitcode ("div", "ab"); - aopOp(result, ic, TRUE, FALSE); + aopOp (result, ic, TRUE, FALSE); aopPut (AOP (result), "b", 0); + + for (size = AOP_SIZE (result) - 1; size--;) + aopPut (AOP (result), zero, offset++); return; } /* signed is a little bit more difficult */ - /* save the signs of the operands */ - MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL)); - - emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE)); - emitcode ("push", "acc"); /* save it on the stack */ - /* now sign adjust for both left & right */ - MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL)); - lbl = newiTempLabel (NULL); - emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100)); - emitcode ("cpl", "a"); - emitcode ("inc", "a"); - emitcode ("", "!tlabeldef", (lbl->key + 100)); - emitcode ("mov", "b,a"); + /* modulus: sign of the right operand has no influence on the result! */ + if (AOP_TYPE(right) == AOP_LIT) + { + signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit); - /* sign adjust left side */ - MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL)); + if (!rUnsigned && val < 0) + emitcode ("mov", "b,#0x%02x", -val); + else + emitcode ("mov", "b,#0x%02x", (unsigned char) val); + } + else /* ! literal */ + { + if (rUnsigned) + emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL)); + else + { + MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL)); + lbl = newiTempLabel (NULL); + emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100); + emitcode ("cpl", "a"); /* 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "!tlabeldef", lbl->key + 100); + emitcode ("mov", "b,a"); + } + } + + /* let's see what's needed: */ + /* apply negative sign during runtime */ + runtimeSign = FALSE; + /* negative sign from literals */ + compiletimeSign = FALSE; - lbl = newiTempLabel (NULL); - emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100)); - emitcode ("cpl", "a"); - emitcode ("inc", "a"); - emitcode ("", "!tlabeldef", (lbl->key + 100)); + /* sign adjust left side */ + if (AOP_TYPE(left) == AOP_LIT) + { + signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit); - /* now the multiplication */ + if (!lUnsigned && val < 0) + { + compiletimeSign = TRUE; /* set sign flag */ + emitcode ("mov", "a,#0x%02x", -val); + } + else + emitcode ("mov", "a,#0x%02x", (unsigned char) val); + } + else /* ! literal */ + { + MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL)); + + if (!lUnsigned) + { + runtimeSign = TRUE; + emitcode ("clr", "F0"); /* clear sign flag */ + + lbl = newiTempLabel (NULL); + emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100); + emitcode ("setb", "F0"); /* set sign flag */ + emitcode ("cpl", "a"); /* 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "!tlabeldef", lbl->key + 100); + } + } + + /* now the modulus */ emitcode ("nop", "; workaround for DS80C390 div bug."); emitcode ("div", "ab"); - /* we are interested in the lower order - only */ - lbl = newiTempLabel (NULL); - emitcode ("pop", "acc"); - /* if there was an over flow we don't - adjust the sign of the result */ - emitcode ("jb", "ov,!tlabel", (lbl->key + 100)); - emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100)); - CLRC; - emitcode ("clr", "a"); - emitcode ("subb", "a,b"); - emitcode ("mov", "b,a"); - emitcode ("", "!tlabeldef", (lbl->key + 100)); - _G.bInUse++; - /* now we are done */ - aopOp(result, ic, TRUE, FALSE); - aopPut (AOP (result), "b", 0); - _G.bInUse--; + if (runtimeSign || compiletimeSign) + { + emitcode ("mov", "a,b"); + lbl = newiTempLabel (NULL); + if (runtimeSign) + emitcode ("jnb", "F0,!tlabel", lbl->key + 100); + emitcode ("cpl", "a"); /* lsb 2's complement */ + emitcode ("inc", "a"); + emitcode ("", "!tlabeldef", lbl->key + 100); + + _G.accInUse++; _G.bInUse++; + aopOp (result, ic, TRUE, FALSE); + size = AOP_SIZE (result) - 1; + + if (size > 0) + { + /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1) + then the result will be in b, a */ + emitcode ("mov", "b,a"); /* 1 */ + /* msb is 0x00 or 0xff depending on the sign */ + if (runtimeSign) + { + emitcode ("mov", "c,F0"); + emitcode ("subb", "a,acc"); + emitcode ("xch", "a,b"); /* 2 */ + while (size--) + aopPut (AOP (result), "b", offset++); /* write msb's */ + } + else /* compiletimeSign */ + while (size--) + aopPut (AOP (result), "#0xff", offset++); /* write msb's */ + } + aopPut (AOP (result), "a", 0); /* 3: write lsb */ + } + else + { + _G.accInUse++; _G.bInUse++; + aopOp(result, ic, TRUE, FALSE); + size = AOP_SIZE (result) - 1; + + aopPut (AOP (result), "b", 0); + while (size--) + aopPut (AOP (result), zero, offset++); + } + _G.accInUse--; _G.bInUse--; } @@ -9286,12 +9700,12 @@ genNearPointerGet (operand * left, aopOp (left, ic, FALSE, FALSE); /* if left is rematerialisable and - result is not bit variable type and + result is not bitfield variable type and the left is pointer to data space i.e lower 128 bytes of space */ if (AOP_TYPE (left) == AOP_IMMD && - !IS_BITVAR (retype) && - !IS_BITVAR (letype) && + !IS_BITFIELD (retype) && + !IS_BITFIELD (letype) && DCL_TYPE (ltype) == POINTER) { genDataPointerGet (left, result, ic); @@ -9317,7 +9731,7 @@ genNearPointerGet (operand * left, aopOp (result, ic, FALSE, FALSE); /* if bitfield then unpack the bits */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) + if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) genUnpackBits (result, rname, POINTER); else { @@ -9417,7 +9831,7 @@ genPagedPointerGet (operand * left, aopOp (result, ic, FALSE, FALSE); /* if bitfield then unpack the bits */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) + if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) genUnpackBits (result, rname, PPOINTER); else { @@ -9522,7 +9936,7 @@ genFarPointerGet (operand * left, aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE)); /* if bit then unpack */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) { + if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) { if (AOP_INDPTRn(left)) { genSetDPTR(AOP(left)->aopu.dptr); } @@ -9642,7 +10056,7 @@ genCodePointerGet (operand * left, aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE)); /* if bit then unpack */ - if (IS_BITVAR (retype)) { + if (IS_BITFIELD (retype)) { if (AOP_INDPTRn(left)) { genSetDPTR(AOP(left)->aopu.dptr); } @@ -9767,7 +10181,7 @@ genGenPointerGet (operand * left, _G.bInUse--; /* if bit then unpack */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) + if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) { genUnpackBits (result, "dptr", GPOINTER); } @@ -10104,8 +10518,8 @@ genNearPointerSet (operand * right, aopOp (right, ic, FALSE, FALSE); /* if bitfield then unpack the bits */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) - genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER); + if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) + genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER); else { /* we have can just get the values */ @@ -10200,8 +10614,8 @@ genPagedPointerSet (operand * right, aopOp (right, ic, FALSE, FALSE); /* if bitfield then unpack the bits */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) - genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER); + if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) + genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER); else { /* we have can just get the values */ @@ -10307,11 +10721,11 @@ genFarPointerSet (operand * right, aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE)); /* if bit then unpack */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) { + if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) { if (AOP_INDPTRn(result)) { genSetDPTR(AOP(result)->aopu.dptr); } - genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER); + genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER); if (AOP_INDPTRn(result)) { genSetDPTR(0); } @@ -10429,9 +10843,9 @@ genGenPointerSet (operand * right, /* if bit then unpack */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) + if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) { - genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER); + genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER); } else { @@ -11117,7 +11531,7 @@ genCast (iCode * ic) if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic))) return; - aopOp (right, ic, FALSE, FALSE); + aopOp (right, ic, FALSE, AOP_IS_STR (result)); aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR)); /* if the result is a bit */ @@ -12987,6 +13401,8 @@ gen390Code (iCode * lic) for (ic = lic; ic; ic = ic->next) { + _G.current_iCode = ic; + if (ic->lineno && cln != ic->lineno) { if (options.debug)