#include <ctype.h>
#include "common.h"
+#include "main.h"
#include "ralloc.h"
#include "gen.h"
#include "SDCCglobl.h"
short dptrInUse;
short dptr1InUse;
set *sendSet;
+ iCode *current_iCode;
}
_G;
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 */
lineCurr->isInline = _G.inLine;
lineCurr->isDebug = _G.debugLine;
+ lineCurr->ic = _G.current_iCode;
+ lineCurr->aln = ds390newAsmLineNode(_currentDPS);
va_end (ap);
}
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 */
}
+/*-----------------------------------------------------------------*/
+/* 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 */
/*-----------------------------------------------------------------*/
{
asmop *aop;
memmap *space = SPEC_OCLS (sym->etype);
+ int accuse = leftRightUseAcc (ic);
/* 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 */
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");
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
if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
if (useDP2) {
if (options.model == MODEL_FLAT24)
- emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
- TR_DPTR("#2");
+ {
+ emitcode ("mov", "dpx1,#!constbyte",
+ (options.stack_loc >> 16) & 0xff);
+ }
emitcode ("mov", "dph1,_bpx+1");
+
emitcode ("mov", "dpl1,_bpx");
emitcode ("mov","dps,#1");
} else {
if (options.model == MODEL_FLAT24)
- emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
+ {
+ emitcode ("mov", "dpx,#!constbyte",
+ (options.stack_loc >> 16) & 0xff);
+ }
emitcode ("mov", "dph,_bpx+1");
emitcode ("mov", "dpl,_bpx");
}
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");
emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
if (useDP2) {
if (options.model == MODEL_FLAT24)
- emitcode ("mov", "dpx1,#!constbyte", (options.stack_loc >> 16) & 0xff);
- TR_DPTR("#2");
+ {
+ emitcode ("mov", "dpx1,#!constbyte",
+ (options.stack_loc >> 16) & 0xff);
+ }
emitcode ("mov", "dph1,a");
emitcode ("mov", "dpl1,b");
} else {
if (options.model == MODEL_FLAT24)
- emitcode ("mov", "dpx,#!constbyte", (options.stack_loc >> 16) & 0xff);
+ {
+ emitcode ("mov", "dpx,#!constbyte",
+ (options.stack_loc >> 16) & 0xff);
+ }
emitcode ("mov", "dph,a");
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));
}
/* 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));
(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;
}
/* 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 */
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;
}
/* depending on type */
switch (aop->type)
{
+ case AOP_DUMMY:
+ return zero;
case AOP_R0:
case AOP_R1:
/* 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)
{
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 */
genNot (iCode * ic)
{
symbol *tlbl;
- sym_link *optype = operandType (IC_LEFT (ic));
D (emitcode (";", "genNot "););
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);
/* 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 */
/* if the registers have been saved already then
do nothing */
- if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) return ;
+ if (ic->regsSaved
+ || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
+ return ;
/* special case if DPTR alive across a function call then must save it
even though callee saves */
- if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
+ if (IS_SYMOP(IC_LEFT(ic)) &&
+ IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
int i;
rsave = newBitVect(ic->rMask->size);
for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
}
}
+static void
+adjustEsp(const char *reg)
+{
+ emitcode ("anl","%s,#3", reg);
+ if (TARGET_IS_DS400)
+ {
+ emitcode ("orl","%s,#!constbyte",
+ reg,
+ (options.stack_loc >> 8) & 0xff);
+ }
+}
+
/*-----------------------------------------------------------------*/
/* genCall - generates a call statement */
/*-----------------------------------------------------------------*/
the same register bank then we need to save the
destination registers on the stack */
dtype = operandType (IC_LEFT (ic));
- if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
+ if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
(FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
IFFUNC_ISISR (currFunc->type))
{
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)
}
else
{
- _G.accInUse++;
+ _G.bInUse++;
aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
- _G.accInUse--;
+ _G.bInUse--;
assignResultValue (IC_RESULT (ic));
emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
emitcode ("mov","sp,a");
emitcode ("mov","a,esp");
- emitcode ("anl","a,#3");
+ adjustEsp("a");
emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
emitcode ("mov","esp,a");
UNPROTECT_SP;
the same register bank then we need to save the
destination registers on the stack */
dtype = operandType (IC_LEFT (ic));
- if (currFunc && dtype && !IFFUNC_ISNAKED(dtype) &&
+ if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
IFFUNC_ISISR (currFunc->type) &&
(FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
emitcode ("mov","sp,a");
emitcode ("mov","a,esp");
- emitcode ("anl","a,#3");
+ adjustEsp("a");
emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
emitcode ("mov","esp,a");
UNPROTECT_SP;
/*-----------------------------------------------------------------*/
/* inExcludeList - return 1 if the string is in exclude Reg list */
/*-----------------------------------------------------------------*/
+static int
+regsCmp(void *p1, void *p2)
+{
+ return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
+}
+
static bool
inExcludeList (char *s)
{
- int i = 0;
+ const char *p = setFirstItem(options.excludeRegsSet);
- if (options.excludeRegs[i] &&
- STRCASECMP (options.excludeRegs[i], "none") == 0)
+ if (p == NULL || STRCASECMP(p, "none") == 0)
return FALSE;
- for (i = 0; options.excludeRegs[i]; i++)
- {
- if (options.excludeRegs[i] &&
- STRCASECMP (s, options.excludeRegs[i]) == 0)
- return TRUE;
- }
- return FALSE;
+
+ return isinSetWith(options.excludeRegsSet, s, regsCmp);
}
/*-----------------------------------------------------------------*/
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 */
/* 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
{
}
}
}
- // jwk: this needs a closer look
+ // TODO: this needs a closer look
SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
}
}
/* 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++;
emitcode ("push","_bpx+1");
emitcode ("mov","_bpx,%s",spname);
emitcode ("mov","_bpx+1,esp");
- emitcode ("anl","_bpx+1,#3");
+ adjustEsp("_bpx+1");
} else {
if (options.useXstack) {
emitcode ("mov", "r0,%s", spname);
emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
emitcode ("mov","sp,a");
emitcode ("mov","a,esp");
- emitcode ("anl","a,#3");
+ adjustEsp("a");
emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
emitcode ("mov","esp,a");
UNPROTECT_SP;
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 */
+ }
}
genEndFunction (iCode * ic)
{
symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+ lineNode *lnp = lineCurr;
+ bitVect *regsUsed;
+ bitVect *regsUsedPrologue;
+ bitVect *regsUnneeded;
+ int idx;
D (emitcode (";", "genEndFunction "););
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))) {
/* 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
{
* Restore any register banks saved by genFunction
* in reverse order.
*/
- // jwk: this needs a closer look
unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
int ix;
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;
}
else
{
- if (IFFUNC_ISCRITICAL (sym->type))
- emitcode ("setb", "ea");
-
if (IFFUNC_CALLEESAVES(sym->type))
{
int i;
/* 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 */
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);
}
/*-----------------------------------------------------------------*/
{
bool dp1InUse, dp2InUse;
bool useDp2;
-
+
// First, generate the right opcode. DPTR may be used if neither left nor result are
// of type AOP_STR.
// AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
// AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
// AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
-// );
-
+// );
- // Right uses DPTR unless left or result is an AOP_STR.
- aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)));
+ // Right uses DPTR unless left or result is an AOP_STR; however,
+ // if right is an AOP_STR, it must use DPTR regardless.
+ if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
+ && !AOP_IS_STR(IC_RIGHT(ic)))
+ {
+ useDp2 = TRUE;
+ }
+ else
+ {
+ useDp2 = FALSE;
+ }
+
+ aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
// if the right used DPTR, left MUST use DPTR2.
// if the right used DPTR2, left MUST use DPTR.
}
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));
if ( AOP_IS_STR(IC_LEFT(ic)) &&
isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
- size = floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
+ size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
if (size <= 9) {
while (size--) emitcode ("inc","dptr");
} else {
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 */
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=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);
- }
- 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);
- }
-
- 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);
- aopPut (AOP (result), "a", 0);
- _G.accInUse--;_G.bInUse--;
- if (AOP_SIZE(result)==2) {
+ 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);
+ 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);
+ }
+
+ 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 (size == 2)
aopPut (AOP (result), "b", 1);
- }
}
/*-----------------------------------------------------------------*/
if (!umult) {
emitcode("clr","F0");
if (AOP_TYPE(right) == AOP_LIT) {
- int val=floatFromVal (AOP (right)->aopu.aop_lit);
+ int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
if (val < 0) {
emitcode("setb","F0");
val = -val;
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--;
}
/* load up MB with right */
if (!umult) {
if (AOP_TYPE(right) == AOP_LIT) {
- int val=floatFromVal (AOP (right)->aopu.aop_lit);
+ int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
if (val < 0) {
lbl = newiTempLabel(NULL);
emitcode ("jbc","F0,!tlabel",lbl->key+100);
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--;
}
/* load up MB with right */
if (!umult) {
if (AOP_TYPE(right) == AOP_LIT) {
- int val=floatFromVal (AOP (right)->aopu.aop_lit);
+ int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
if (val < 0) {
val = -val;
}
AOP_TYPE (right) == AOP_CRY)
{
emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
- emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
+ emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
}
else
{
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;
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)))
{
{
if (ifx)
jmpTrueOrFalse (ifx, tlbl);
+ else
+ emitcode ("", "!tlabeldef", tlbl->key + 100);
goto release;
}
}
}
else if (ifx)
jmpTrueOrFalse (ifx, tlbl);
+ else
+ emitcode ("", "!tlabeldef", tlbl->key + 100);
}
else
{
}
else if (ifx)
jmpTrueOrFalse (ifx, tlbl);
+ else
+ emitcode ("", "!tlabeldef", tlbl->key + 100);
}
else
{
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 */
/*-----------------------------------------------------------------*/
}
#endif
-#if 0
-//REMOVE ME!!!
/*-----------------------------------------------------------------*/
/* shiftLLeftOrResult - shift left one byte from left, or to result */
/*-----------------------------------------------------------------*/
/* back to result */
aopPut (AOP (result), "a", offr);
}
-#endif
#if 0
//REMOVE ME!!!
}
#endif
-#if 0
-//REMOVE ME!!!
/*-----------------------------------------------------------------*/
/* shiftRLong - shift right one long from left to result */
/* offl = LSB or MSB16 */
werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
}
- MOVA (aopGet (AOP (left), MSB32, FALSE, NULL));
+ MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
if (offl==MSB16) {
// shift is > 8
emitcode ("rlc", "a");
emitcode ("subb", "a,acc");
emitcode ("xch", "a,%s",
- aopGet(AOP(left), MSB32, FALSE, DP2_RESULT_REG));
+ aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
} else {
aopPut (AOP(result), zero, MSB32);
}
if (isSameRegs && offl==MSB16) {
emitcode ("xch",
- "a,%s",aopGet (AOP (left), MSB24, FALSE, DP2_RESULT_REG));
+ "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
} else {
aopPut (AOP (result), "a", MSB32);
- MOVA (aopGet (AOP (left), MSB24, FALSE, NULL));
+ MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
}
emitcode ("rrc", "a");
if (isSameRegs && offl==1) {
emitcode ("xch", "a,%s",
- aopGet (AOP (left), MSB16, FALSE, DP2_RESULT_REG));
+ aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
} else {
aopPut (AOP (result), "a", MSB24);
- MOVA (aopGet (AOP (left), MSB16, FALSE, NULL));
+ MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
}
emitcode ("rrc", "a");
aopPut (AOP (result), "a", MSB16 - offl);
if (offl == LSB)
{
- MOVA (aopGet (AOP (left), LSB, FALSE, NULL));
+ MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
emitcode ("rrc", "a");
aopPut (AOP (result), "a", LSB);
}
}
-#endif
-#if 0
-//REMOVE ME!!!
/*-----------------------------------------------------------------*/
/* genrshFour - shift four byte by a known amount != 0 */
/*-----------------------------------------------------------------*/
genrshFour (operand * result, operand * left,
int shCount, int sign)
{
- D (emitcode (";", "genrshFour");
- );
+ D (emitcode (";", "genrshFour"););
/* if shifting more that 3 bytes */
if (shCount >= 24)
{
shCount -= 24;
+ _startLazyDPSEvaluation();
if (shCount)
shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
else
movLeft2Result (left, MSB32, result, LSB, sign);
addSign (result, MSB16, sign);
+ _endLazyDPSEvaluation();
}
else if (shCount >= 16)
{
shCount -= 16;
+ _startLazyDPSEvaluation();
if (shCount)
shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
else
movLeft2Result (left, MSB32, result, MSB16, sign);
}
addSign (result, MSB24, sign);
+ _endLazyDPSEvaluation();
}
else if (shCount >= 8)
{
shCount -= 8;
+ _startLazyDPSEvaluation();
if (shCount == 1)
- shiftRLong (left, MSB16, result, sign);
+ {
+ shiftRLong (left, MSB16, result, sign);
+ }
else if (shCount == 0)
{
movLeft2Result (left, MSB16, result, LSB, 0);
shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
addSign (result, MSB32, sign);
}
+ _endLazyDPSEvaluation();
}
else
- { /* 1 <= shCount <= 7 */
+ {
+ /* 1 <= shCount <= 7 */
if (shCount <= 2)
{
shiftRLong (left, LSB, result, sign);
}
}
}
-#endif
#ifdef BETTER_LITERAL_SHIFT
/*-----------------------------------------------------------------*/
if ((shCount != 0)
&& (shCount < (size * 8))
&& (size != 1)
- && (size != 2))
+ && (size != 2)
+ && (size != 4))
{
- D(emitcode (";", "genRightShiftLiteral wimping out"););
+ D(emitcode (";", "genRightShiftLiteral wimping out"););
return FALSE;
}
case 2:
genrshTwo (result, left, shCount, sign);
break;
-#if 0
+#if 1
case 4:
genrshFour (result, left, shCount, sign);
break;
genRightShift (iCode * ic)
{
operand *right, *left, *result;
- sym_link *retype;
+ sym_link *letype;
int size, offset;
char *l;
symbol *tlbl, *tlbl1;
/* 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;
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;
-
- case CPOINTER:
- emitcode ("clr", "a");
- emitcode ("inc", "dptr");
- emitcode ("movc", "a,@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 GPOINTER:
- emitcode ("inc", "dptr");
- emitcode ("lcall", "__gptrget");
- break;
- }
+ D(emitcode ("; genUnpackBits",""));
- 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++);
+ }
}
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);
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
{
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
{
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);
}
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);
}
_G.bInUse--;
/* if bit then unpack */
- if (IS_BITVAR (retype) || IS_BITVAR (letype))
+ if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
{
genUnpackBits (result, "dptr", GPOINTER);
}
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 */
/*-----------------------------------------------------------------*/
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 */
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 */
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);
}
/* 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
{
/* if 10 bit stack */
if (options.stack10bit) {
char buff[10];
+ int offset;
+
tsprintf(buff, sizeof(buff),
"#!constbyte",(options.stack_loc >> 16) & 0xff);
/* if it has an offset then we need to compute it */
((char) sym->stack )) & 0xff);
emitcode ("mov", "b,a");
emitcode ("mov", "a,_bpx+1");
- emitcode ("addc","a,#!constbyte", (((sym->stack < 0) ?
- ((short) (sym->stack - _G.nRegsSaved)) :
- ((short) sym->stack )) >> 8) & 0xff);
+
+ offset = (((sym->stack < 0) ?
+ ((short) (sym->stack - _G.nRegsSaved)) :
+ ((short) sym->stack )) >> 8) & 0xff;
+
+ emitcode ("addc","a,#!constbyte", offset);
+
aopPut (AOP (IC_RESULT (ic)), "b", 0);
aopPut (AOP (IC_RESULT (ic)), "a", 1);
aopPut (AOP (IC_RESULT (ic)), buff, 2);
}
+#if 0 // obsolete, and buggy for != xdata
/*-----------------------------------------------------------------*/
/* genArrayInit - generates code for address of */
/*-----------------------------------------------------------------*/
freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
}
+#endif
/*-----------------------------------------------------------------*/
/* genFarFarAssign - assignment when both are in far space */
if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
return;
- aopOp (right, ic, FALSE, FALSE);
- aopOp (result, ic, FALSE, AOP_USESDPTR(right));
+ aopOp (right, ic, FALSE, AOP_IS_STR (result));
+ 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 */
/* also, if the source is a bit, we don't need to sign extend, because
* it can't possibly have set the sign bit.
*/
- if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE (right) == AOP_CRY)
+ if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
{
while (size--)
{
}
}
+/*-----------------------------------------------------------------*/
+/* genDummyRead - generate code for dummy read of volatiles */
+/*-----------------------------------------------------------------*/
+static void
+genDummyRead (iCode * ic)
+{
+ operand *op;
+ int size, offset;
+
+ D(emitcode("; genDummyRead",""));
+
+ op = IC_RIGHT (ic);
+ if (op && IS_SYMOP (op))
+ {
+ 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);
+ }
+
+ op = IC_LEFT (ic);
+ if (op && IS_SYMOP (op))
+ {
+ 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);
+ }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* 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 */
}
#if 1
/* print the allocation information */
- if (allocInfo)
+ if (allocInfo && currFunc)
printAllocInfo (currFunc, codeOutFile);
#endif
/* if debug information required */
if (options.debug && currFunc)
{
- cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
+ debugFile->writeFunction(currFunc);
_G.debugLine = 1;
if (IS_STATIC (currFunc->etype))
emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
for (ic = lic; ic; ic = ic->next)
{
+ _G.current_iCode = ic;
+
if (ic->lineno && cln != ic->lineno)
{
if (options.debug)
else addSet (&_G.sendSet, ic);
break;
+ case DUMMY_READ_VOLATILE:
+ 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);
break;
+#endif
default:
ic = ic;