Made everything static
-------------------------------------------------------------------------*/
+#define D(x)
+//#define D(x) x
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_SYS_ISA_DEFS_H
#include <sys/isa_defs.h>
#else
+#ifdef HAVE_MACHINE_ENDIAN_H
+#include <machine/endian.h>
+#else
#ifdef HAVE_ENDIAN_H
#include <endian.h>
#else
-#if !defined(__BORLANDC__) && !defined(_MSC_VER)
+#if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
#warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
#warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
#endif
#endif
#endif
+#endif
#include "common.h"
#include "SDCCpeeph.h"
char *fReturn8051[] =
{"dpl", "dph", "b", "a"};
-char *fReturn390[] =
-{"dpl", "dph", "dpx", "b", "a"};
-unsigned fReturnSize = 4; /* shared with ralloc.c */
+unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
char **fReturn = fReturn8051;
static char *accUse[] =
{"a", "b"};
extern int mcs51_ptrRegReq;
extern int mcs51_nRegs;
extern FILE *codeOutFile;
-static void saverbank (int, iCode *, bool);
+static void saveRBank (int, iCode *, bool);
#define RESULTONSTACK(x) \
(IC_RESULT(x) && IC_RESULT(x)->aop && \
IC_RESULT(x)->aop->type == AOP_STK )
emitcode (char *inst, char *fmt,...)
{
va_list ap;
- char lb[MAX_INLINEASM];
+ char lb[INITIAL_INLINEASM];
char *lbp = lb;
va_start (ap, fmt);
/* first check if r0 & r1 are used by this
instruction, in which case we are in trouble */
- if ((r0iu = bitVectBitValue (ic->rUsed, R0_IDX)) &&
- (r1iu = bitVectBitValue (ic->rUsed, R1_IDX)))
- {
+ r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
+ r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
+ if (r0iu && r1iu) {
goto endOfWorld;
}
return NULL;
}
- piCode (ic, stdout);
/* other wise this is true end of the world */
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
"getFreePtr should never reach here");
- exit (0);
+ exit (1);
}
/*-----------------------------------------------------------------*/
return aop;
}
-static void
-genSetDPTR (int n)
-{
- if (!n)
- {
- emitcode (";", "Select standard DPTR");
- emitcode ("mov", "dps, #0x00");
- }
- else
- {
- emitcode (";", "Select alternate DPTR");
- emitcode ("mov", "dps, #0x01");
- }
-}
-
/*-----------------------------------------------------------------*/
/* pointerCode - returns the code for a pointer type */
/*-----------------------------------------------------------------*/
aopForSym (iCode * ic, symbol * sym, bool result)
{
asmop *aop;
- memmap *space = SPEC_OCLS (sym->etype);
+ memmap *space;
+
+ wassertl (ic != NULL, "Got a null iCode");
+ wassertl (sym != NULL, "Got a null symbol");
+
+ space = SPEC_OCLS (sym->etype);
/* if already has one */
if (sym->aop)
/* assign depending on the storage class */
/* if it is on the stack or indirectly addressable */
/* space we need to assign either r0 or r1 to it */
- if ((sym->onStack && !options.stack10bit) || sym->iaccess)
+ if (sym->onStack || sym->iaccess)
{
sym->aop = aop = newAsmop (0);
aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
return aop;
}
- if (sym->onStack && options.stack10bit)
- {
- /* It's on the 10 bit stack, which is located in
- * far data space.
- */
-
- if (_G.accInUse)
- emitcode ("push", "acc");
-
- emitcode ("mov", "a,_bp");
- emitcode ("add", "a,#0x%02x",
- ((sym->stack < 0) ?
- ((char) (sym->stack - _G.nRegsSaved)) :
- ((char) sym->stack)) & 0xff);
-
- genSetDPTR (1);
- emitcode ("mov", "dpx1,#0x40");
- emitcode ("mov", "dph1,#0x00");
- emitcode ("mov", "dpl1, a");
- genSetDPTR (0);
-
- if (_G.accInUse)
- emitcode ("pop", "acc");
-
- sym->aop = aop = newAsmop (AOP_DPTR2);
- aop->size = getSize (sym->type);
- return aop;
- }
-
/* if in bit space */
if (IN_BITSPACE (space))
{
for (;;)
{
if (ic->op == '+')
- val += operandLitValue (IC_RIGHT (ic));
+ val += (int) operandLitValue (IC_RIGHT (ic));
else if (ic->op == '-')
- val -= operandLitValue (IC_RIGHT (ic));
+ val -= (int) operandLitValue (IC_RIGHT (ic));
else
break;
sym = OP_SYMBOL (op);
-
/* if the type is a conditional */
if (sym->regType == REG_CND)
{
if (sym->ruonly)
{
- int i;
+ unsigned i;
+
aop = op->aop = sym->aop = newAsmop (AOP_STR);
aop->size = getSize (sym->type);
- for (i = 0; i < fReturnSize; i++)
+ for (i = 0; i < fReturnSizeMCS51; i++)
aop->aopu.aop_str[i] = fReturn[i];
return;
}
getFreePtr (ic, &aop, FALSE);
- if (options.stack10bit)
- {
- /* I'm not sure what to do here yet... */
- /* #STUB */
- fprintf (stderr,
- "*** Warning: probably generating bad code for "
- "10 bit stack mode.\n");
- }
-
if (stk)
{
emitcode ("mov", "a,_bp");
return rs;
case AOP_DPTR:
- case AOP_DPTR2:
-
- if (aop->type == AOP_DPTR2)
- {
- genSetDPTR (1);
- }
-
while (offset > aop->coff)
{
emitcode ("inc", "dptr");
{
emitcode ("movx", "a,@dptr");
}
-
- if (aop->type == AOP_DPTR2)
- {
- genSetDPTR (0);
- }
-
return (dname ? "acc" : "a");
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
"aopget got unsupported aop->type");
- exit (0);
+ exit (1);
}
/*-----------------------------------------------------------------*/
/* aopPut - puts a string for a aop */
aopPut (asmop * aop, char *s, int offset)
{
char *d = buffer;
- symbol *lbl;
if (aop->size && offset > (aop->size - 1))
{
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
"aopPut got offset > aop->size");
- exit (0);
+ exit (1);
}
/* will assign value to value */
break;
case AOP_DPTR:
- case AOP_DPTR2:
-
- if (aop->type == AOP_DPTR2)
- {
- genSetDPTR (1);
- }
-
if (aop->code)
{
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
"aopPut writting to code space");
- exit (0);
+ exit (1);
}
while (offset > aop->coff)
MOVA (s);
emitcode ("movx", "@dptr,a");
-
- if (aop->type == AOP_DPTR2)
- {
- genSetDPTR (0);
- }
break;
case AOP_R0:
emitcode ("mov", "%s,c", aop->aopu.aop_dir);
else
{
- lbl = newiTempLabel (NULL);
-
if (strcmp (s, "a"))
{
MOVA (s);
}
- emitcode ("clr", "c");
- emitcode ("jz", "%05d$", lbl->key + 100);
- emitcode ("cpl", "c");
- emitcode ("", "%05d$:", lbl->key + 100);
- emitcode ("mov", "%s,c", aop->aopu.aop_dir);
+ {
+ symbol *lbl = newiTempLabel (NULL);
+ emitcode ("clr", "c");
+ emitcode ("jz", "%05d$", lbl->key + 100);
+ emitcode ("cpl", "c");
+ emitcode ("", "%05d$:", lbl->key + 100);
+ emitcode ("mov", "%s,c", aop->aopu.aop_dir);
+ }
}
}
break;
default:
werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
"aopPut got unsupported aop->type");
- exit (0);
+ exit (1);
}
}
static void
reAdjustPreg (asmop * aop)
{
- int size;
-
- aop->coff = 0;
- if ((size = aop->size) <= 1)
+ if ((aop->coff==0) || aop->size <= 1)
return;
- size--;
+
switch (aop->type)
{
case AOP_R0:
case AOP_R1:
- while (size--)
+ while (aop->coff--)
emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
break;
case AOP_DPTR:
- case AOP_DPTR2:
- if (aop->type == AOP_DPTR2)
- {
- genSetDPTR (1);
- }
- while (size--)
+ while (aop->coff--)
{
emitcode ("lcall", "__decdptr");
}
-
- if (aop->type == AOP_DPTR2)
- {
- genSetDPTR (0);
- }
break;
-
}
-
+ aop->coff = 0;
}
#define AOP(op) op->aop
AOP_TYPE(x) == AOP_R0))
#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
- AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
- AOP(x)->paged))
+ AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
#define AOP_INPREG(x) (x && (x->type == AOP_REG && \
(x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
aopGet (op->aop,
offset++, FALSE, FALSE));
}
- tlbl = newiTempLabel (NULL);
tlbl = newiTempLabel (NULL);
aopPut (res->aop, one, 1);
int i;
iCode *ic;
bitVect *rsave;
- sym_link *detype;
/* look for call */
for (ic = lic; ic; ic = ic->next)
return;
}
- /* if the registers have been saved already then
+ /* if the registers have been saved already or don't need to be then
do nothing */
- if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
+ if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
+ IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
return;
/* find the registers in use at this time
if (bitVectBitValue (rsave, i))
emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
}
-
- detype = getSpec (operandType (IC_LEFT (ic)));
- if (detype &&
- (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
- IS_ISR (currFunc->etype) &&
- !ic->bankSaved)
-
- saverbank (SPEC_BANK (detype), ic, TRUE);
-
}
+
/*-----------------------------------------------------------------*/
/* unsaveRegisters - pop the pushed registers */
/*-----------------------------------------------------------------*/
int size, offset = 0;
char *l;
+ D(emitcode (";", "genIpush"));
/* if this is not a parm push : ie. it is spill push
and spill push is always done on the local stack */
}
/*-----------------------------------------------------------------*/
-/* unsaverbank - restores the resgister bank from stack */
+/* unsaveRBank - restores the resgister bank from stack */
/*-----------------------------------------------------------------*/
static void
-unsaverbank (int bank, iCode * ic, bool popPsw)
+unsaveRBank (int bank, iCode * ic, bool popPsw)
{
int i;
- asmop *aop;
+ asmop *aop = NULL;
regs *r = NULL;
+ if (options.useXstack)
+ {
+ if (!ic)
+ {
+ /* Assume r0 is available for use. */
+ r = mcs51_regWithIdx (R0_IDX);;
+ }
+ else
+ {
+ aop = newAsmop (0);
+ r = getFreePtr (ic, &aop, FALSE);
+ }
+ emitcode ("mov", "%s,_spx", r->name);
+ }
+
if (popPsw)
{
if (options.useXstack)
- {
- aop = newAsmop (0);
- r = getFreePtr (ic, &aop, FALSE);
-
-
- emitcode ("mov", "%s,_spx", r->name);
+ {
emitcode ("movx", "a,@%s", r->name);
emitcode ("mov", "psw,a");
emitcode ("dec", "%s", r->name);
-
}
else
+ {
emitcode ("pop", "psw");
+ }
}
for (i = (mcs51_nRegs - 1); i >= 0; i--)
if (options.useXstack)
{
-
emitcode ("mov", "_spx,%s", r->name);
- freeAsmop (NULL, aop, ic, TRUE);
-
}
+
+ if (aop)
+ {
+ freeAsmop (NULL, aop, ic, TRUE);
+ }
}
/*-----------------------------------------------------------------*/
-/* saverbank - saves an entire register bank on the stack */
+/* saveRBank - saves an entire register bank on the stack */
/*-----------------------------------------------------------------*/
static void
-saverbank (int bank, iCode * ic, bool pushPsw)
+saveRBank (int bank, iCode * ic, bool pushPsw)
{
int i;
- asmop *aop;
+ asmop *aop = NULL;
regs *r = NULL;
if (options.useXstack)
{
-
- aop = newAsmop (0);
- r = getFreePtr (ic, &aop, FALSE);
+ if (!ic)
+ {
+ /* Assume r0 is available for use. */
+ r = mcs51_regWithIdx (R0_IDX);;
+ }
+ else
+ {
+ aop = newAsmop (0);
+ r = getFreePtr (ic, &aop, FALSE);
+ }
emitcode ("mov", "%s,_spx", r->name);
-
}
for (i = 0; i < mcs51_nRegs; i++)
emitcode ("movx", "@%s,a", r->name);
emitcode ("inc", "%s", r->name);
emitcode ("mov", "_spx,%s", r->name);
- freeAsmop (NULL, aop, ic, TRUE);
}
else
+ {
emitcode ("push", "psw");
+ }
emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
}
- ic->bankSaved = 1;
+ if (aop)
+ {
+ freeAsmop (NULL, aop, ic, TRUE);
+ }
+
+ if (ic)
+ {
+ ic->bankSaved = 1;
+ }
}
/*-----------------------------------------------------------------*/
static void
genCall (iCode * ic)
{
- sym_link *detype;
-
- /* if caller saves & we have not saved then */
- if (!ic->regsSaved)
- saveRegisters (ic);
-
- /* if we are calling a function that is not using
- the same register bank then we need to save the
- destination registers on the stack */
- detype = getSpec (operandType (IC_LEFT (ic)));
- if (detype &&
- (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
- IS_ISR (currFunc->etype) &&
- !ic->bankSaved)
-
- saverbank (SPEC_BANK (detype), ic, TRUE);
+ sym_link *dtype;
+ bool restoreBank = FALSE;
+ bool swapBanks = FALSE;
+ D(emitcode(";", "genCall"));
/* if send set is not empty the assign */
if (_G.sendSet)
{
}
_G.sendSet = NULL;
}
+
+ /* if we are calling a not _naked function that is not using
+ the same register bank then we need to save the
+ destination registers on the stack */
+ dtype = operandType (IC_LEFT (ic));
+ if (dtype && !IFFUNC_ISNAKED(dtype) &&
+ (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
+ IFFUNC_ISISR (currFunc->type))
+ {
+ if (!ic->bankSaved)
+ {
+ /* This is unexpected; the bank should have been saved in
+ * genFunction.
+ */
+ saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
+ restoreBank = TRUE;
+ }
+ swapBanks = TRUE;
+ }
+
+ /* if caller saves & we have not saved then */
+ if (!ic->regsSaved)
+ saveRegisters (ic);
+
+ if (swapBanks)
+ {
+ emitcode ("mov", "psw,#0x%02x",
+ ((FUNC_REGBANK(dtype)) << 3) & 0xff);
+ }
+
/* make the call */
emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
OP_SYMBOL (IC_LEFT (ic))->rname :
OP_SYMBOL (IC_LEFT (ic))->name));
+ if (swapBanks)
+ {
+ emitcode ("mov", "psw,#0x%02x",
+ ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
+ }
+
/* if we need assign a result value */
if ((IS_ITEMP (IC_RESULT (ic)) &&
(OP_SYMBOL (IC_RESULT (ic))->nRegs ||
else
for (i = 0; i < ic->parmBytes; i++)
emitcode ("dec", "%s", spname);
-
}
- /* if register bank was saved then pop them */
- if (ic->bankSaved)
- unsaverbank (SPEC_BANK (detype), ic, TRUE);
-
/* if we hade saved some registers then unsave them */
- if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
+ if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
unsaveRegisters (ic);
-
+ /* if register bank was saved then pop them */
+ if (restoreBank)
+ unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
}
/*-----------------------------------------------------------------*/
static void
genPcall (iCode * ic)
{
- sym_link *detype;
+ sym_link *dtype;
symbol *rlbl = newiTempLabel (NULL);
/* if we are calling a function that is not using
the same register bank then we need to save the
destination registers on the stack */
- detype = getSpec (operandType (IC_LEFT (ic)));
- if (detype &&
- IS_ISR (currFunc->etype) &&
- (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
- saverbank (SPEC_BANK (detype), ic, TRUE);
+ dtype = operandType (IC_LEFT (ic));
+ if (dtype &&
+ IFFUNC_ISISR (currFunc->type) &&
+ (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)))
+ saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
/* push the return address on to the stack */
emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
emitcode ("push", "acc");
- if (options.model == MODEL_FLAT24)
- {
- emitcode ("mov", "a,#(%05d$ >> 16)", (rlbl->key + 100));
- emitcode ("push", "acc");
- }
-
/* now push the calling address */
aopOp (IC_LEFT (ic), ic, FALSE);
}
/* if register bank was saved then unsave them */
- if (detype &&
- (SPEC_BANK (currFunc->etype) !=
- SPEC_BANK (detype)))
- unsaverbank (SPEC_BANK (detype), ic, TRUE);
+ if (dtype &&
+ (FUNC_REGBANK (currFunc->type) !=
+ FUNC_REGBANK (dtype)))
+ unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
/* if we hade saved some registers then
unsave them */
if (ic->regsSaved)
unsaveRegisters (ic);
-
}
/*-----------------------------------------------------------------*/
genFunction (iCode * ic)
{
symbol *sym;
- sym_link *fetype;
+ sym_link *ftype;
+ bool switchedPSW = FALSE;
_G.nRegsSaved = 0;
/* create the function header */
emitcode (";", "-----------------------------------------");
emitcode ("", "%s:", sym->rname);
- fetype = getSpec (operandType (IC_LEFT (ic)));
+ ftype = operandType (IC_LEFT (ic));
+
+ if (IFFUNC_ISNAKED(ftype))
+ {
+ emitcode(";", "naked function: no prologue.");
+ return;
+ }
/* if critical function then turn interrupts off */
- if (SPEC_CRTCL (fetype))
+ if (IFFUNC_ISCRITICAL (ftype))
emitcode ("clr", "ea");
/* here we need to generate the equates for the
register bank if required */
- if (SPEC_BANK (fetype) != rbank)
+ if (FUNC_REGBANK (ftype) != rbank)
{
int i;
- rbank = SPEC_BANK (fetype);
+ rbank = FUNC_REGBANK (ftype);
for (i = 0; i < mcs51_nRegs; i++)
{
if (strcmp (regs8051[i].base, "0") == 0)
/* if this is an interrupt service routine then
save acc, b, dpl, dph */
- if (IS_ISR (sym->etype))
+ if (IFFUNC_ISISR (sym->type))
{
if (!inExcludeList ("acc"))
emitcode ("push", "dpl");
if (!inExcludeList ("dph"))
emitcode ("push", "dph");
- if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
- {
- emitcode ("push", "dpx");
- /* Make sure we're using standard DPTR */
- emitcode ("push", "dps");
- emitcode ("mov", "dps, #0x00");
- if (options.stack10bit)
- {
- /* This ISR could conceivably use DPTR2. Better save it. */
- emitcode ("push", "dpl1");
- emitcode ("push", "dph1");
- emitcode ("push", "dpx1");
- }
- }
/* if this isr has no bank i.e. is going to
run with bank 0 , then we need to save more
registers :-) */
- if (!SPEC_BANK (sym->etype))
+ if (!FUNC_REGBANK (sym->type))
{
/* if this function does not call any other
function then we can be economical and
save only those registers that are used */
- if (!sym->hasFcall)
+ if (!IFFUNC_HASFCALL(sym->type))
{
int i;
else
{
/* this function has a function call cannot
- determines register usage so we will have the
+ determines register usage so we will have to push the
entire bank */
- saverbank (0, ic, FALSE);
+ saveRBank (0, ic, FALSE);
+ }
+ }
+ else
+ {
+ /* This ISR uses a non-zero bank.
+ *
+ * We assume that the bank is available for our
+ * exclusive use.
+ *
+ * However, if this ISR calls a function which uses some
+ * other bank, we must save that bank entirely.
+ */
+ unsigned long banksToSave = 0;
+
+ if (IFFUNC_HASFCALL(sym->type))
+ {
+
+#define MAX_REGISTER_BANKS 4
+
+ iCode *i;
+ int ix;
+
+ for (i = ic; i; i = i->next)
+ {
+ if (i->op == ENDFUNCTION)
+ {
+ /* we got to the end OK. */
+ break;
+ }
+
+ if (i->op == CALL)
+ {
+ sym_link *dtype;
+
+ dtype = operandType (IC_LEFT(i));
+ if (dtype
+ && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
+ {
+ /* Mark this bank for saving. */
+ if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
+ {
+ werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
+ }
+ else
+ {
+ banksToSave |= (1 << FUNC_REGBANK(dtype));
+ }
+
+ /* And note that we don't need to do it in
+ * genCall.
+ */
+ i->bankSaved = 1;
+ }
+ }
+ if (i->op == PCALL)
+ {
+ /* This is a mess; we have no idea what
+ * register bank the called function might
+ * use.
+ *
+ * The only thing I can think of to do is
+ * throw a warning and hope.
+ */
+ werror(W_FUNCPTR_IN_USING_ISR);
+ }
+ }
+
+ if (banksToSave && options.useXstack)
+ {
+ /* Since we aren't passing it an ic,
+ * saveRBank will assume r0 is available to abuse.
+ *
+ * So switch to our (trashable) bank now, so
+ * the caller's R0 isn't trashed.
+ */
+ emitcode ("push", "psw");
+ emitcode ("mov", "psw,#0x%02x",
+ (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
+ switchedPSW = TRUE;
+ }
+
+ for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
+ {
+ if (banksToSave & (1 << ix))
+ {
+ saveRBank(ix, NULL, FALSE);
+ }
+ }
}
+ // jwk: this needs a closer look
+ SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
}
}
else
{
/* if callee-save to be used for this function
then save the registers being used in this function */
- if (sym->calleeSave)
+ if (IFFUNC_CALLEESAVES(sym->type))
{
int i;
}
/* set the register bank to the desired value */
- if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
+ if ((FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
+ && !switchedPSW)
{
emitcode ("push", "psw");
- emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
+ emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
}
- if (IS_RENT (sym->etype) || options.stackAuto)
+ if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
{
if (options.useXstack)
{
symbol *sym = OP_SYMBOL (IC_LEFT (ic));
- if (IS_RENT (sym->etype) || options.stackAuto)
+ if (IFFUNC_ISNAKED(sym->type))
+ {
+ emitcode(";", "naked function: no epilogue.");
+ return;
+ }
+
+ if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
{
emitcode ("mov", "%s,_bp", spname);
}
}
- if ((IS_RENT (sym->etype) || options.stackAuto))
+ if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
{
if (options.useXstack)
{
}
/* restore the register bank */
- if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
- emitcode ("pop", "psw");
+ if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
+ {
+ if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
+ || !options.useXstack)
+ {
+ /* Special case of ISR using non-zero bank with useXstack
+ * is handled below.
+ */
+ emitcode ("pop", "psw");
+ }
+ }
- if (IS_ISR (sym->etype))
+ if (IFFUNC_ISISR (sym->type))
{
/* now we need to restore the registers */
/* if this isr has no bank i.e. is going to
run with bank 0 , then we need to save more
registers :-) */
- if (!SPEC_BANK (sym->etype))
+ if (!FUNC_REGBANK (sym->type))
{
-
/* if this function does not call any other
function then we can be economical and
save only those registers that are used */
- if (!sym->hasFcall)
+ if (!IFFUNC_HASFCALL(sym->type))
{
int i;
else
{
/* this function has a function call cannot
- determines register usage so we will have the
+ determines register usage so we will have to pop the
entire bank */
- unsaverbank (0, ic, FALSE);
+ unsaveRBank (0, ic, FALSE);
}
}
-
- if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
+ else
{
- if (options.stack10bit)
+ /* This ISR uses a non-zero bank.
+ *
+ * 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;
+
+ for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
{
- emitcode ("pop", "dpx1");
- emitcode ("pop", "dph1");
- emitcode ("pop", "dpl1");
+ if (savedBanks & (1 << ix))
+ {
+ unsaveRBank(ix, NULL, FALSE);
+ }
+ }
+
+ if (options.useXstack)
+ {
+ /* Restore bank AFTER calling unsaveRBank,
+ * since it can trash r0.
+ */
+ emitcode ("pop", "psw");
}
- emitcode ("pop", "dps");
- emitcode ("pop", "dpx");
}
+
if (!inExcludeList ("dph"))
emitcode ("pop", "dph");
if (!inExcludeList ("dpl"))
if (!inExcludeList ("acc"))
emitcode ("pop", "acc");
- if (SPEC_CRTCL (sym->etype))
+ if (IFFUNC_ISCRITICAL (sym->type))
emitcode ("setb", "ea");
/* if debug then send end of function */
-/* if (options.debug && currFunc) { */
- if (currFunc)
+ /* if (options.debug && currFunc) */
+ if (options.debug && currFunc)
{
_G.debugLine = 1;
emitcode ("", "C$%s$%d$%d$%d ==.",
}
else
{
- if (SPEC_CRTCL (sym->etype))
+ if (IFFUNC_ISCRITICAL (sym->type))
emitcode ("setb", "ea");
- if (sym->calleeSave)
+ if (IFFUNC_CALLEESAVES(sym->type))
{
int i;
}
/* if debug then send end of function */
- if (currFunc)
+ if (options.debug && currFunc)
{
_G.debugLine = 1;
emitcode ("", "C$%s$%d$%d$%d ==.",
/* if the literal value of the right hand side
is greater than 4 then it is not worth it */
- if ((icount = floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
+ if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
return FALSE;
/* if increment 16 bits in register */
else
{
/* first add without previous c */
- if (!offset)
- emitcode ("add", "a,#0x%02x",
- (unsigned int) (lit & 0x0FFL));
- else
+ if (!offset) {
+ if (!size && lit==-1) {
+ emitcode ("dec", "a");
+ } else {
+ emitcode ("add", "a,#0x%02x",
+ (unsigned int) (lit & 0x0FFL));
+ }
+ } else {
emitcode ("addc", "a,#0x%02x",
(unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
+ }
}
aopPut (AOP (IC_RESULT (ic)), "a", offset++);
}
/*-----------------------------------------------------------------*/
-/* genMultOneByte : 8 bit multiplication & division */
+/* genMultOneByte : 8*8=8/16 bit multiplication */
/*-----------------------------------------------------------------*/
static void
genMultOneByte (operand * left,
operand * result)
{
sym_link *opetype = operandType (result);
- char *l;
symbol *lbl;
- int size, offset;
+ int size=AOP_SIZE(result);
- /* (if two literals, the value is computed before) */
+ if (size<1 || size>2) {
+ // this should never happen
+ fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
+ AOP_SIZE(result), __FILE__, lineno);
+ exit (1);
+ }
+
+ /* (if two literals: the value is computed before) */
/* if one literal, literal on the right */
if (AOP_TYPE (left) == AOP_LIT)
{
operand *t = right;
right = left;
left = t;
+ //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));
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+ emitcode ("mul", "ab");
+ aopPut (AOP (result), "a", 0);
+ if (size==2) {
+ aopPut (AOP (result), "b", 1);
}
+ return;
+ }
- size = AOP_SIZE (result);
- /* signed or unsigned */
- emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
- l = aopGet (AOP (left), 0, FALSE, FALSE);
- MOVA (l);
- emitcode ("mul", "ab");
- /* if result size = 1, mul signed = mul unsigned */
- aopPut (AOP (result), "a", 0);
- if (size > 1)
- {
- if (SPEC_USIGN (opetype))
- {
- aopPut (AOP (result), "b", 1);
- if (size > 2)
- /* for filling the MSBs */
- emitcode ("clr", "a");
- }
- else
- {
- emitcode ("mov", "a,b");
+ // we have to do a signed multiply
- /* adjust the MSB if left or right neg */
+ //emitcode (";", "signed");
+ emitcode ("clr", "F0"); // reset sign flag
+ MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
- /* if one literal */
- if (AOP_TYPE (right) == AOP_LIT)
- {
- /* AND literal negative */
- if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0)
- {
- /* adjust MSB (c==0 after mul) */
- emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
- }
- }
- else
- {
- lbl = newiTempLabel (NULL);
- emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
- emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
- emitcode ("", "%05d$:", (lbl->key + 100));
- emitcode ("xch", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
- lbl = newiTempLabel (NULL);
- emitcode ("jc", "%05d$", (lbl->key + 100));
- emitcode ("subb", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
- emitcode ("", "%05d$:", (lbl->key + 100));
- }
+ lbl=newiTempLabel(NULL);
+ emitcode ("jnb", "acc.7,%05d$", 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");
- lbl = newiTempLabel (NULL);
- emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
- emitcode ("cjne", "a,#0x80,%05d$", (lbl->key + 100));
- emitcode ("", "%05d$:", (lbl->key + 100));
- emitcode ("xch", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE));
- lbl = newiTempLabel (NULL);
- emitcode ("jc", "%05d$", (lbl->key + 100));
- emitcode ("subb", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
- emitcode ("", "%05d$:", (lbl->key + 100));
+ emitcode ("", "%05d$:", lbl->key+100);
+
+ /* if literal */
+ if (AOP_TYPE(right)==AOP_LIT) {
+ signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
+ /* AND literal negative */
+ if (val < 0) {
+ emitcode ("cpl", "F0"); // complement sign flag
+ emitcode ("mov", "b,#0x%02x", -val);
+ } else {
+ emitcode ("mov", "b,#0x%02x", val);
+ }
+ } else {
+ lbl=newiTempLabel(NULL);
+ emitcode ("mov", "b,a");
+ emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
+ emitcode ("jnb", "acc.7,%05d$", 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 ("", "%05d$:", lbl->key+100);
+ }
+ emitcode ("mul", "ab");
+
+ lbl=newiTempLabel(NULL);
+ emitcode ("jnb", "F0,%05d$", lbl->key+100);
+ // only ONE op was negative, we have to do a 8/16-bit two's complement
+ emitcode ("cpl", "a"); // lsb
+ if (size==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");
+ }
- aopPut (AOP (result), "a", 1);
- if (size > 2)
- {
- /* get the sign */
- emitcode ("rlc", "a");
- emitcode ("subb", "a,acc");
- }
- }
- size -= 2;
- offset = 2;
- if (size > 0)
- while (size--)
- aopPut (AOP (result), "a", offset++);
- }
+ emitcode ("", "%05d$:", lbl->key+100);
+ aopPut (AOP (result), "a", 0);
+ if (size==2) {
+ aopPut (AOP (result), "b", 1);
+ }
}
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
static void
genCmp (operand * left, operand * right,
- operand * result, iCode * ifx, int sign)
+ operand * result, iCode * ifx, int sign, iCode *ic)
{
int size, offset = 0;
unsigned long lit = 0L;
}
release:
+ freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+ freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
{
outBitC (result);
aopOp (right, ic, FALSE);
aopOp (result, ic, TRUE);
- genCmp (right, left, result, ifx, sign);
+ genCmp (right, left, result, ifx, sign,ic);
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
- freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
}
aopOp (right, ic, FALSE);
aopOp (result, ic, TRUE);
- genCmp (left, right, result, ifx, sign);
+ genCmp (left, right, result, ifx, sign,ic);
- freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
- freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
freeAsmop (result, NULL, ic, TRUE);
}
return NULL;
}
+
+/*-----------------------------------------------------------------*/
+/* hasInc - operand is incremented before any other use */
+/*-----------------------------------------------------------------*/
+static iCode *
+hasInc (operand *op, iCode *ic)
+{
+ sym_link *type = operandType(op);
+ sym_link *retype = getSpec (type);
+ iCode *lic = ic->next;
+ int isize ;
+
+ /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
+ if (!IS_SYMOP(op)) return NULL;
+
+ if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
+ isize = getSize(type->next);
+ while (lic) {
+ /* if operand of the form op = op + <sizeof *op> */
+ if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
+ isOperandEqual(IC_RESULT(lic),op) &&
+ isOperandLiteral(IC_RIGHT(lic)) &&
+ operandLitValue(IC_RIGHT(lic)) == isize) {
+ return lic;
+ }
+ /* if the operand used or deffed */
+ if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
+ return NULL;
+ }
+ lic = lic->next;
+ }
+ return NULL;
+}
+
/*-----------------------------------------------------------------*/
/* genAndOp - for && operation */
/*-----------------------------------------------------------------*/
emitcode ("setb", "c");
while (sizer--)
{
- MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
- emitcode ("anl", "a,%s",
- aopGet (AOP (left), offset, FALSE, FALSE));
+ if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+ emitcode ("anl", "a,%s",
+ aopGet (AOP (right), offset, FALSE, FALSE));
+ } else {
+ if (AOP_TYPE(left)==AOP_ACC) {
+ emitcode("mov", "b,a");
+ MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
+ emitcode("anl", "a,b");
+ }else {
+ MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
+ emitcode ("anl", "a,%s",
+ aopGet (AOP (left), offset, FALSE, FALSE));
+ }
+ }
emitcode ("jnz", "%05d$", tlbl->key + 100);
offset++;
}
emitcode ("setb", "c");
while (sizer--)
{
- MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
- emitcode ("orl", "a,%s",
- aopGet (AOP (left), offset, FALSE, FALSE));
+ if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+ emitcode ("orl", "a,%s",
+ aopGet (AOP (right), offset, FALSE, FALSE));
+ } else {
+ MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
+ emitcode ("orl", "a,%s",
+ aopGet (AOP (left), offset, FALSE, FALSE));
+ }
emitcode ("jnz", "%05d$", tlbl->key + 100);
offset++;
}
}
else
{
- MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
- emitcode ("xrl", "a,%s",
- aopGet (AOP (left), offset, FALSE, FALSE));
+ if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+ emitcode ("xrl", "a,%s",
+ aopGet (AOP (right), offset, FALSE, FALSE));
+ } else {
+ MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
+ emitcode ("xrl", "a,%s",
+ aopGet (AOP (left), offset, FALSE, FALSE));
+ }
}
emitcode ("jnz", "%05d$", tlbl->key + 100);
offset++;
static void
genInline (iCode * ic)
{
- char buffer[MAX_INLINEASM];
- char *bp = buffer;
- char *bp1 = buffer;
+ char *buffer, *bp, *bp1;
_G.inLine += (!options.asmpeep);
+
+ buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
strcpy (buffer, IC_INLINE (ic));
/* emit each line as a code */
/* move it to the result */
size = AOP_SIZE (result);
offset = size - 1;
+ if (size == 1) { /* special case for 1 byte */
+ l = aopGet (AOP (left), offset, FALSE, FALSE);
+ MOVA (l);
+ emitcode ("rr", "a");
+ goto release;
+ }
CLRC;
while (size--)
{
MOVA (l);
}
emitcode ("mov", "acc.7,c");
+ release:
aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
freeAsmop (left, NULL, ic, TRUE);
freeAsmop (result, NULL, ic, TRUE);
{
l = aopGet (AOP (left), offset, FALSE, FALSE);
MOVA (l);
+ if (size == 0) { /* special case for 1 byte */
+ emitcode("rl","a");
+ goto release;
+ }
emitcode ("add", "a,acc");
if (AOP_SIZE (result) > 1)
aopPut (AOP (result), "a", offset++);
MOVA (l);
}
emitcode ("mov", "acc.0,c");
+ release:
aopPut (AOP (result), "a", 0);
freeAsmop (left, NULL, ic, TRUE);
freeAsmop (result, NULL, ic, TRUE);
break;
case 6: // AAAAAABB:CCCCCCDD
-
emitcode ("anl", "a,#0x%02x",
SRMask[shCount]); // 000000BB:CCCCCCDD
-
emitcode ("mov", "c,acc.0"); // c = B
-
emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
-
+#if 0 // REMOVE ME
AccAXRrl1 (x); // BCCCCCCD:D000000B
-
AccAXRrl1 (x); // BBCCCCCC:DD000000
-
+#else
+ emitcode("rrc","a");
+ emitcode("xch","a,%s", x);
+ emitcode("rrc","a");
+ emitcode("mov","c,acc.0"); //<< get correct bit
+ emitcode("xch","a,%s", x);
+
+ emitcode("rrc","a");
+ emitcode("xch","a,%s", x);
+ emitcode("rrc","a");
+ emitcode("xch","a,%s", x);
+#endif
break;
case 7: // a:x <<= 7
movLeft2Result (left, LSB, result, MSB32, 0);
aopPut (AOP (result), zero, LSB);
aopPut (AOP (result), zero, MSB16);
- aopPut (AOP (result), zero, MSB32);
+ aopPut (AOP (result), zero, MSB24);
return;
}
break;
case 2:
- case 3:
genlshTwo (result, left, shCount);
break;
case 4:
genlshFour (result, left, shCount);
break;
+ default:
+ fprintf(stderr, "*** ack! mystery literal shift!\n");
+ break;
}
}
freeAsmop (left, NULL, ic, TRUE);
shiftRLong (operand * left, int offl,
operand * result, int sign)
{
- if (!sign)
- emitcode ("clr", "c");
+ int isSameRegs=sameRegs(AOP(left),AOP(result));
+
+ if (isSameRegs && offl>1) {
+ // we are in big trouble, but this shouldn't happen
+ werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
+ }
+
MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
- if (sign)
+
+ if (offl==MSB16) {
+ // shift is > 8
+ if (sign) {
+ emitcode ("rlc", "a");
+ emitcode ("subb", "a,acc");
+ emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
+ } else {
+ aopPut (AOP(result), zero, MSB32);
+ }
+ }
+
+ if (!sign) {
+ emitcode ("clr", "c");
+ } else {
emitcode ("mov", "c,acc.7");
- emitcode ("rrc", "a");
- aopPut (AOP (result), "a", MSB32 - offl);
- if (offl == MSB16)
- /* add sign of "a" */
- addSign (result, MSB32, sign);
+ }
- MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
emitcode ("rrc", "a");
- aopPut (AOP (result), "a", MSB24 - offl);
- MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
+ if (isSameRegs && offl==MSB16) {
+ emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
+ } else {
+ aopPut (AOP (result), "a", MSB32);
+ MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
+ }
+
+ emitcode ("rrc", "a");
+ if (isSameRegs && offl==1) {
+ emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
+ } else {
+ aopPut (AOP (result), "a", MSB24);
+ MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
+ }
emitcode ("rrc", "a");
aopPut (AOP (result), "a", MSB16 - offl);
case CPOINTER:
emitcode ("clr", "a");
- emitcode ("movc", "a,%s", "@a+dptr");
+ emitcode ("movc", "a,@a+dptr");
break;
case GPOINTER:
case CPOINTER:
emitcode ("clr", "a");
emitcode ("inc", "dptr");
- emitcode ("movc", "a", "@a+dptr");
+ emitcode ("movc", "a,@a+dptr");
break;
case GPOINTER:
static void
genNearPointerGet (operand * left,
operand * result,
- iCode * ic)
+ iCode * ic,
+ iCode * pi)
{
asmop *aop = NULL;
regs *preg = NULL;
}
else
rname = aopGet (AOP (left), 0, FALSE, FALSE);
-
- freeAsmop (left, NULL, ic, TRUE);
- aopOp (result, ic, FALSE);
+
+ //aopOp (result, ic, FALSE);
+ aopOp (result, ic, result?TRUE:FALSE);
/* if bitfield then unpack the bits */
if (IS_BITVAR (retype))
aopPut (AOP (result), buffer, offset);
}
offset++;
- if (size)
+ if (size || pi)
emitcode ("inc", "%s", rname);
}
}
/* now some housekeeping stuff */
- if (aop)
+ if (aop) /* we had to allocate for this iCode */
{
- /* we had to allocate for this iCode */
+ if (pi) { /* post increment present */
+ aopPut(AOP ( left ),rname,0);
+ }
freeAsmop (NULL, aop, ic, TRUE);
}
else
if size > 0 && this could be used again
we have to point it back to where it
belongs */
- if (AOP_SIZE (result) > 1 &&
- !OP_SYMBOL (left)->remat &&
- (OP_SYMBOL (left)->liveTo > ic->seq ||
- ic->depth))
+ if ((AOP_SIZE (result) > 1 &&
+ !OP_SYMBOL (left)->remat &&
+ (OP_SYMBOL (left)->liveTo > ic->seq ||
+ ic->depth)) &&
+ !pi)
{
int size = AOP_SIZE (result) - 1;
while (size--)
}
/* done */
+ freeAsmop (left, NULL, ic, TRUE);
freeAsmop (result, NULL, ic, TRUE);
-
+ if (pi) pi->generated = 1;
}
/*-----------------------------------------------------------------*/
static void
genPagedPointerGet (operand * left,
operand * result,
- iCode * ic)
+ iCode * ic,
+ iCode *pi)
{
asmop *aop = NULL;
regs *preg = NULL;
else
rname = aopGet (AOP (left), 0, FALSE, FALSE);
- freeAsmop (left, NULL, ic, TRUE);
aopOp (result, ic, FALSE);
/* if bitfield then unpack the bits */
offset++;
- if (size)
+ if (size || pi)
emitcode ("inc", "%s", rname);
}
}
/* now some housekeeping stuff */
- if (aop)
+ if (aop) /* we had to allocate for this iCode */
{
- /* we had to allocate for this iCode */
+ if (pi) aopPut ( AOP (left), rname, 0);
freeAsmop (NULL, aop, ic, TRUE);
}
else
if size > 0 && this could be used again
we have to point it back to where it
belongs */
- if (AOP_SIZE (result) > 1 &&
- !OP_SYMBOL (left)->remat &&
- (OP_SYMBOL (left)->liveTo > ic->seq ||
- ic->depth))
+ if ((AOP_SIZE (result) > 1 &&
+ !OP_SYMBOL (left)->remat &&
+ (OP_SYMBOL (left)->liveTo > ic->seq ||
+ ic->depth)) &&
+ !pi)
{
int size = AOP_SIZE (result) - 1;
while (size--)
}
/* done */
+ freeAsmop (left, NULL, ic, TRUE);
freeAsmop (result, NULL, ic, TRUE);
-
+ if (pi) pi->generated = 1;
}
/*-----------------------------------------------------------------*/
static void
genFarPointerGet (operand * left,
- operand * result, iCode * ic)
+ operand * result, iCode * ic, iCode * pi)
{
int size, offset;
sym_link *retype = getSpec (operandType (result));
{ /* we need to get it byte by byte */
emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
- if (options.model == MODEL_FLAT24)
- {
- emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE));
- }
}
}
/* so dptr know contains the address */
- freeAsmop (left, NULL, ic, TRUE);
aopOp (result, ic, FALSE);
/* if bit then unpack */
{
emitcode ("movx", "a,@dptr");
aopPut (AOP (result), "a", offset++);
- if (size)
+ if (size || pi)
emitcode ("inc", "dptr");
}
}
-
+
+ if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
+ aopPut ( AOP (left), "dpl", 0);
+ aopPut ( AOP (left), "dph", 1);
+ pi->generated = 1;
+ }
+ freeAsmop (left, NULL, ic, TRUE);
freeAsmop (result, NULL, ic, TRUE);
}
/*-----------------------------------------------------------------*/
-/* emitcodePointerGet - gget value from code space */
+/* genCodePointerGet - gget value from code space */
/*-----------------------------------------------------------------*/
static void
-emitcodePointerGet (operand * left,
- operand * result, iCode * ic)
+genCodePointerGet (operand * left,
+ operand * result, iCode * ic, iCode *pi)
{
int size, offset;
sym_link *retype = getSpec (operandType (result));
{ /* we need to get it byte by byte */
emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
- if (options.model == MODEL_FLAT24)
- {
- emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE));
- }
}
}
/* so dptr know contains the address */
- freeAsmop (left, NULL, ic, TRUE);
aopOp (result, ic, FALSE);
/* if bit then unpack */
emitcode ("clr", "a");
emitcode ("movc", "a,@a+dptr");
aopPut (AOP (result), "a", offset++);
- if (size)
+ if (size || pi)
emitcode ("inc", "dptr");
}
}
+ if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
+ aopPut ( AOP (left), "dpl", 0);
+ aopPut ( AOP (left), "dph", 1);
+ pi->generated = 1;
+ }
+ freeAsmop (left, NULL, ic, TRUE);
freeAsmop (result, NULL, ic, TRUE);
}
/*-----------------------------------------------------------------*/
static void
genGenPointerGet (operand * left,
- operand * result, iCode * ic)
+ operand * result, iCode * ic, iCode *pi)
{
int size, offset;
sym_link *retype = getSpec (operandType (result));
{ /* we need to get it byte by byte */
emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
- if (options.model == MODEL_FLAT24)
- {
- emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE));
- emitcode ("mov", "b,%s", aopGet (AOP (left), 3, FALSE, FALSE));
- }
- else
- {
- emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
- }
+ emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
}
}
/* so dptr know contains the address */
- freeAsmop (left, NULL, ic, TRUE);
aopOp (result, ic, FALSE);
/* if bit then unpack */
{
emitcode ("lcall", "__gptrget");
aopPut (AOP (result), "a", offset++);
- if (size)
+ if (size || pi)
emitcode ("inc", "dptr");
}
}
+ if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
+ aopPut ( AOP (left), "dpl", 0);
+ aopPut ( AOP (left), "dph", 1);
+ pi->generated = 1;
+ }
+ freeAsmop (left, NULL, ic, TRUE);
freeAsmop (result, NULL, ic, TRUE);
}
/* genPointerGet - generate code for pointer get */
/*-----------------------------------------------------------------*/
static void
-genPointerGet (iCode * ic)
+genPointerGet (iCode * ic, iCode *pi)
{
operand *left, *result;
sym_link *type, *etype;
{
/* we have to go by the storage class */
p_type = PTR_TYPE (SPEC_OCLS (etype));
-
-/* if (SPEC_OCLS(etype)->codesp ) { */
-/* p_type = CPOINTER ; */
-/* } */
-/* else */
-/* if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
-/* p_type = FPOINTER ; */
-/* else */
-/* if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
-/* p_type = PPOINTER; */
-/* else */
-/* if (SPEC_OCLS(etype) == idata ) */
-/* p_type = IPOINTER; */
-/* else */
-/* p_type = POINTER ; */
}
/* now that we have the pointer type we assign
case POINTER:
case IPOINTER:
- genNearPointerGet (left, result, ic);
+ genNearPointerGet (left, result, ic, pi);
break;
case PPOINTER:
- genPagedPointerGet (left, result, ic);
+ genPagedPointerGet (left, result, ic, pi);
break;
case FPOINTER:
- genFarPointerGet (left, result, ic);
+ genFarPointerGet (left, result, ic, pi);
break;
case CPOINTER:
- emitcodePointerGet (left, result, ic);
+ genCodePointerGet (left, result, ic, pi);
break;
case GPOINTER:
- genGenPointerGet (left, result, ic);
+ genGenPointerGet (left, result, ic, pi);
break;
}
static void
genNearPointerSet (operand * right,
operand * result,
- iCode * ic)
+ iCode * ic,
+ iCode * pi)
{
asmop *aop = NULL;
regs *preg = NULL;
genDataPointerSet (right, result, ic);
return;
}
-
+
/* if the value is already in a pointer register
then don't need anything more */
if (!AOP_INPREG (AOP (result)))
{
- /* otherwise get a free pointer register */
- aop = newAsmop (0);
- preg = getFreePtr (ic, &aop, FALSE);
- emitcode ("mov", "%s,%s",
- preg->name,
- aopGet (AOP (result), 0, FALSE, TRUE));
- rname = preg->name;
+ if (
+ //AOP_TYPE (result) == AOP_STK
+ IS_AOP_PREG(result)
+ )
+ {
+ // Aha, it is a pointer, just in disguise.
+ rname = aopGet (AOP (result), 0, FALSE, FALSE);
+ if (*rname != '@')
+ {
+ fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
+ __FILE__, __LINE__);
+ }
+ else
+ {
+ // Expected case.
+ rname++; // skip the '@'.
+ }
+ }
+ else
+ {
+ /* otherwise get a free pointer register */
+ aop = newAsmop (0);
+ preg = getFreePtr (ic, &aop, FALSE);
+ emitcode ("mov", "%s,%s",
+ preg->name,
+ aopGet (AOP (result), 0, FALSE, TRUE));
+ rname = preg->name;
+ }
+ }
+ else
+ {
+ rname = aopGet (AOP (result), 0, FALSE, FALSE);
}
- else
- rname = aopGet (AOP (result), 0, FALSE, FALSE);
- freeAsmop (result, NULL, ic, TRUE);
aopOp (right, ic, FALSE);
-
+
/* if bitfield then unpack the bits */
if (IS_BITVAR (retype) || IS_BITVAR (letype))
genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
}
else
emitcode ("mov", "@%s,%s", rname, l);
- if (size)
+ if (size || pi)
emitcode ("inc", "%s", rname);
offset++;
}
}
/* now some housekeeping stuff */
- if (aop)
+ if (aop) /* we had to allocate for this iCode */
{
- /* we had to allocate for this iCode */
+ if (pi) aopPut (AOP (result),rname,0);
freeAsmop (NULL, aop, ic, TRUE);
}
else
if size > 0 && this could be used again
we have to point it back to where it
belongs */
- if (AOP_SIZE (right) > 1 &&
- !OP_SYMBOL (result)->remat &&
- (OP_SYMBOL (result)->liveTo > ic->seq ||
- ic->depth))
+ if ((AOP_SIZE (right) > 1 &&
+ !OP_SYMBOL (result)->remat &&
+ (OP_SYMBOL (result)->liveTo > ic->seq ||
+ ic->depth)) &&
+ !pi)
{
int size = AOP_SIZE (right) - 1;
while (size--)
}
/* done */
+ if (pi) pi->generated = 1;
+ freeAsmop (result, NULL, ic, TRUE);
freeAsmop (right, NULL, ic, TRUE);
-
-
}
/*-----------------------------------------------------------------*/
static void
genPagedPointerSet (operand * right,
operand * result,
- iCode * ic)
+ iCode * ic,
+ iCode * pi)
{
asmop *aop = NULL;
regs *preg = NULL;
else
rname = aopGet (AOP (result), 0, FALSE, FALSE);
- freeAsmop (result, NULL, ic, TRUE);
aopOp (right, ic, FALSE);
/* if bitfield then unpack the bits */
MOVA (l);
emitcode ("movx", "@%s,a", rname);
- if (size)
+ if (size || pi)
emitcode ("inc", "%s", rname);
offset++;
}
/* now some housekeeping stuff */
- if (aop)
+ if (aop) /* we had to allocate for this iCode */
{
- /* we had to allocate for this iCode */
+ if (pi) aopPut (AOP (result),rname,0);
freeAsmop (NULL, aop, ic, TRUE);
}
else
}
/* done */
+ if (pi) pi->generated = 1;
+ freeAsmop (result, NULL, ic, TRUE);
freeAsmop (right, NULL, ic, TRUE);
/*-----------------------------------------------------------------*/
static void
genFarPointerSet (operand * right,
- operand * result, iCode * ic)
+ operand * result, iCode * ic, iCode * pi)
{
int size, offset;
sym_link *retype = getSpec (operandType (right));
{ /* we need to get it byte by byte */
emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
- if (options.model == MODEL_FLAT24)
- {
- emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE));
- }
}
}
/* so dptr know contains the address */
- freeAsmop (result, NULL, ic, TRUE);
aopOp (right, ic, FALSE);
/* if bit then unpack */
char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
MOVA (l);
emitcode ("movx", "@dptr,a");
- if (size)
+ if (size || pi)
emitcode ("inc", "dptr");
}
}
-
+ if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
+ aopPut (AOP(result),"dpl",0);
+ aopPut (AOP(result),"dph",1);
+ pi->generated=1;
+ }
+ freeAsmop (result, NULL, ic, TRUE);
freeAsmop (right, NULL, ic, TRUE);
}
/*-----------------------------------------------------------------*/
static void
genGenPointerSet (operand * right,
- operand * result, iCode * ic)
+ operand * result, iCode * ic, iCode * pi)
{
int size, offset;
sym_link *retype = getSpec (operandType (right));
{ /* we need to get it byte by byte */
emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
- if (options.model == MODEL_FLAT24)
- {
- emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE));
- emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE));
- }
- else
- {
- emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
- }
+ emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
}
}
/* so dptr know contains the address */
- freeAsmop (result, NULL, ic, TRUE);
aopOp (right, ic, FALSE);
/* if bit then unpack */
char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
MOVA (l);
emitcode ("lcall", "__gptrput");
- if (size)
+ if (size || pi)
emitcode ("inc", "dptr");
}
}
+ if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
+ aopPut (AOP(result),"dpl",0);
+ aopPut (AOP(result),"dph",1);
+ pi->generated=1;
+ }
+ freeAsmop (result, NULL, ic, TRUE);
freeAsmop (right, NULL, ic, TRUE);
}
/* genPointerSet - stores the value into a pointer location */
/*-----------------------------------------------------------------*/
static void
-genPointerSet (iCode * ic)
+genPointerSet (iCode * ic, iCode *pi)
{
operand *right, *result;
sym_link *type, *etype;
case POINTER:
case IPOINTER:
- genNearPointerSet (right, result, ic);
+ genNearPointerSet (right, result, ic, pi);
break;
case PPOINTER:
- genPagedPointerSet (right, result, ic);
+ genPagedPointerSet (right, result, ic, pi);
break;
case FPOINTER:
- genFarPointerSet (right, result, ic);
+ genFarPointerSet (right, result, ic, pi);
break;
case GPOINTER:
- genGenPointerSet (right, result, ic);
+ genGenPointerSet (right, result, ic, pi);
break;
}
/* fill the result with zero */
size = AOP_SIZE (IC_RESULT (ic)) - 1;
-
- if (options.stack10bit && size < (FPTRSIZE - 1))
- {
- fprintf (stderr,
- "*** warning: pointer to stack var truncated.\n");
- }
-
offset = 1;
while (size--)
{
- /* Yuck! */
- if (options.stack10bit && offset == 2)
- {
- aopPut (AOP (IC_RESULT (ic)), "#0x40", offset++);
- }
- else
- {
- aopPut (AOP (IC_RESULT (ic)), zero, offset++);
- }
+ aopPut (AOP (IC_RESULT (ic)), zero, offset++);
}
goto release;
int size, offset;
unsigned long lit = 0L;
+ D(emitcode(";","genAssign"));
+
result = IC_RESULT (ic);
right = IC_RIGHT (ic);
aopOp (right, ic, FALSE);
/* special case both in far space */
- if ((AOP_TYPE (right) == AOP_DPTR ||
- AOP_TYPE (right) == AOP_DPTR2) &&
+ if (AOP_TYPE (right) == AOP_DPTR &&
IS_TRUE_SYMOP (result) &&
isOperandInFarSpace (result))
{
operand *right = IC_RIGHT (ic);
int size, offset;
+ D(emitcode(";", "genCast"));
+
/* if they are equivalent then do nothing */
if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
return;
aopOp (result, ic, FALSE);
/* if the result is a bit */
- if (AOP_TYPE (result) == AOP_CRY)
+ // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
+ if (IS_BITVAR(OP_SYMBOL(result)->type))
{
/* if the right size is a literal then
we know what the value is */
p_type = DCL_TYPE (type);
else
{
- /* we have to go by the storage class */
- p_type = PTR_TYPE (SPEC_OCLS (etype));
+ if (SPEC_SCLS(etype)==S_REGISTER) {
+ // let's assume it is a generic pointer
+ p_type=GPOINTER;
+ } else {
+ /* we have to go by the storage class */
+ p_type = PTR_TYPE (SPEC_OCLS (etype));
+ }
}
/* the first two bytes are known */
case CPOINTER:
l = "#0x02";
break;
- case PPOINTER:
+ case GPOINTER:
+ l = "0x03";
+ break;
+ case PPOINTER: // what the fck is this?
l = "#0x03";
break;
/* now depending on the sign of the source && destination */
size = AOP_SIZE (result) - AOP_SIZE (right);
/* if unsigned or not an integral type */
- if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
+ if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
{
while (size--)
aopPut (AOP (result), zero, offset++);
aopOp (IC_RESULT (ic), ic, FALSE);
- if (IS_AOP_PREG (IC_RESULT (ic)))
+ if (AOP_NEEDSACC(IC_RESULT(ic)))
+ {
+ /* If the result is accessed indirectly via
+ * the accumulator, we must explicitly write
+ * it back after the decrement.
+ */
+ char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
+
+ if (strcmp(rByte, "a"))
+ {
+ /* Something is hopelessly wrong */
+ fprintf(stderr, "*** warning: internal error at %s:%d\n",
+ __FILE__, __LINE__);
+ /* We can just give up; the generated code will be inefficient,
+ * but what the hey.
+ */
+ freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+ return 0;
+ }
+ emitcode ("dec", "%s", rByte);
+ aopPut(AOP(IC_RESULT(ic)), rByte, 0);
+ emitcode ("jnz", "%05d$", lbl->key + 100);
+ }
+ else if (IS_AOP_PREG (IC_RESULT (ic)))
{
emitcode ("dec", "%s",
aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
{
int size = getSize (operandType (IC_RESULT (ic)));
- int offset = fReturnSize - size;
+ int offset = fReturnSizeMCS51 - size;
while (size--)
{
- emitcode ("push", "%s", (strcmp (fReturn[fReturnSize - offset - 1], "a") ?
- fReturn[fReturnSize - offset - 1] : "acc"));
+ emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
+ fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
offset++;
}
aopOp (IC_RESULT (ic), ic, FALSE);
freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
}
+/*-----------------------------------------------------------------*/
+/* gen51AggregateAssign - copy complete array's or structures */
+/*-----------------------------------------------------------------*/
+void gen51AggregateAssign(iCode *ic) {
+ operand *left=IC_LEFT(ic);
+ operand *right=IC_RIGHT(ic);
+ char *fromName=OP_SYMBOL(right)->rname;
+ char *toName=OP_SYMBOL(left)->rname;
+ int fromSize=getSize(OP_SYMBOL(right)->type);
+ int toSize=getSize(OP_SYMBOL(left)->type);
+ int count=toSize;
+
+ if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
+ SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
+ // well, this code isn't used yet from anywhere else as for initialising
+ fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
+ exit (457);
+ }
+
+ if (fromSize!=toSize) {
+ fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
+ ic->filename, ic->lineno);
+ exit (821);
+ }
+
+#if 1
+ // use the generic memcpy() for now
+ emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
+ emitcode ("mov", "dptr,#_memcpy_PARM_2");
+ emitcode ("mov", "a,#%s", fromName);
+ emitcode ("movx", "@dptr,a");
+ emitcode ("inc", "dptr");
+ emitcode ("mov", "a,#(%s>>8)", fromName);
+ emitcode ("movx", "@dptr,a");
+ emitcode ("inc", "dptr");
+ emitcode ("mov", "a,#%02x; only from cseg for now", 2);
+ emitcode ("movx", "@dptr,a");
+ emitcode ("mov", "dptr,#_memcpy_PARM_3");
+ emitcode ("mov", "a,#(%d>>0); number of bytes", count);
+ emitcode ("movx", "@dptr,a");
+ emitcode ("inc", "dptr");
+ emitcode ("mov", "a,#(%d>>8)", count);
+ emitcode ("movx", "@dptr,a");
+ emitcode ("mov", "dptr,#%s", toName);
+ emitcode ("mov", "b,#%02x; only to xseg for now", 1);
+ emitcode ("lcall", "_memcpy");
+#else
+ // more efficient, but will require the native_memcpy_cs2xs
+ emitcode ("mov", "r0,#%s", fromName);
+ emitcode ("mov", "r1,#(%s>>8)", fromName);
+ emitcode ("mov", "r2,#%s", toName);
+ emitcode ("mov", "r3,#(%s>>8)", toName);
+ emitcode ("mov", "r4,#%d", count);
+ emitcode ("mov", "r5,#(%d>>8)", count);
+ emitcode ("lcall", "_native_memcpy_cs2xs");
+#endif
+}
+
/*-----------------------------------------------------------------*/
/* gen51Code - generate code for 8051 based controllers */
/*-----------------------------------------------------------------*/
if (allocInfo)
printAllocInfo (currFunc, codeOutFile);
/* if debug information required */
-/* if (options.debug && currFunc) { */
- if (currFunc)
+ /* if (options.debug && currFunc) { */
+ if (options.debug && currFunc)
{
cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
_G.debugLine = 1;
break;
case GET_VALUE_AT_ADDRESS:
- genPointerGet (ic);
+ genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
break;
case '=':
if (POINTER_SET (ic))
- genPointerSet (ic);
+ genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
else
genAssign (ic);
break;
addSet (&_G.sendSet, ic);
break;
+ case ARRAYINIT:
+ gen51AggregateAssign(ic);
+ break;
+
default:
ic = ic;
- /* piCode(ic,stdout); */
-
}
}