X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fz80%2Fgen.c;h=b45d7a8516c2fe621b1cb7e75ce53458700e8f8e;hb=5a1d5e778e85664f4e6657019348b4756b16eacb;hp=697c3e09a5672f524c1a6dd40eef05448df55c9d;hpb=193aa0c8689791ae7d723d428ebd84e3d06fe7fd;p=fw%2Fsdcc diff --git a/src/z80/gen.c b/src/z80/gen.c index 697c3e09..b45d7a85 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -396,15 +396,15 @@ static void _vemit2 (const char *szFormat, va_list ap) { struct dbuf_s dbuf; - const char *buffer; + char *buffer; dbuf_init(&dbuf, INITIAL_INLINEASM); dbuf_tvprintf (&dbuf, szFormat, ap); - buffer = dbuf_c_str(&dbuf); + buffer = (char *)dbuf_c_str(&dbuf); - _tidyUp ((char *)buffer); + _tidyUp (buffer); _G.lines.current = (_G.lines.current ? connectLine (_G.lines.current, _newLineNode (buffer)) : (_G.lines.head = _newLineNode (buffer))); @@ -432,6 +432,8 @@ emit2 (const char *szFormat,...) static void emitDebug (const char *szFormat,...) { + if (!options.verboseAsm) + return; if (!DISABLE_DEBUG) { va_list ap; @@ -1383,28 +1385,62 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset) { if (pairId == PAIR_HL || pairId == PAIR_IY) { - if (_G.pairs[pairId].last_type == left->type) + if ((_G.pairs[pairId].last_type == AOP_IMMD && left->type == AOP_IMMD) || + (_G.pairs[pairId].last_type == AOP_IY && left->type == AOP_IY)) { if (_G.pairs[pairId].base && !strcmp (_G.pairs[pairId].base, base)) { if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3) { adjustPair (pair, &_G.pairs[pairId].offset, offset); - return; + goto adjusted; } if (pairId == PAIR_IY && (offset >= INT8MIN && offset <= INT8MAX)) { - return; + goto adjusted; } } } } + + if (pairId == PAIR_HL && left->type == AOP_LIT && _G.pairs[pairId].last_type == AOP_LIT && + !IS_FLOAT (left->aopu.aop_lit->type) && offset == 0 && _G.pairs[pairId].offset == 0) + { + unsigned new_low, new_high, old_low, old_high; + unsigned long v_new = ulFromVal (left->aopu.aop_lit); + unsigned long v_old = strtoul (_G.pairs[pairId].base, NULL, 0); + new_low = (v_new >> 0) & 0xff; + new_high = (v_new >> 8) & 0xff; + old_low = (v_old >> 0) & 0xff; + old_high = (v_old >> 8) & 0xff; + + /* Change lower byte only. */ + if(new_high == old_high) + { + emit2("ld l, %s", aopGet (left, 0, FALSE)); + goto adjusted; + } + /* Change upper byte only. */ + else if(new_low == old_low) + { + emit2("ld h, %s", aopGet (left, 1, FALSE)); + goto adjusted; + } + } + + _G.pairs[pairId].last_type = left->type; _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base)); _G.pairs[pairId].offset = offset; } /* Both a lit on the right and a true symbol on the left */ emit2 ("ld %s,!hashedstr", pair, l); + return; + +adjusted: + _G.pairs[pairId].last_type = left->type; + _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base)); + _G.pairs[pairId].offset = offset; } static PAIR_ID @@ -1508,8 +1544,18 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, iCode *ic, int offset) } else { - emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE)); - emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE)); + /* Operand resides (partially) in the pair */ + if(!strcmp(aopGet (aop, offset + 1, FALSE), _pairs[pairId].l)) + { + emit2 ("ld a,%s", aopGet (aop, offset + 1, FALSE)); + emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE)); + emit2 ("ld %s,a", _pairs[pairId].h); + } + else + { + emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE)); + emit2 ("ld %s,%s", _pairs[pairId].h, aopGet (aop, offset + 1, FALSE)); + } } /* PENDING: check? */ if (pairId == PAIR_HL) @@ -1637,6 +1683,14 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset) _G.pairs[pairId].last_type = aop->type; } +/* Can be used for local labels where Code generation takes care of spilling */ +static void +emitLabelNoSpill (int key) +{ + emit2 ("!tlabeldef", key); + _G.lines.current->isLabel = 1; +} + static void emitLabel (int key) { @@ -1807,11 +1861,9 @@ aopGet (asmop * aop, int offset, bool bit16) case AOP_PAIRPTR: setupPair (aop->aopu.aop_pairId, aop, offset); if (aop->aopu.aop_pairId==PAIR_IX) - SNPRINTF (buffer, sizeof(buffer), - "!*ixx", 0); + tsprintf (buffer, sizeof(buffer), "!*ixx", offset); else if (aop->aopu.aop_pairId==PAIR_IY) - SNPRINTF (buffer, sizeof(buffer), - "!*iyx", 0); + tsprintf (buffer, sizeof(buffer), "!*iyx", offset); else SNPRINTF (buffer, sizeof(buffer), "(%s)", _pairs[aop->aopu.aop_pairId].name); @@ -2523,7 +2575,7 @@ assignResultValue (operand * oper) aopPut (AOP (oper), _fReturn[size], size-1); size--; } - while (size--) + while(size--) { aopPut (AOP (oper), _fReturn[size], size); } @@ -2666,7 +2718,6 @@ genIpush (iCode * ic) { fetchHL (AOP (IC_LEFT (ic))); emit2 ("push hl"); - spillPair (PAIR_HL); _G.stack.pushed += 2; goto release; } @@ -2674,11 +2725,9 @@ genIpush (iCode * ic) { fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2); emit2 ("push hl"); - spillPair (PAIR_HL); _G.stack.pushed += 2; fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 0); emit2 ("push hl"); - spillPair (PAIR_HL); _G.stack.pushed += 2; goto release; } @@ -2946,19 +2995,6 @@ emitCall (iCode * ic, bool ispcall) /* Mark the registers as restored. */ _G.saves.saved = FALSE; - /* if we need assign a result value */ - if ((IS_ITEMP (IC_RESULT (ic)) && - (OP_SYMBOL (IC_RESULT (ic))->nRegs || - OP_SYMBOL (IC_RESULT (ic))->spildir)) || - IS_TRUE_SYMOP (IC_RESULT (ic))) - { - aopOp (IC_RESULT (ic), ic, FALSE, FALSE); - - assignResultValue (IC_RESULT (ic)); - - freeAsmop (IC_RESULT (ic), NULL, ic); - } - /* adjust the stack for parameters if required */ if (ic->parmBytes) { @@ -2993,6 +3029,19 @@ emitCall (iCode * ic, bool ispcall) } } + /* if we need assign a result value */ + if ((IS_ITEMP (IC_RESULT (ic)) && + (OP_SYMBOL (IC_RESULT (ic))->nRegs || + OP_SYMBOL (IC_RESULT (ic))->spildir)) || + IS_TRUE_SYMOP (IC_RESULT (ic))) + { + aopOp (IC_RESULT (ic), ic, FALSE, FALSE); + + assignResultValue (IC_RESULT (ic)); + + freeAsmop (IC_RESULT (ic), NULL, ic); + } + spillCached (); if (IC_RESULT (ic)) { @@ -3264,7 +3313,22 @@ genFunction (iCode * ic) else if (sym->stack && IS_GB && sym->stack > -INT8MIN) emit2 ("!enterxl", sym->stack); else if (sym->stack) - emit2 ("!enterx", sym->stack); + { + if ((optimize.codeSize && sym->stack <= 8) || sym->stack <= 4) + { + int stack = sym->stack; + emit2 ("!enter"); + while (stack > 1) + { + emit2 ("push af"); + stack -= 2; + } + if(stack > 0) + emit2 ("dec sp"); + } + else + emit2 ("!enterx", sym->stack); + } else emit2 ("!enter"); @@ -3574,7 +3638,7 @@ genPlusIncr (iCode * ic) emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); } } - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); return TRUE; } @@ -3626,7 +3690,7 @@ outBitAcc (operand * result) { emit2 ("!shortjp Z,!tlabel", tlbl->key + 100); emit2 ("ld a,!one"); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); outAcc (result); } } @@ -3834,7 +3898,16 @@ genPlus (iCode * ic) { fetchPair (PAIR_HL, AOP (IC_LEFT (ic))); emit2 ("add hl,%s", getPairName (AOP (IC_RIGHT (ic)))); - spillCached(); + spillPair (PAIR_HL); + commitPair ( AOP (IC_RESULT (ic)), PAIR_HL); + goto release; + } + + if (isPair (AOP (IC_LEFT (ic))) && AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT && getPairId (AOP (IC_LEFT (ic))) != PAIR_HL) + { + fetchPair (PAIR_HL, AOP (IC_RIGHT (ic))); + emit2 ("add hl,%s", getPairName (AOP (IC_LEFT (ic)))); + spillPair (PAIR_HL); commitPair ( AOP (IC_RESULT (ic)), PAIR_HL); goto release; } @@ -3912,28 +3985,62 @@ genPlus (iCode * ic) setupToPreserveCarry (ic); - while (size--) + /* This is ugly, but it fixes the worst code generation bug on Z80. */ + /* Probably something similar has to be done for addition of larger numbers, too. */ + if(size == 2) { - if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC) + _moveA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE)); + emit2 ("add a,%s", aopGet (AOP (IC_RIGHT (ic)), 0, FALSE)); + if(strcmp (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), aopGet (AOP (IC_LEFT (ic)), 1, FALSE))) { - _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE)); - if (offset == 0) - emit2 ("add a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); - else - emit2 ("adc a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); + aopPut (AOP (IC_RESULT (ic)), "a", 0); + _moveA (aopGet (AOP (IC_LEFT (ic)), 1, FALSE)); } else { - _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE)); - if (offset == 0) - emit2 ("add a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); + emitDebug ("; Addition result is in same register as operand of next addition."); + if(strchr (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), 'c') || + strchr (aopGet (AOP (IC_RESULT (ic)), 0, FALSE), 'b') ) + { + emit2 ("push de"); + emit2 ("ld e, a"); + emit2 ("ld a, %s", aopGet (AOP (IC_LEFT (ic)), 1, FALSE)); + emit2 ("ld d, a"); + emit2 ("ld a, e"); + emit2 ("ld %s, a", aopGet (AOP (IC_RESULT (ic)), 0, FALSE)); + emit2 ("ld a, d"); + emit2 ("pop de"); + } else - emit2 ("adc a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); + { + emit2 ("push bc"); + emit2 ("ld c, a"); + emit2 ("ld a, %s", aopGet (AOP (IC_LEFT (ic)), 1, FALSE)); + emit2 ("ld b, a"); + emit2 ("ld a, c"); + emit2 ("ld %s, a", aopGet (AOP (IC_RESULT (ic)), 0, FALSE)); + emit2 ("ld a, b"); + emit2 ("pop bc"); + } + } + emit2 ("adc a,%s", aopGet (AOP (IC_RIGHT (ic)), 1, FALSE)); + aopPut (AOP (IC_RESULT (ic)), "a", 1); + goto release; + } + + while (size--) + { + _moveA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE)); + if (offset == 0) + { + if(size == 0 && AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT && ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) == 1) + emit2 ("inc a"); + else + emit2 ("add a,%s", aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); + } + else + emit2 ("adc a,%s", aopGet (AOP (IC_RIGHT (ic)), offset, FALSE)); aopPut (AOP (IC_RESULT (ic)), "a", offset++); } @@ -4126,7 +4233,12 @@ genMinus (iCode * ic) { /* first add without previous c */ if (!offset) - emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL)); + { + if (size == 0 && (unsigned int) (lit & 0x0FFL) == 0xFF) + emit2 ("dec a"); + else + emit2 ("add a,!immedbyte", (unsigned int) (lit & 0x0FFL)); + } else emit2 ("adc a,!immedbyte", (unsigned int) ((lit >> (offset * 8)) & 0x0FFL)); } @@ -4147,6 +4259,72 @@ release: freeAsmop (IC_RESULT (ic), NULL, ic); } +/*-----------------------------------------------------------------*/ +/* genMultChar - generates code for unsigned 8x8 multiplication */ +/*-----------------------------------------------------------------*/ +static void +genMultOneChar (iCode * ic) +{ + symbol *tlbl1, *tlbl2; + bool savedB = FALSE; + + if(IS_GB) + { + wassertl (0, "Multiplication is handled through support function calls on gbz80"); + return; + } + + /* Save b into a if b is in use. */ + if (bitVectBitValue (ic->rMask, B_IDX) && + !(getPairId (AOP (IC_RESULT (ic))) == PAIR_BC)) + { + emit2 ("ld a, b"); + savedB = TRUE; + } + if (isPairInUse (PAIR_DE, ic) && + !(getPairId (AOP (IC_RESULT (ic))) == PAIR_DE)) + { + _push (PAIR_DE); + _G.stack.pushedDE = TRUE; + } + + tlbl1 = newiTempLabel (NULL); + tlbl2 = newiTempLabel (NULL); + + emit2 ("ld e,%s", aopGet (AOP (IC_RIGHT (ic)), LSB, FALSE)); + emit2 ("ld h,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE)); + emit2 ("ld l,#0x00"); + emit2 ("ld d,l"); + emit2 ("ld b,#0x08"); + emitLabelNoSpill (tlbl1->key + 100); + emit2 ("add hl,hl"); + emit2 ("jp NC,!tlabel", tlbl2->key + 100); + emit2 ("add hl,de"); + emitLabelNoSpill (tlbl2->key + 100); + emit2 ("djnz !tlabel", tlbl1->key + 100); + + spillPair(PAIR_HL); + + if (IS_Z80 && _G.stack.pushedDE) + { + _pop (PAIR_DE); + _G.stack.pushedDE = FALSE; + } + if (savedB) + { + emit2 ("ld b, a"); + } + + if (AOP_SIZE (IC_RESULT (ic)) == 1) + aopPut (AOP (IC_RESULT (ic)), "l", 0); + else + commitPair ( AOP (IC_RESULT (ic)), PAIR_HL); + + freeAsmop (IC_LEFT (ic), NULL, ic); + freeAsmop (IC_RIGHT (ic), NULL, ic); + freeAsmop (IC_RESULT (ic), NULL, ic); +} + /*-----------------------------------------------------------------*/ /* genMult - generates code for multiplication */ /*-----------------------------------------------------------------*/ @@ -4181,6 +4359,12 @@ genMult (iCode * ic) IC_LEFT (ic) = t; } + if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) + { + genMultOneChar (ic); + return; + } + wassertl (AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT, "Right must be a literal"); val = (int) ulFromVal ( AOP (IC_RIGHT (ic))->aopu.aop_lit); @@ -4192,7 +4376,9 @@ genMult (iCode * ic) _G.stack.pushedDE = TRUE; } - if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic))))) + if (byteResult) + emit2 ("ld a,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE)); + else if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic))))) { emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE)); if (!byteResult) @@ -4210,32 +4396,40 @@ genMult (iCode * ic) i = val; - /* Fully unroled version of mul.s. Not the most efficient. - */ for (count = 0; count < 16; count++) { if (count != 0 && active) { - emit2 ("add hl,hl"); + if (byteResult) + emit2 ("add a,a"); + else + emit2 ("add hl,hl"); } if (i & 0x8000U) { if (active == FALSE) { - emit2 ("ld l,e"); - if (!byteResult) - emit2 ("ld h,d"); + if (byteResult) + emit2("ld e,a"); + else + { + emit2 ("ld l,e"); + emit2 ("ld h,d"); + } } else { - emit2 ("add hl,de"); + if (byteResult) + emit2 ("add a,e"); + else + emit2 ("add hl,de"); } active = TRUE; } i <<= 1; } - spillCached(); + spillPair(PAIR_HL); if (IS_Z80 && _G.stack.pushedDE) { @@ -4244,7 +4438,7 @@ genMult (iCode * ic) } if (byteResult) - aopPut (AOP (IC_RESULT (ic)), _pairs[PAIR_HL].l, 0); + aopPut (AOP (IC_RESULT (ic)), "a", 0); else commitPair ( AOP (IC_RESULT (ic)), PAIR_HL); @@ -4709,13 +4903,16 @@ genCmpGt (iCode * ic, iCode * ifx) letype = getSpec (operandType (left)); retype = getSpec (operandType (right)); sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype)); - /* assign the amsops */ + /* assign the asmops */ aopOp (left, ic, FALSE, FALSE); aopOp (right, ic, FALSE, FALSE); aopOp (result, ic, TRUE, FALSE); + setupToPreserveCarry (ic); + genCmp (right, left, result, ifx, sign); + _G.preserveCarry = FALSE; freeAsmop (left, NULL, ic); freeAsmop (right, NULL, ic); freeAsmop (result, NULL, ic); @@ -4739,13 +4936,16 @@ genCmpLt (iCode * ic, iCode * ifx) retype = getSpec (operandType (right)); sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype)); - /* assign the amsops */ + /* assign the asmops */ aopOp (left, ic, FALSE, FALSE); aopOp (right, ic, FALSE, FALSE); aopOp (result, ic, TRUE, FALSE); + setupToPreserveCarry (ic); + genCmp (left, right, result, ifx, sign); + _G.preserveCarry = FALSE; freeAsmop (left, NULL, ic); freeAsmop (right, NULL, ic); freeAsmop (result, NULL, ic); @@ -4825,7 +5025,7 @@ gencjneshort (operand * left, operand * right, symbol * lbl) } else { - emit2 ("sub %s", aopGet (AOP (right), offset, FALSE)); + emit2 ("sub a,%s", aopGet (AOP (right), offset, FALSE)); emit2 ("jp NZ,!tlabel", lbl->key + 100); } offset++; @@ -4849,7 +5049,7 @@ gencjneshort (operand * left, operand * right, symbol * lbl) emit2 ("; direct compare"); _emitMove (_pairs[pair].l, aopGet (AOP (left), offset, FALSE)); _moveA (aopGet (AOP (right), offset, FALSE)); - emit2 ("sub %s", _pairs[pair].l); + emit2 ("sub a,%s", _pairs[pair].l); emit2 ("!shortjp NZ,!tlabel", lbl->key + 100); offset++; } @@ -4873,7 +5073,7 @@ gencjne (operand * left, operand * right, symbol * lbl) emit2 ("!shortjp !tlabel", tlbl->key + 100); emitLabel (lbl->key + 100); emit2 ("xor a,a"); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); _pop (pop); } @@ -4919,7 +5119,7 @@ genCmpEq (iCode * ic, iCode * ifx) { _pop (pop); emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); _pop (pop); } else @@ -4928,10 +5128,10 @@ genCmpEq (iCode * ic, iCode * ifx) symbol *lbl = newiTempLabel (NULL); _pop (pop); emit2 ("!shortjp !tlabel", lbl->key + 100); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); _pop (pop); emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100); - emitLabel (lbl->key + 100); + emitLabelNoSpill (lbl->key + 100); } } /* mark the icode as generated */ @@ -5026,7 +5226,7 @@ genAndOp (iCode * ic) _toBoolean (left); emit2 ("!shortjp Z,!tlabel", tlbl->key + 100); _toBoolean (right); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); outBitAcc (result); } @@ -5063,7 +5263,7 @@ genOrOp (iCode * ic) _toBoolean (left); emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); _toBoolean (right); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); outBitAcc (result); } @@ -5105,14 +5305,14 @@ jmpTrueOrFalse (iCode * ic, symbol * tlbl) { symbol *nlbl = newiTempLabel (NULL); emit2 ("jp !tlabel", nlbl->key + 100); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100); - emitLabel (nlbl->key + 100); + emitLabelNoSpill (nlbl->key + 100); } else { emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); } ic->generated = 1; } @@ -5195,6 +5395,7 @@ genAnd (iCode * ic, iCode * ifx) /* For the flags */ emit2 ("or a,a"); } + if (size || ifx) /* emit jmp only, if it is actually used */ emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); } offset++; @@ -5378,9 +5579,19 @@ genOr (iCode * ic, iCode * ifx) bytelit = (lit >> (offset * 8)) & 0x0FFL; _moveA (aopGet (AOP (left), offset, FALSE)); - /* OR with any literal is the same as OR with itself. */ - emit2 ("or a,a"); - emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); + + if (bytelit != 0) + { /* FIXME, allways true, shortcut possible */ + emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE)); + } + else + { + /* For the flags */ + emit2 ("or a,a"); + } + + if (ifx) /* emit jmp only, if it is actually used */ + emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); offset++; } @@ -5785,7 +5996,7 @@ shiftR2Left2Result (operand * left, int offl, { emit2 ("ld a,!immedbyte", shCount); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); emitRsh2 (AOP (result), size, is_signed); @@ -5859,7 +6070,7 @@ shiftL2Left2Result (operand * left, int offl, { emit2 ("ld a,!immedbyte+1", shCount); emit2 ("!shortjp !tlabel", tlbl1->key + 100); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); } while (size--) @@ -5879,7 +6090,7 @@ shiftL2Left2Result (operand * left, int offl, } if (shCount > 1) { - emitLabel (tlbl1->key + 100); + emitLabelNoSpill (tlbl1->key + 100); emit2 ("dec a"); emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); } @@ -6010,13 +6221,25 @@ shiftL1Left2Result (operand * left, int offl, operand * result, int offr, int shCount) { const char *l; - l = aopGet (AOP (left), offl, FALSE); - _moveA (l); - /* shift left accumulator */ - AccLsh (shCount); - aopPut (AOP (result), "a", offr); -} + /* If operand and result are the same we can shift in place. + However shifting in acc using add is cheaper than shifting + in place using sla; when shifting by more than 2 shifting in + acc is worth the additional effort for loading from/to acc. */ + if (sameRegs (AOP (left), AOP (result)) && shCount <= 2 && offr == offl) + { + while (shCount--) + emit2 ("sla %s", aopGet (AOP (result), 0, FALSE)); + } + else + { + l = aopGet (AOP (left), offl, FALSE); + _moveA (l); + /* shift left accumulator */ + AccLsh (shCount); + aopPut (AOP (result), "a", offr); + } +} /*-----------------------------------------------------------------*/ /* genlshTwo - left shift two bytes by known amount */ @@ -6186,7 +6409,7 @@ genLeftShift (iCode * ic) _pop (PAIR_AF); emit2 ("!shortjp !tlabel", tlbl1->key + 100); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); l = aopGet (AOP (result), offset, FALSE); while (size--) @@ -6203,7 +6426,7 @@ genLeftShift (iCode * ic) } offset++; } - emitLabel (tlbl1->key + 100); + emitLabelNoSpill (tlbl1->key + 100); emit2 ("dec a"); emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); @@ -6461,7 +6684,7 @@ genRightShift (iCode * ic) _pop (PAIR_AF); emit2 ("!shortjp !tlabel", tlbl1->key + 100); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); while (size--) { l = aopGet (AOP (result), offset--, FALSE); @@ -6475,7 +6698,7 @@ genRightShift (iCode * ic) emit2 ("rr %s", l); } } - emitLabel (tlbl1->key + 100); + emitLabelNoSpill (tlbl1->key + 100); emit2 ("dec a"); emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100); @@ -6518,7 +6741,7 @@ genUnpackBits (operand * result, int pair) emit2 ("bit %d,a", blen - 1); emit2 ("jp Z,!tlabel", tlbl->key + 100); emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen)); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); } aopPut (AOP (result), "a", offset++); goto finish; @@ -6538,11 +6761,10 @@ genUnpackBits (operand * result, int pair) { /* signed bitfield */ symbol *tlbl = newiTempLabel (NULL); - - emit2 ("bit %d,a", blen - 1); + emit2 ("bit %d,a", blen - 1 - 8); emit2 ("jp Z,!tlabel", tlbl->key + 100); - emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen)); - emitLabel (tlbl->key + 100); + emit2 ("or a,!immedbyte", (unsigned char) (0xff << (blen - 8))); + emitLabelNoSpill (tlbl->key + 100); } emit2 ("ld h,a"); spillPair (PAIR_HL); @@ -6575,7 +6797,7 @@ genUnpackBits (operand * result, int pair) emit2 ("bit %d,a", rlen - 1); emit2 ("jp Z,!tlabel", tlbl->key + 100); emit2 ("or a,!immedbyte", (unsigned char) (0xff << rlen)); - emitLabel (tlbl->key + 100); + emitLabelNoSpill (tlbl->key + 100); } aopPut (AOP (result), "a", offset++); } @@ -7119,7 +7341,7 @@ genAddrOf (iCode * ic) { if (sym->onStack) { - spillCached (); + spillPair (PAIR_HL); if (sym->stack <= 0) { setupPairFromSP (PAIR_HL, sym->stack + _G.stack.pushed + _G.stack.offset); @@ -7138,7 +7360,7 @@ genAddrOf (iCode * ic) } else { - spillCached (); + spillPair (PAIR_HL); if (sym->onStack) { /* if it has an offset then we need to compute it */ @@ -7318,7 +7540,7 @@ genJumpTab (iCode * ic) emit2 ("ld e,%s", l); emit2 ("ld d,!zero"); jtab = newiTempLabel (NULL); - spillCached (); + spillPair (PAIR_HL); emit2 ("ld hl,!immed!tlabel", jtab->key + 100); emit2 ("add hl,de"); emit2 ("add hl,de"); @@ -7403,8 +7625,7 @@ genCast (iCode * ic) else { /* we need to extend the sign :{ */ - const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1, - FALSE); + const char *l = aopGet (AOP (right), AOP_SIZE (right) - 1, FALSE); _moveA (l); emit2 ("rla "); emit2 ("sbc a,a"); @@ -7526,7 +7747,7 @@ genCritical (iCode *ic) //disable interrupt emit2 ("!di"); //save P/O flag - emit2 ("push af"); + _push (PAIR_AF); } } @@ -7555,7 +7776,7 @@ genEndCritical (iCode *ic) else { //restore P/O flag - emit2 ("pop af"); + _pop (PAIR_AF); //parity odd <==> P/O=0 <==> interrupt enable flag IFF2 was 0 <==> //don't enable interrupts as they were off before emit2 ("jp PO,!tlabel", tlbl->key + 100); @@ -7832,67 +8053,12 @@ _swap (PAIR_ID one, PAIR_ID two) } } -/* The problem is that we may have all three pairs used and they may - be needed in a different order. - - Note: Have ex de,hl - - Combinations: - hl = hl => unity, fine - bc = bc - de = de - - hl = hl hl = hl, swap de <=> bc - bc = de - de = bc - - hl = bc Worst case - bc = de - de = hl - - hl = bc de = de, swap bc <=> hl - bc = hl - de = de - - hl = de Worst case - bc = hl - de = bc - - hl = de bc = bc, swap hl <=> de - bc = bc - de = hl - - Break it down into: - * Any pair = pair are done last - * Any pair = iTemp are done last - * Any swaps can be done any time - - A worst case: - push p1 - p1 = p2 - p2 = p3 - pop p3 - - So how do we detect the cases? - How about a 3x3 matrix? - source - dest x x x x - x x x x - x x x x (Fourth for iTemp/other) - - First determin which mode to use by counting the number of unity and - iTemp assigns. - Three - any order - Two - Assign the pair first, then the rest - One - Swap the two, then the rest - Zero - Worst case. -*/ static void -setupForBuiltin3 (iCode *ic, int nparams, operand **pparams) +setupForMemcpy (iCode *ic, int nparams, operand **pparams) { PAIR_ID ids[NUM_PAIRS][NUM_PAIRS]; PAIR_ID dest[3] = { - PAIR_BC, PAIR_HL, PAIR_DE + PAIR_DE, PAIR_HL, PAIR_BC }; int i, j, nunity = 0; memset (ids, PAIR_INVALID, sizeof (ids)); @@ -7900,10 +8066,6 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams) /* Sanity checks */ wassert (nparams == 3); - /* First save everything that needs to be saved. */ - _saveRegsForCall (ic, 0); - - /* Loading HL first means that DE is always fine. */ for (i = 0; i < nparams; i++) { aopOp (pparams[i], ic, FALSE, FALSE); @@ -7925,7 +8087,7 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams) } else if (nunity == 2) { - /* One is assigned. Pull it out and assign. */ + /* Two are OK. Assign the other one. */ for (i = 0; i < 3; i++) { for (j = 0; j < NUM_PAIRS; j++) @@ -7948,7 +8110,7 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams) } else if (nunity == 1) { - /* Find the pairs to swap. */ + /* One is OK. Find the other two. */ for (i = 0; i < 3; i++) { for (j = 0; j < NUM_PAIRS; j++) @@ -7957,12 +8119,22 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams) { if (j == PAIR_INVALID || j == dest[i]) { - /* Keep looking. */ + /* This one is OK. */ } else { - _swap (j, dest[i]); - goto done; + /* Found one. */ + if(ids[j][dest[i]] == TRUE) + { + /* Just swap. */ + _swap (j, dest[i]); + goto done; + } + else + { + fetchPair (dest[i], AOP (pparams[i])); + continue; + } } } } @@ -7996,53 +8168,27 @@ setupForBuiltin3 (iCode *ic, int nparams, operand **pparams) } } -static void -genBuiltInStrcpy (iCode *ic, int nParams, operand **pparams) -{ - operand *from, *to; - symbol *label; - bool deInUse; - - wassertl (nParams == 2, "Built-in strcpy must have two parameters"); - to = pparams[0]; - from = pparams[1]; - - deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX); - - setupForBuiltin3 (ic, nParams, pparams); - - label = newiTempLabel(NULL); - - emitLabel (label->key); - emit2 ("ld a,(hl)"); - emit2 ("ldi"); - emit2 ("or a"); - emit2 ("!shortjp NZ,!tlabel ; 1", label->key); - - freeAsmop (from, NULL, ic->next); - freeAsmop (to, NULL, ic); -} - static void genBuiltInMemcpy (iCode *ic, int nParams, operand **pparams) { operand *from, *to, *count; - bool deInUse; - wassertl (nParams == 3, "Built-in memcpy must have two parameters"); + wassertl (nParams == 3, "Built-in memcpy() must have three parameters"); to = pparams[2]; from = pparams[1]; count = pparams[0]; - deInUse = bitVectBitValue (ic->rMask, D_IDX) || bitVectBitValue(ic->rMask, E_IDX); + _saveRegsForCall (ic, 0); - setupForBuiltin3 (ic, nParams, pparams); + setupForMemcpy (ic, nParams, pparams); emit2 ("ldir"); freeAsmop (count, NULL, ic->next->next); freeAsmop (from, NULL, ic); + spillPair (PAIR_HL); + _restoreRegsAfterCall(); /* if we need assign a result value */ @@ -8076,11 +8222,7 @@ static void genBuiltIn (iCode *ic) /* which function is it */ bif = OP_SYMBOL(IC_LEFT(bi_iCode)); - if (strcmp(bif->name,"__builtin_strcpy")==0) - { - genBuiltInStrcpy(bi_iCode, nbi_parms, bi_parms); - } - else if (strcmp(bif->name,"__builtin_memcpy")==0) + if (strcmp(bif->name,"__builtin_memcpy")==0) { genBuiltInMemcpy(bi_iCode, nbi_parms, bi_parms); }