From 5ade496e10daa3aed1f7fbef6d7199fbd8a4d161 Mon Sep 17 00:00:00 2001 From: johanknol Date: Fri, 16 Nov 2001 14:07:03 +0000 Subject: [PATCH] small stack fix git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@1602 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- src/ds390/gen.c | 10997 ---------------------------------------------- 1 file changed, 10997 deletions(-) diff --git a/src/ds390/gen.c b/src/ds390/gen.c index 3e23ce3e..e69de29b 100644 --- a/src/ds390/gen.c +++ b/src/ds390/gen.c @@ -1,10997 +0,0 @@ -/*------------------------------------------------------------------------- - gen.c - source file for code generation for DS80C390 - - Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998) - and - Jean-Louis VERN.jlvern@writeme.com (1999) - Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a) - DS390 adaptation by Kevin Vigor - - This program is free software; you can redistribute it and/or modify it - under the terms of the GNU General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - In other words, you are welcome to use, share and improve this program. - You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! --------------------------------------------------------------------------*/ - -#include -#include -#include -#include - -#include -#include "ralloc.h" -#include "gen.h" -#include "SDCCglobl.h" -#include "newalloc.h" - -#ifdef HAVE_SYS_ISA_DEFS_H -#include -#else -#ifdef HAVE_MACHINE_ENDIAN_H -#include -#else -#ifdef HAVE_ENDIAN_H -#include -#else -#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 - -#define BETTER_LITERAL_SHIFT - -char *aopLiteral (value * val, int offset); - -/* this is the down and dirty file with all kinds of - kludgy & hacky stuff. This is what it is all about - CODE GENERATION for a specific MCU . some of the - routines may be reusable, will have to see */ - -static char *zero = "#0x00"; -static char *one = "#0x01"; -static char *spname; - -#define D(x) x - -#define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); } -#define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); } - -unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */ -static char *fReturn24[] = -{"dpl", "dph", "dpx", "b", "a"}; -static char *fReturn16[] = -{"dpl", "dph", "b", "a"}; -static char **fReturn = fReturn24; -static char *accUse[] = -{"a", "b"}; - -static short rbank = -1; - -static struct - { - short r0Pushed; - short r1Pushed; - short accInUse; - short inLine; - short debugLine; - short nRegsSaved; - set *sendSet; - } -_G; - -static void saveRBank (int, iCode *, bool); - -#define RESULTONSTACK(x) \ - (IC_RESULT(x) && IC_RESULT(x)->aop && \ - IC_RESULT(x)->aop->type == AOP_STK ) - -/* #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x); */ -#define MOVA(x) { char *_mova_tmp = strdup(x); \ - if (strcmp(_mova_tmp,"a") && strcmp(_mova_tmp,"acc")) \ - { \ - emitcode("mov","a,%s",_mova_tmp); \ - } \ - free(_mova_tmp); \ - } -#define CLRC emitcode("clr","c") -#define SETC emitcode("setb","c") - -// A scratch register which will be used to hold -// result bytes from operands in far space via DPTR2. -#define DP2_RESULT_REG "ap" - -static lineNode *lineHead = NULL; -static lineNode *lineCurr = NULL; - -static unsigned char SLMask[] = -{0xFF, 0xFE, 0xFC, 0xF8, 0xF0, - 0xE0, 0xC0, 0x80, 0x00}; -static unsigned char SRMask[] = -{0xFF, 0x7F, 0x3F, 0x1F, 0x0F, - 0x07, 0x03, 0x01, 0x00}; - -#define LSB 0 -#define MSB16 1 -#define MSB24 2 -#define MSB32 3 - -/*-----------------------------------------------------------------*/ -/* emitcode - writes the code into a file : for now it is simple */ -/*-----------------------------------------------------------------*/ -static void -emitcode (char *inst, char *fmt,...) -{ - va_list ap; - char lb[INITIAL_INLINEASM]; - char *lbp = lb; - - va_start (ap, fmt); - - if (inst && *inst) - { - if (fmt && *fmt) - sprintf (lb, "%s\t", inst); - else - sprintf (lb, "%s", inst); - vsprintf (lb + (strlen (lb)), fmt, ap); - } - else - vsprintf (lb, fmt, ap); - - while (isspace (*lbp)) - lbp++; - - if (lbp && *lbp) - lineCurr = (lineCurr ? - connectLine (lineCurr, newLineNode (lb)) : - (lineHead = newLineNode (lb))); - lineCurr->isInline = _G.inLine; - lineCurr->isDebug = _G.debugLine; - va_end (ap); -} - -/*-----------------------------------------------------------------*/ -/* getFreePtr - returns r0 or r1 whichever is free or can be pushed */ -/*-----------------------------------------------------------------*/ -static regs * -getFreePtr (iCode * ic, asmop ** aopp, bool result) -{ - bool r0iu = FALSE, r1iu = FALSE; - bool r0ou = FALSE, r1ou = FALSE; - - /* the logic: if r0 & r1 used in the instruction - then we are in trouble otherwise */ - - /* first check if r0 & r1 are used by this - instruction, in which case we are in trouble */ - r0iu = bitVectBitValue (ic->rUsed, R0_IDX); - r1iu = bitVectBitValue (ic->rUsed, R1_IDX); - if (r0iu && r1iu) { - goto endOfWorld; - } - - r0ou = bitVectBitValue (ic->rMask, R0_IDX); - r1ou = bitVectBitValue (ic->rMask, R1_IDX); - - /* if no usage of r0 then return it */ - if (!r0iu && !r0ou) - { - ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX); - (*aopp)->type = AOP_R0; - - return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX); - } - - /* if no usage of r1 then return it */ - if (!r1iu && !r1ou) - { - ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX); - (*aopp)->type = AOP_R1; - - return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX); - } - - /* now we know they both have usage */ - /* if r0 not used in this instruction */ - if (!r0iu) - { - /* push it if not already pushed */ - if (!_G.r0Pushed) - { - emitcode ("push", "%s", - ds390_regWithIdx (R0_IDX)->dname); - _G.r0Pushed++; - } - - ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX); - (*aopp)->type = AOP_R0; - - return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX); - } - - /* if r1 not used then */ - - if (!r1iu) - { - /* push it if not already pushed */ - if (!_G.r1Pushed) - { - emitcode ("push", "%s", - ds390_regWithIdx (R1_IDX)->dname); - _G.r1Pushed++; - } - - ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX); - (*aopp)->type = AOP_R1; - return ds390_regWithIdx (R1_IDX); - } - -endOfWorld: - /* I said end of world but not quite end of world yet */ - /* if this is a result then we can push it on the stack */ - if (result) - { - (*aopp)->type = AOP_STK; - return NULL; - } - - /* other wise this is true end of the world */ - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "getFreePtr should never reach here"); - exit (1); -} - -/*-----------------------------------------------------------------*/ -/* newAsmop - creates a new asmOp */ -/*-----------------------------------------------------------------*/ -static asmop * -newAsmop (short type) -{ - asmop *aop; - - aop = Safe_calloc (1, sizeof (asmop)); - aop->type = type; - return aop; -} - -static int _currentDPS; /* Current processor DPS. */ -static int _desiredDPS; /* DPS value compiler thinks we should be using. */ -static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */ - -/*-----------------------------------------------------------------*/ -/* genSetDPTR: generate code to select which DPTR is in use (zero */ -/* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */ -/* alternate DPTR (DPL1/DPH1/DPX1). */ -/*-----------------------------------------------------------------*/ -static void -genSetDPTR (int n) -{ - - /* If we are doing lazy evaluation, simply note the desired - * change, but don't emit any code yet. - */ - if (_lazyDPS) - { - _desiredDPS = n; - return; - } - - if (!n) - { - emitcode ("mov", "dps, #0x00"); - } - else - { - TR_DPTR("#1"); - emitcode ("mov", "dps, #0x01"); - } -} - -/*-----------------------------------------------------------------*/ -/* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */ -/* */ -/* Any code that operates on DPTR (NB: not on the individual */ -/* components, like DPH) *must* call _flushLazyDPS() before using */ -/* DPTR within a lazy DPS evaluation block. */ -/* */ -/* Note that aopPut and aopGet already contain the proper calls to */ -/* _flushLazyDPS, so it is safe to use these calls within a lazy */ -/* DPS evaluation block. */ -/* */ -/* Also, _flushLazyDPS must be called before any flow control */ -/* operations that could potentially branch out of the block. */ -/* */ -/* Lazy DPS evaluation is simply an optimization (though an */ -/* important one), so if in doubt, leave it out. */ -/*-----------------------------------------------------------------*/ -static void -_startLazyDPSEvaluation (void) -{ - _currentDPS = 0; - _desiredDPS = 0; -#ifdef BETTER_LITERAL_SHIFT - _lazyDPS++; -#else - _lazyDPS = 1; -#endif -} - -/*-----------------------------------------------------------------*/ -/* _flushLazyDPS: emit code to force the actual DPS setting to the */ -/* desired one. Call before using DPTR within a lazy DPS evaluation */ -/* block. */ -/*-----------------------------------------------------------------*/ -static void -_flushLazyDPS (void) -{ - if (!_lazyDPS) - { - /* nothing to do. */ - return; - } - - if (_desiredDPS != _currentDPS) - { - if (_desiredDPS) - { - emitcode ("inc", "dps"); - } - else - { - emitcode ("dec", "dps"); - } - _currentDPS = _desiredDPS; - } -} - -/*-----------------------------------------------------------------*/ -/* _endLazyDPSEvaluation: end lazy DPS evaluation block. */ -/* */ -/* Forces us back to the safe state (standard DPTR selected). */ -/*-----------------------------------------------------------------*/ -static void -_endLazyDPSEvaluation (void) -{ -#ifdef BETTER_LITERAL_SHIFT - _lazyDPS--; -#else - _lazyDPS = 0; -#endif - if (!_lazyDPS) - { - if (_currentDPS) - { - genSetDPTR (0); - _flushLazyDPS (); - } - _currentDPS = 0; - _desiredDPS = 0; - } -} - - - -/*-----------------------------------------------------------------*/ -/* pointerCode - returns the code for a pointer type */ -/*-----------------------------------------------------------------*/ -static int -pointerCode (sym_link * etype) -{ - - return PTR_TYPE (SPEC_OCLS (etype)); - -} - -/*-----------------------------------------------------------------*/ -/* aopForSym - for a true symbol */ -/*-----------------------------------------------------------------*/ -static asmop * -aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2) -{ - asmop *aop; - memmap *space = SPEC_OCLS (sym->etype); - - /* if already has one */ - if (sym->aop) - return 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) - { - sym->aop = aop = newAsmop (0); - aop->aopu.aop_ptr = getFreePtr (ic, &aop, result); - aop->size = getSize (sym->type); - - /* now assign the address of the variable to - the pointer register */ - if (aop->type != AOP_STK) - { - - if (sym->onStack) - { - 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); - emitcode ("mov", "%s,a", - aop->aopu.aop_ptr->name); - - if (_G.accInUse) - emitcode ("pop", "acc"); - } - else - emitcode ("mov", "%s,#%s", - aop->aopu.aop_ptr->name, - sym->rname); - aop->paged = space->paged; - } - else - aop->aopu.aop_stk = sym->stack; - 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,_bpx"); - emitcode ("clr","c"); - emitcode ("subb", "a,#0x%02x", - -((sym->stack < 0) ? - ((short) (sym->stack - _G.nRegsSaved)) : - ((short) sym->stack)) & 0xff); - emitcode ("mov","b,a"); - emitcode ("mov","a,#0x%02x",(-((sym->stack < 0) ? - ((short) (sym->stack - _G.nRegsSaved)) : - ((short) sym->stack)) >> 8) & 0xff); - emitcode ("subb","a,_bpx+1"); - if (useDP2) { - if (options.model == MODEL_FLAT24) - emitcode ("mov", "dpx1,#0x40"); - TR_DPTR("#2"); - emitcode ("mov", "dph1,a"); - emitcode ("mov", "dpl1,b"); - } else { - if (options.model == MODEL_FLAT24) - emitcode ("mov", "dpx,#0x40"); - emitcode ("mov", "dph,a"); - emitcode ("mov", "dpl,b"); - } - - if (_G.accInUse) - emitcode ("pop", "acc"); - - sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR)); - aop->size = getSize (sym->type); - return aop; - } - - /* if in bit space */ - if (IN_BITSPACE (space)) - { - sym->aop = aop = newAsmop (AOP_CRY); - aop->aopu.aop_dir = sym->rname; - aop->size = getSize (sym->type); - return aop; - } - /* if it is in direct space */ - if (IN_DIRSPACE (space)) - { - sym->aop = aop = newAsmop (AOP_DIR); - aop->aopu.aop_dir = sym->rname; - aop->size = getSize (sym->type); - return aop; - } - - /* special case for a function */ - if (IS_FUNC (sym->type)) - { - sym->aop = aop = newAsmop (AOP_IMMD); - aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1); - strcpy (aop->aopu.aop_immd.aop_immd1, 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)); - if (useDP2) - { - genSetDPTR (1); - _flushLazyDPS (); - emitcode ("mov", "dptr,#%s", sym->rname); - genSetDPTR (0); - } - else - { - emitcode ("mov", "dptr,#%s", sym->rname); - } - aop->size = getSize (sym->type); - - /* if it is in code space */ - if (IN_CODESPACE (space)) - aop->code = 1; - - return aop; -} - -/*-----------------------------------------------------------------*/ -/* aopForRemat - rematerialzes an object */ -/*-----------------------------------------------------------------*/ -static asmop * -aopForRemat (symbol * sym) -{ - iCode *ic = sym->rematiCode; - asmop *aop = newAsmop (AOP_IMMD); - int ptr_type =0; - int val = 0; - - for (;;) - { - if (ic->op == '+') - val += (int) operandLitValue (IC_RIGHT (ic)); - else if (ic->op == '-') - val -= (int) operandLitValue (IC_RIGHT (ic)); - else if (IS_CAST_ICODE(ic)) { - sym_link *from_type = operandType(IC_RIGHT(ic)); - aop->aopu.aop_immd.from_cast_remat = 1; - ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode; - ptr_type = DCL_TYPE(from_type); - if (ptr_type == IPOINTER) { - // bug #481053 - ptr_type = POINTER; - } - continue ; - } else break; - - ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode; - } - - if (val) - sprintf (buffer, "(%s %c 0x%04x)", - OP_SYMBOL (IC_LEFT (ic))->rname, - val >= 0 ? '+' : '-', - abs (val) & 0xffff); - else - strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname); - - aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1); - strcpy (aop->aopu.aop_immd.aop_immd1, buffer); - /* set immd2 field if required */ - if (aop->aopu.aop_immd.from_cast_remat) { - sprintf(buffer,"#0x%02x",ptr_type); - aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1); - strcpy (aop->aopu.aop_immd.aop_immd2, buffer); - } - - return aop; -} - -/*-----------------------------------------------------------------*/ -/* regsInCommon - two operands have some registers in common */ -/*-----------------------------------------------------------------*/ -static bool -regsInCommon (operand * op1, operand * op2) -{ - symbol *sym1, *sym2; - int i; - - /* if they have registers in common */ - if (!IS_SYMOP (op1) || !IS_SYMOP (op2)) - return FALSE; - - sym1 = OP_SYMBOL (op1); - sym2 = OP_SYMBOL (op2); - - if (sym1->nRegs == 0 || sym2->nRegs == 0) - return FALSE; - - for (i = 0; i < sym1->nRegs; i++) - { - int j; - if (!sym1->regs[i]) - continue; - - for (j = 0; j < sym2->nRegs; j++) - { - if (!sym2->regs[j]) - continue; - - if (sym2->regs[j] == sym1->regs[i]) - return TRUE; - } - } - - return FALSE; -} - -/*-----------------------------------------------------------------*/ -/* operandsEqu - equivalent */ -/*-----------------------------------------------------------------*/ -static bool -operandsEqu (operand * op1, operand * op2) -{ - symbol *sym1, *sym2; - - /* if they not symbols */ - if (!IS_SYMOP (op1) || !IS_SYMOP (op2)) - return FALSE; - - sym1 = OP_SYMBOL (op1); - sym2 = OP_SYMBOL (op2); - - /* if both are itemps & one is spilt - and the other is not then false */ - if (IS_ITEMP (op1) && IS_ITEMP (op2) && - sym1->isspilt != sym2->isspilt) - return FALSE; - - /* if they are the same */ - if (sym1 == sym2) - return TRUE; - - if (strcmp (sym1->rname, sym2->rname) == 0) - return TRUE; - - - /* if left is a tmp & right is not */ - if (IS_ITEMP (op1) && - !IS_ITEMP (op2) && - sym1->isspilt && - (sym1->usl.spillLoc == sym2)) - return TRUE; - - if (IS_ITEMP (op2) && - !IS_ITEMP (op1) && - sym2->isspilt && - sym1->level > 0 && - (sym2->usl.spillLoc == sym1)) - return TRUE; - - return FALSE; -} - -/*-----------------------------------------------------------------*/ -/* sameRegs - two asmops have the same registers */ -/*-----------------------------------------------------------------*/ -static bool -sameRegs (asmop * aop1, asmop * aop2) -{ - int i; - - if (aop1 == aop2) - { - if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2) - { - return FALSE; - } - return TRUE; - } - - if (aop1->type != AOP_REG || - aop2->type != AOP_REG) - return FALSE; - - if (aop1->size != aop2->size) - return FALSE; - - for (i = 0; i < aop1->size; i++) - if (aop1->aopu.aop_reg[i] != - aop2->aopu.aop_reg[i]) - return FALSE; - - return TRUE; -} - -/*-----------------------------------------------------------------*/ -/* aopOp - allocates an asmop for an operand : */ -/*-----------------------------------------------------------------*/ -static void -aopOp (operand * op, iCode * ic, bool result, bool useDP2) -{ - asmop *aop; - symbol *sym; - int i; - - if (!op) - return; - - /* if this a literal */ - if (IS_OP_LITERAL (op)) - { - op->aop = aop = newAsmop (AOP_LIT); - aop->aopu.aop_lit = op->operand.valOperand; - aop->size = getSize (operandType (op)); - return; - } - - /* if already has a asmop then continue */ - if (op->aop) - return; - - /* if the underlying symbol has a aop */ - if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) - { - op->aop = OP_SYMBOL (op)->aop; - return; - } - - /* if this is a true symbol */ - if (IS_TRUE_SYMOP (op)) - { - op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2); - return; - } - - /* this is a temporary : this has - only four choices : - a) register - b) spillocation - c) rematerialize - d) conditional - e) can be a return use only */ - - sym = OP_SYMBOL (op); - - - /* if the type is a conditional */ - if (sym->regType == REG_CND) - { - aop = op->aop = sym->aop = newAsmop (AOP_CRY); - aop->size = 0; - return; - } - - /* if it is spilt then two situations - a) is rematerialize - b) has a spill location */ - if (sym->isspilt || sym->nRegs == 0) - { - - /* rematerialize it NOW */ - if (sym->remat) - { - sym->aop = op->aop = aop = - aopForRemat (sym); - aop->size = getSize (sym->type); - return; - } - - if (sym->accuse) - { - int i; - aop = op->aop = sym->aop = newAsmop (AOP_ACC); - aop->size = getSize (sym->type); - for (i = 0; i < 2; i++) - aop->aopu.aop_str[i] = accUse[i]; - return; - } - - if (sym->ruonly) - { - int i; - - if (useDP2) - { - /* a AOP_STR uses DPTR, but DPTR is already in use; - * we're just hosed. - */ - fprintf (stderr, "*** Internal error: AOP_STR with DPTR in use! for operand %s\n",sym->name); - } - - aop = op->aop = sym->aop = newAsmop (AOP_STR); - aop->size = getSize (sym->type); - for (i = 0; i < (int) fReturnSizeDS390; i++) - aop->aopu.aop_str[i] = fReturn[i]; - return; - } - - /* else spill location */ - sym->aop = op->aop = aop = - aopForSym (ic, sym->usl.spillLoc, result, useDP2); - aop->size = getSize (sym->type); - return; - } - - /* must be in a register */ - sym->aop = op->aop = aop = newAsmop (AOP_REG); - aop->size = sym->nRegs; - for (i = 0; i < sym->nRegs; i++) - aop->aopu.aop_reg[i] = sym->regs[i]; -} - -/*-----------------------------------------------------------------*/ -/* freeAsmop - free up the asmop given to an operand */ -/*----------------------------------------------------------------*/ -static void -freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop) -{ - asmop *aop; - - if (!op) - aop = aaop; - else - aop = op->aop; - - if (!aop) - return; - - if (aop->freed) - goto dealloc; - - aop->freed = 1; - - /* depending on the asmop type only three cases need work AOP_RO - , AOP_R1 && AOP_STK */ - switch (aop->type) - { - case AOP_R0: - if (_G.r0Pushed) - { - if (pop) - { - emitcode ("pop", "ar0"); - _G.r0Pushed--; - } - } - bitVectUnSetBit (ic->rUsed, R0_IDX); - break; - - case AOP_R1: - if (_G.r1Pushed) - { - if (pop) - { - emitcode ("pop", "ar1"); - _G.r1Pushed--; - } - } - bitVectUnSetBit (ic->rUsed, R1_IDX); - break; - - case AOP_STK: - { - int sz = aop->size; - int stk = aop->aopu.aop_stk + aop->size; - bitVectUnSetBit (ic->rUsed, R0_IDX); - bitVectUnSetBit (ic->rUsed, R1_IDX); - - 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"); - emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff); - emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name); - } - else - { - emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name); - } - - while (sz--) - { - emitcode ("pop", "acc"); - emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name); - if (!sz) - break; - emitcode ("dec", "%s", aop->aopu.aop_ptr->name); - } - op->aop = aop; - freeAsmop (op, NULL, ic, TRUE); - if (_G.r0Pushed) - { - emitcode ("pop", "ar0"); - _G.r0Pushed--; - } - - if (_G.r1Pushed) - { - emitcode ("pop", "ar1"); - _G.r1Pushed--; - } - } - } - -dealloc: - /* all other cases just dealloc */ - if (op) - { - op->aop = NULL; - if (IS_SYMOP (op)) - { - OP_SYMBOL (op)->aop = NULL; - /* if the symbol has a spill */ - if (SPIL_LOC (op)) - SPIL_LOC (op)->aop = NULL; - } - } -} - -/*------------------------------------------------------------------*/ -/* aopGet - for fetching value of the aop */ -/* */ -/* Set canClobberACC if you are sure it is OK to clobber the value */ -/* in the accumulator. Set it FALSE otherwise; FALSE is always safe, */ -/* just less efficient. */ -/*------------------------------------------------------------------*/ - -static char * -aopGet (asmop * aop, - int offset, - bool bit16, - bool dname, - bool canClobberACC) -{ - char *s = buffer; - char *rs; - - /* offset is greater than - size then zero */ - if (offset > (aop->size - 1) && - aop->type != AOP_LIT) - return zero; - - /* depending on type */ - switch (aop->type) - { - - case AOP_R0: - case AOP_R1: - /* if we need to increment it */ - while (offset > aop->coff) - { - emitcode ("inc", "%s", aop->aopu.aop_ptr->name); - aop->coff++; - } - - while (offset < aop->coff) - { - emitcode ("dec", "%s", aop->aopu.aop_ptr->name); - aop->coff--; - } - - aop->coff = offset; - if (aop->paged) - { - emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name); - return (dname ? "acc" : "a"); - } - sprintf (s, "@%s", aop->aopu.aop_ptr->name); - rs = Safe_calloc (1, strlen (s) + 1); - strcpy (rs, s); - return rs; - - case AOP_DPTR: - case AOP_DPTR2: - - if (aop->type == AOP_DPTR2) - { - genSetDPTR (1); - if (!canClobberACC) - { - TR_AP("#1"); - emitcode ("xch", "a, %s", DP2_RESULT_REG); - } - } - - _flushLazyDPS (); - - while (offset > aop->coff) - { - emitcode ("inc", "dptr"); - aop->coff++; - } - - while (offset < aop->coff) - { - emitcode ("lcall", "__decdptr"); - aop->coff--; - } - - aop->coff = offset; - if (aop->code) - { - emitcode ("clr", "a"); - emitcode ("movc", "a,@a+dptr"); - } - else - { - emitcode ("movx", "a,@dptr"); - } - - if (aop->type == AOP_DPTR2) - { - genSetDPTR (0); - if (!canClobberACC) - { - TR_AP("#2"); - emitcode ("xch", "a, %s", DP2_RESULT_REG); - return DP2_RESULT_REG; - } - } - return (dname ? "acc" : "a"); - - case AOP_IMMD: - if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) { - sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2); - } else if (bit16) - sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1); - else if (offset) - sprintf (s, "#(%s >> %d)", - aop->aopu.aop_immd.aop_immd1, - offset * 8); - else - sprintf (s, "#%s", - aop->aopu.aop_immd.aop_immd1); - rs = Safe_calloc (1, strlen (s) + 1); - strcpy (rs, s); - return rs; - - case AOP_DIR: - if (offset) - sprintf (s, "(%s + %d)", - aop->aopu.aop_dir, - offset); - else - sprintf (s, "%s", aop->aopu.aop_dir); - rs = Safe_calloc (1, strlen (s) + 1); - strcpy (rs, s); - return rs; - - case AOP_REG: - if (dname) - return aop->aopu.aop_reg[offset]->dname; - else - return aop->aopu.aop_reg[offset]->name; - - case AOP_CRY: - emitcode ("clr", "a"); - emitcode ("mov", "c,%s", aop->aopu.aop_dir); - emitcode ("rlc", "a"); - return (dname ? "acc" : "a"); - - case AOP_ACC: - if (!offset && dname) - return "acc"; - return aop->aopu.aop_str[offset]; - - case AOP_LIT: - return aopLiteral (aop->aopu.aop_lit, offset); - - case AOP_STR: - aop->coff = offset; - if (strcmp (aop->aopu.aop_str[offset], "a") == 0 && - dname) - return "acc"; - - return aop->aopu.aop_str[offset]; - - } - - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "aopget got unsupported aop->type"); - exit (1); -} -/*-----------------------------------------------------------------*/ -/* aopPut - puts a string for a aop */ -/*-----------------------------------------------------------------*/ -static void -aopPut (asmop * aop, char *s, int offset) -{ - char *d = buffer; - - if (aop->size && offset > (aop->size - 1)) - { - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "aopPut got offset > aop->size"); - exit (1); - } - - /* will assign value to value */ - /* depending on where it is ofcourse */ - switch (aop->type) - { - case AOP_DIR: - if (offset) - sprintf (d, "(%s + %d)", - aop->aopu.aop_dir, offset); - else - sprintf (d, "%s", aop->aopu.aop_dir); - - if (strcmp (d, s)) - emitcode ("mov", "%s,%s", d, s); - - break; - - case AOP_REG: - if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 && - strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0) - { - if (*s == '@' || - strcmp (s, "r0") == 0 || - strcmp (s, "r1") == 0 || - strcmp (s, "r2") == 0 || - strcmp (s, "r3") == 0 || - strcmp (s, "r4") == 0 || - strcmp (s, "r5") == 0 || - strcmp (s, "r6") == 0 || - strcmp (s, "r7") == 0) - emitcode ("mov", "%s,%s", - aop->aopu.aop_reg[offset]->dname, s); - else - emitcode ("mov", "%s,%s", - aop->aopu.aop_reg[offset]->name, s); - } - break; - - case AOP_DPTR: - case AOP_DPTR2: - - if (aop->type == AOP_DPTR2) - { - genSetDPTR (1); - } - _flushLazyDPS (); - - if (aop->code) - { - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "aopPut writting to code space"); - exit (1); - } - - while (offset > aop->coff) - { - aop->coff++; - emitcode ("inc", "dptr"); - } - - while (offset < aop->coff) - { - aop->coff--; - emitcode ("lcall", "__decdptr"); - } - - aop->coff = offset; - - /* if not in accumulater */ - MOVA (s); - - emitcode ("movx", "@dptr,a"); - - if (aop->type == AOP_DPTR2) - { - genSetDPTR (0); - } - break; - - case AOP_R0: - case AOP_R1: - while (offset > aop->coff) - { - aop->coff++; - emitcode ("inc", "%s", aop->aopu.aop_ptr->name); - } - while (offset < aop->coff) - { - aop->coff--; - emitcode ("dec", "%s", aop->aopu.aop_ptr->name); - } - aop->coff = offset; - - if (aop->paged) - { - MOVA (s); - emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name); - - } - else if (*s == '@') - { - MOVA (s); - emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name); - } - else if (strcmp (s, "r0") == 0 || - strcmp (s, "r1") == 0 || - strcmp (s, "r2") == 0 || - strcmp (s, "r3") == 0 || - strcmp (s, "r4") == 0 || - strcmp (s, "r5") == 0 || - strcmp (s, "r6") == 0 || - strcmp (s, "r7") == 0) - { - char buffer[10]; - sprintf (buffer, "a%s", s); - emitcode ("mov", "@%s,%s", - aop->aopu.aop_ptr->name, buffer); - } - else - emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s); - - break; - - case AOP_STK: - if (strcmp (s, "a") == 0) - emitcode ("push", "acc"); - else - if (*s=='@') { - MOVA(s); - emitcode ("push", "acc"); - } else { - emitcode ("push", s); - } - - break; - - case AOP_CRY: - /* if bit variable */ - if (!aop->aopu.aop_dir) - { - emitcode ("clr", "a"); - emitcode ("rlc", "a"); - } - else - { - if (s == zero) - emitcode ("clr", "%s", aop->aopu.aop_dir); - else if (s == one) - emitcode ("setb", "%s", aop->aopu.aop_dir); - else if (!strcmp (s, "c")) - emitcode ("mov", "%s,c", aop->aopu.aop_dir); - else - { - if (strcmp (s, "a")) - { - MOVA (s); - } - { - 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; - - case AOP_STR: - aop->coff = offset; - if (strcmp (aop->aopu.aop_str[offset], s)) - emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s); - break; - - case AOP_ACC: - aop->coff = offset; - if (!offset && (strcmp (s, "acc") == 0)) - break; - - if (strcmp (aop->aopu.aop_str[offset], s)) - emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s); - break; - - default: - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "aopPut got unsupported aop->type"); - exit (1); - } - -} - - -/*--------------------------------------------------------------------*/ -/* reAdjustPreg - points a register back to where it should (coff==0) */ -/*--------------------------------------------------------------------*/ -static void -reAdjustPreg (asmop * aop) -{ - if ((aop->coff==0) || (aop->size <= 1)) { - return; - } - - switch (aop->type) - { - case AOP_R0: - case AOP_R1: - 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); - _flushLazyDPS (); - } - while (aop->coff--) - { - emitcode ("lcall", "__decdptr"); - } - - if (aop->type == AOP_DPTR2) - { - genSetDPTR (0); - } - break; - - } - aop->coff=0; -} - -#define AOP(op) op->aop -#define AOP_TYPE(op) AOP(op)->type -#define AOP_SIZE(op) AOP(op)->size -#define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \ - 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)) - -#define AOP_INPREG(x) (x && (x->type == AOP_REG && \ - (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \ - x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) ))) - -/* Workaround for DS80C390 bug: div ab may return bogus results - * if A is accessed in instruction immediately before the div. - * - * Will be fixed in B4 rev of processor, Dallas claims. - */ - -#define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \ - if (!AOP_NEEDSACC(RIGHT)) \ - { \ - /* We can load A first, then B, since \ - * B (the RIGHT operand) won't clobber A, \ - * thus avoiding touching A right before the div. \ - */ \ - D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \ - L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \ - MOVA(L); \ - emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\ - } \ - else \ - { \ - /* Just stuff in a nop after loading A. */ \ - emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,FALSE));\ - L = aopGet(AOP(LEFT),0,FALSE,FALSE,TRUE); \ - MOVA(L); \ - emitcode("nop", "; workaround for DS80C390 div bug."); \ - } - -/*-----------------------------------------------------------------*/ -/* genNotFloat - generates not for float operations */ -/*-----------------------------------------------------------------*/ -static void -genNotFloat (operand * op, operand * res) -{ - int size, offset; - char *l; - 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 (); - l = aopGet (op->aop, offset++, FALSE, FALSE, TRUE); - MOVA (l); - - while (size--) - { - emitcode ("orl", "a,%s", - aopGet (op->aop, - offset++, FALSE, FALSE, FALSE)); - } - _endLazyDPSEvaluation (); - - tlbl = newiTempLabel (NULL); - aopPut (res->aop, one, 1); - emitcode ("jz", "%05d$", (tlbl->key + 100)); - aopPut (res->aop, zero, 1); - emitcode ("", "%05d$:", (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 */ -/* a generic pointer type. */ -/*-----------------------------------------------------------------*/ -static int -opIsGptr (operand * op) -{ - sym_link *type = operandType (op); - - if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type)) - { - return 1; - } - return 0; -} - -/*-----------------------------------------------------------------*/ -/* getDataSize - get the operand data size */ -/*-----------------------------------------------------------------*/ -static int -getDataSize (operand * op) -{ - int size; - size = AOP_SIZE (op); - if (size == GPTRSIZE) - { - sym_link *type = operandType (op); - if (IS_GENPTR (type)) - { - /* generic pointer; arithmetic operations - * should ignore the high byte (pointer type). - */ - size--; - } - } - return size; -} - -/*-----------------------------------------------------------------*/ -/* outAcc - output Acc */ -/*-----------------------------------------------------------------*/ -static void -outAcc (operand * result) -{ - int size, offset; - size = getDataSize (result); - if (size) - { - aopPut (AOP (result), "a", 0); - size--; - offset = 1; - /* unsigned or positive */ - while (size--) - { - aopPut (AOP (result), zero, offset++); - } - } -} - -/*-----------------------------------------------------------------*/ -/* outBitC - output a bit C */ -/*-----------------------------------------------------------------*/ -static void -outBitC (operand * result) -{ - /* if the result is bit */ - if (AOP_TYPE (result) == AOP_CRY) - { - aopPut (AOP (result), "c", 0); - } - else - { - emitcode ("clr", "a"); - emitcode ("rlc", "a"); - outAcc (result); - } -} - -/*-----------------------------------------------------------------*/ -/* toBoolean - emit code for orl a,operator(sizeop) */ -/*-----------------------------------------------------------------*/ -static void -toBoolean (operand * oper) -{ - int size = AOP_SIZE (oper) - 1; - int offset = 1; - bool usedB = FALSE; - - /* The generic part of a generic pointer should - * not participate in it's truth value. - * - * i.e. 0x10000000 is zero. - */ - if (opIsGptr (oper)) - { - D (emitcode (";", "toBoolean: generic ptr special case."); - ); - size--; - } - - _startLazyDPSEvaluation (); - if (AOP_NEEDSACC (oper) && size) - { - usedB = TRUE; - emitcode ("push", "b"); - emitcode ("mov", "b, %s", aopGet (AOP (oper), 0, FALSE, FALSE, FALSE)); - } - else - { - MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, TRUE)); - } - while (size--) - { - if (usedB) - { - emitcode ("orl", "b,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE)); - } - else - { - emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE, FALSE)); - } - } - _endLazyDPSEvaluation (); - - if (usedB) - { - emitcode ("mov", "a,b"); - emitcode ("pop", "b"); - } -} - - -/*-----------------------------------------------------------------*/ -/* genNot - generate code for ! operation */ -/*-----------------------------------------------------------------*/ -static void -genNot (iCode * ic) -{ - symbol *tlbl; - sym_link *optype = operandType (IC_LEFT (ic)); - - D (emitcode (";", "genNot "); - ); - - /* assign asmOps to operand & result */ - aopOp (IC_LEFT (ic), ic, FALSE, FALSE); - aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR); - - /* if in bit space then a special case */ - if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) - { - emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir); - emitcode ("cpl", "c"); - outBitC (IC_RESULT (ic)); - goto release; - } - - /* if type float then do float */ - if (IS_FLOAT (optype)) - { - genNotFloat (IC_LEFT (ic), IC_RESULT (ic)); - goto release; - } - - toBoolean (IC_LEFT (ic)); - - tlbl = newiTempLabel (NULL); - emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100); - emitcode ("", "%05d$:", tlbl->key + 100); - outBitC (IC_RESULT (ic)); - -release: - /* release the aops */ - freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1)); - freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); -} - - -/*-----------------------------------------------------------------*/ -/* genCpl - generate code for complement */ -/*-----------------------------------------------------------------*/ -static void -genCpl (iCode * ic) -{ - int offset = 0; - int size; - - D (emitcode (";", "genCpl "); - ); - - - /* assign asmOps to operand & result */ - aopOp (IC_LEFT (ic), ic, FALSE, FALSE); - aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR); - - /* if both are in bit space then - a special case */ - if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY && - AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) - { - - emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir); - emitcode ("cpl", "c"); - emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir); - goto release; - } - - size = AOP_SIZE (IC_RESULT (ic)); - _startLazyDPSEvaluation (); - while (size--) - { - char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("cpl", "a"); - aopPut (AOP (IC_RESULT (ic)), "a", offset++); - } - _endLazyDPSEvaluation (); - - -release: - /* release the aops */ - freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1)); - freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genUminusFloat - unary minus for floating points */ -/*-----------------------------------------------------------------*/ -static void -genUminusFloat (operand * op, operand * result) -{ - int size, offset = 0; - char *l; - /* for this we just need to flip the - first it then copy the rest in place */ - D (emitcode (";", "genUminusFloat"); - ); - - _startLazyDPSEvaluation (); - size = AOP_SIZE (op) - 1; - l = aopGet (AOP (op), 3, FALSE, FALSE, TRUE); - MOVA (l); - - emitcode ("cpl", "acc.7"); - aopPut (AOP (result), "a", 3); - - while (size--) - { - aopPut (AOP (result), - aopGet (AOP (op), offset, FALSE, FALSE, FALSE), - offset); - offset++; - } - _endLazyDPSEvaluation (); -} - -/*-----------------------------------------------------------------*/ -/* genUminus - unary minus code generation */ -/*-----------------------------------------------------------------*/ -static void -genUminus (iCode * ic) -{ - int offset, size; - sym_link *optype, *rtype; - - D (emitcode (";", "genUminus "); - ); - - - /* assign asmops */ - aopOp (IC_LEFT (ic), ic, FALSE, FALSE); - aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR); - - /* if both in bit space then special - case */ - if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY && - AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) - { - - emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir); - emitcode ("cpl", "c"); - emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir); - goto release; - } - - optype = operandType (IC_LEFT (ic)); - rtype = operandType (IC_RESULT (ic)); - - /* if float then do float stuff */ - if (IS_FLOAT (optype)) - { - genUminusFloat (IC_LEFT (ic), IC_RESULT (ic)); - goto release; - } - - /* otherwise subtract from zero */ - size = AOP_SIZE (IC_LEFT (ic)); - offset = 0; - _startLazyDPSEvaluation (); - while (size--) - { - char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE); - if (!strcmp (l, "a")) - { - if (offset == 0) - SETC; - emitcode ("cpl", "a"); - emitcode ("addc", "a,#0"); - } - else - { - if (offset == 0) - CLRC; - emitcode ("clr", "a"); - emitcode ("subb", "a,%s", l); - } - aopPut (AOP (IC_RESULT (ic)), "a", offset++); - } - _endLazyDPSEvaluation (); - - /* if any remaining bytes in the result */ - /* we just need to propagate the sign */ - if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic))))) - { - emitcode ("rlc", "a"); - emitcode ("subb", "a,acc"); - while (size--) - aopPut (AOP (IC_RESULT (ic)), "a", offset++); - } - -release: - /* release the aops */ - freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1)); - freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* saveRegisters - will look for a call and save the registers */ -/*-----------------------------------------------------------------*/ -static void -saveRegisters (iCode * lic) -{ - int i; - iCode *ic; - bitVect *rsave; - sym_link *detype; - - /* look for call */ - for (ic = lic; ic; ic = ic->next) - if (ic->op == CALL || ic->op == PCALL) - break; - - if (!ic) - { - fprintf (stderr, "found parameter push with no function call\n"); - return; - } - - /* if the registers have been saved already then - do nothing */ - if (ic->regsSaved || IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic)))) 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)) { - int i =0; - rsave = newBitVect(ic->rMask->size); - for (i = DPL_IDX ; i <= B_IDX ; i++ ) { - if (bitVectBitValue(ic->rMask,i)) - rsave = bitVectSetBit(rsave,i); - } - } else { - /* find the registers in use at this time - and push them away to safety */ - rsave = bitVectCplAnd (bitVectCopy (ic->rMask), - ic->rUsed); - } - ic->regsSaved = 1; - if (options.useXstack) - { - if (bitVectBitValue (rsave, R0_IDX)) - emitcode ("mov", "b,r0"); - emitcode ("mov", "r0,%s", spname); - for (i = 0; i < ds390_nRegs; i++) - { - if (bitVectBitValue (rsave, i)) - { - if (i == R0_IDX) - emitcode ("mov", "a,b"); - else - emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name); - emitcode ("movx", "@r0,a"); - emitcode ("inc", "r0"); - } - } - emitcode ("mov", "%s,r0", spname); - if (bitVectBitValue (rsave, R0_IDX)) - emitcode ("mov", "r0,b"); - } - else - for (i = 0; i < ds390_nRegs; i++) - { - if (bitVectBitValue (rsave, i)) - emitcode ("push", "%s", ds390_regWithIdx (i)->dname); - } - - detype = getSpec (operandType (IC_LEFT (ic))); -} - -/*-----------------------------------------------------------------*/ -/* unsaveRegisters - pop the pushed registers */ -/*-----------------------------------------------------------------*/ -static void -unsaveRegisters (iCode * ic) -{ - int i; - bitVect *rsave; - - if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) { - int i =0; - rsave = newBitVect(ic->rMask->size); - for (i = DPL_IDX ; i <= B_IDX ; i++ ) { - if (bitVectBitValue(ic->rMask,i)) - rsave = bitVectSetBit(rsave,i); - } - } else { - /* find the registers in use at this time - and push them away to safety */ - rsave = bitVectCplAnd (bitVectCopy (ic->rMask), - ic->rUsed); - } - if (options.useXstack) - { - emitcode ("mov", "r0,%s", spname); - for (i = ds390_nRegs; i >= 0; i--) - { - if (bitVectBitValue (rsave, i)) - { - emitcode ("dec", "r0"); - emitcode ("movx", "a,@r0"); - if (i == R0_IDX) - emitcode ("mov", "b,a"); - else - emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name); - } - - } - emitcode ("mov", "%s,r0", spname); - if (bitVectBitValue (rsave, R0_IDX)) - emitcode ("mov", "r0,b"); - } - else - for (i = ds390_nRegs; i >= 0; i--) - { - if (bitVectBitValue (rsave, i)) - emitcode ("pop", "%s", ds390_regWithIdx (i)->dname); - } - -} - - -/*-----------------------------------------------------------------*/ -/* pushSide - */ -/*-----------------------------------------------------------------*/ -static void -pushSide (operand * oper, int size) -{ - int offset = 0; - _startLazyDPSEvaluation (); - while (size--) - { - char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, FALSE); - if (AOP_TYPE (oper) != AOP_REG && - AOP_TYPE (oper) != AOP_DIR && - strcmp (l, "a")) - { - emitcode ("mov", "a,%s", l); - emitcode ("push", "acc"); - } - else - emitcode ("push", "%s", l); - } - _endLazyDPSEvaluation (); -} - -/*-----------------------------------------------------------------*/ -/* assignResultValue - */ -/*-----------------------------------------------------------------*/ -static void -assignResultValue (operand * oper) -{ - int offset = 0; - int size = AOP_SIZE (oper); - - _startLazyDPSEvaluation (); - while (size--) - { - aopPut (AOP (oper), fReturn[offset], offset); - offset++; - } - _endLazyDPSEvaluation (); -} - - -/*-----------------------------------------------------------------*/ -/* genXpush - pushes onto the external stack */ -/*-----------------------------------------------------------------*/ -static void -genXpush (iCode * ic) -{ - asmop *aop = newAsmop (0); - regs *r; - int size, offset = 0; - - D (emitcode (";", "genXpush "); - ); - - aopOp (IC_LEFT (ic), ic, FALSE, FALSE); - r = getFreePtr (ic, &aop, FALSE); - - - emitcode ("mov", "%s,_spx", r->name); - - size = AOP_SIZE (IC_LEFT (ic)); - _startLazyDPSEvaluation (); - while (size--) - { - - char *l = aopGet (AOP (IC_LEFT (ic)), - offset++, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("movx", "@%s,a", r->name); - emitcode ("inc", "%s", r->name); - - } - _endLazyDPSEvaluation (); - - - emitcode ("mov", "_spx,%s", r->name); - - freeAsmop (NULL, aop, ic, TRUE); - freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genIpush - genrate code for pushing this gets a little complex */ -/*-----------------------------------------------------------------*/ -static void -genIpush (iCode * ic) -{ - 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 */ - if (!ic->parmPush) - { - - /* and the item is spilt then do nothing */ - if (OP_SYMBOL (IC_LEFT (ic))->isspilt) - return; - - aopOp (IC_LEFT (ic), ic, FALSE, FALSE); - size = AOP_SIZE (IC_LEFT (ic)); - /* push it on the stack */ - _startLazyDPSEvaluation (); - while (size--) - { - l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, TRUE); - if (*l == '#') - { - MOVA (l); - l = "acc"; - } - emitcode ("push", "%s", l); - } - _endLazyDPSEvaluation (); - return; - } - - /* this is a paramter push: in this case we call - the routine to find the call and save those - registers that need to be saved */ - saveRegisters (ic); - - /* if use external stack then call the external - stack pushing routine */ - if (options.useXstack) - { - genXpush (ic); - return; - } - - /* then do the push */ - aopOp (IC_LEFT (ic), ic, FALSE, FALSE); - - // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic))); - size = AOP_SIZE (IC_LEFT (ic)); - - _startLazyDPSEvaluation (); - while (size--) - { - l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, FALSE); - if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG && - AOP_TYPE (IC_LEFT (ic)) != AOP_DIR && - strcmp (l, "a")) - { - emitcode ("mov", "a,%s", l); - emitcode ("push", "acc"); - } - else - emitcode ("push", "%s", l); - } - _endLazyDPSEvaluation (); - - freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genIpop - recover the registers: can happen only for spilling */ -/*-----------------------------------------------------------------*/ -static void -genIpop (iCode * ic) -{ - int size, offset; - - D (emitcode (";", "genIpop "); - ); - - - /* if the temp was not pushed then */ - if (OP_SYMBOL (IC_LEFT (ic))->isspilt) - return; - - aopOp (IC_LEFT (ic), ic, FALSE, FALSE); - size = AOP_SIZE (IC_LEFT (ic)); - offset = (size - 1); - _startLazyDPSEvaluation (); - while (size--) - { - emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--, - FALSE, TRUE, TRUE)); - } - _endLazyDPSEvaluation (); - - freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* unsaveRBank - restores the resgister bank from stack */ -/*-----------------------------------------------------------------*/ -static void -unsaveRBank (int bank, iCode * ic, bool popPsw) -{ - int i; - asmop *aop = NULL; - regs *r = NULL; - - if (options.useXstack) - { - if (!ic) - { - /* Assume r0 is available for use. */ - r = ds390_regWithIdx (R0_IDX);; - } - else - { - aop = newAsmop (0); - r = getFreePtr (ic, &aop, FALSE); - } - emitcode ("mov", "%s,_spx", r->name); - } - - if (popPsw) - { - if (options.useXstack) - { - emitcode ("movx", "a,@%s", r->name); - emitcode ("mov", "psw,a"); - emitcode ("dec", "%s", r->name); - } - else - { - emitcode ("pop", "psw"); - } - } - - for (i = (ds390_nRegs - 1); i >= 0; i--) - { - if (options.useXstack) - { - emitcode ("movx", "a,@%s", r->name); - emitcode ("mov", "(%s+%d),a", - regs390[i].base, 8 * bank + regs390[i].offset); - emitcode ("dec", "%s", r->name); - - } - else - emitcode ("pop", "(%s+%d)", - regs390[i].base, 8 * bank + regs390[i].offset); - } - - if (options.useXstack) - { - emitcode ("mov", "_spx,%s", r->name); - } - - if (aop) - { - freeAsmop (NULL, aop, ic, TRUE); - } -} - -/*-----------------------------------------------------------------*/ -/* saveRBank - saves an entire register bank on the stack */ -/*-----------------------------------------------------------------*/ -static void -saveRBank (int bank, iCode * ic, bool pushPsw) -{ - int i; - asmop *aop = NULL; - regs *r = NULL; - - if (options.useXstack) - { - if (!ic) - { - /* Assume r0 is available for use. */ - r = ds390_regWithIdx (R0_IDX);; - } - else - { - aop = newAsmop (0); - r = getFreePtr (ic, &aop, FALSE); - } - emitcode ("mov", "%s,_spx", r->name); - } - - for (i = 0; i < ds390_nRegs; i++) - { - if (options.useXstack) - { - emitcode ("inc", "%s", r->name); - emitcode ("mov", "a,(%s+%d)", - regs390[i].base, 8 * bank + regs390[i].offset); - emitcode ("movx", "@%s,a", r->name); - } - else - emitcode ("push", "(%s+%d)", - regs390[i].base, 8 * bank + regs390[i].offset); - } - - if (pushPsw) - { - if (options.useXstack) - { - emitcode ("mov", "a,psw"); - emitcode ("movx", "@%s,a", r->name); - emitcode ("inc", "%s", r->name); - emitcode ("mov", "_spx,%s", r->name); - } - else - { - emitcode ("push", "psw"); - } - - emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff); - } - - if (aop) - { - freeAsmop (NULL, aop, ic, TRUE); - } - - if (ic) - { - ic->bankSaved = 1; - } -} - -/*-----------------------------------------------------------------*/ -/* genCall - generates a call statement */ -/*-----------------------------------------------------------------*/ -static void -genCall (iCode * ic) -{ - sym_link *dtype; - bool restoreBank = FALSE; - bool swapBanks = FALSE; - - D (emitcode (";", "genCall ");); - - /* 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 send set is not empty the assign */ - /* We've saved all the registers we care about; - * therefore, we may clobber any register not used - * in the calling convention (i.e. anything not in - * fReturn. - */ - if (_G.sendSet) - { - iCode *sic; - - for (sic = setFirstItem (_G.sendSet); sic; - sic = setNextItem (_G.sendSet)) - { - int size, offset = 0; - -#if 0 - aopOp (IC_LEFT (sic), sic, FALSE, FALSE); - size = AOP_SIZE (IC_LEFT (sic)); - - _startLazyDPSEvaluation (); - while (size--) - { - char *l = aopGet (AOP(IC_LEFT(sic)), offset, - FALSE, FALSE, TRUE); - if ((AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) && size) - { - emitcode("mov", "%s,%s", regs390[offset].name, l); - } - else if (strcmp (l, fReturn[offset])) - { - emitcode ("mov", "%s,%s", - fReturn[offset], - l); - } - offset++; - } - _endLazyDPSEvaluation (); - if (AOP_TYPE(IC_LEFT(sic)) == AOP_DPTR) - { - size = AOP_SIZE (IC_LEFT (sic)); - if (size) - { - size--; - } - while (size) - { - size--; - emitcode("mov", "%s,%s", - fReturn[size], regs390[size].name); - } - } -#else - // we know that dpl(hxb) is the result, so - _startLazyDPSEvaluation (); - size=getSize(operandType(IC_LEFT(sic))); - if (size>1) { - aopOp (IC_LEFT (sic), sic, FALSE, TRUE); - } else { - aopOp (IC_LEFT (sic), sic, FALSE, FALSE); - } - while (size--) - { - char *l = aopGet (AOP (IC_LEFT (sic)), offset, - FALSE, FALSE, TRUE); - if (strcmp (l, fReturn[offset])) - { - emitcode ("mov", "%s,%s", - fReturn[offset], - l); - } - offset++; - } - _endLazyDPSEvaluation (); -#endif - freeAsmop (IC_LEFT (sic), NULL, sic, TRUE); - } - _G.sendSet = NULL; - } - - 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 || - OP_SYMBOL (IC_RESULT (ic))->accuse || - OP_SYMBOL (IC_RESULT (ic))->spildir)) || - IS_TRUE_SYMOP (IC_RESULT (ic))) - { - if (isOperandInFarSpace (IC_RESULT (ic)) - && getSize (operandType (IC_RESULT (ic))) <= 2) - { - int size = getSize (operandType (IC_RESULT (ic))); - - /* Special case for 1 or 2 byte return in far space. */ - MOVA (fReturn[0]); - if (size > 1) - { - emitcode ("mov", "b,%s", fReturn[1]); - } - - aopOp (IC_RESULT (ic), ic, FALSE, FALSE); - aopPut (AOP (IC_RESULT (ic)), "a", 0); - - if (size > 1) - { - aopPut (AOP (IC_RESULT (ic)), "b", 1); - } - freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); - } - else - { - _G.accInUse++; - aopOp (IC_RESULT (ic), ic, FALSE, TRUE); - _G.accInUse--; - - assignResultValue (IC_RESULT (ic)); - - freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); - } - } - - /* adjust the stack for parameters if - required */ - if (ic->parmBytes) { - if (options.stack10bit) { - emitcode ("clr","c"); - emitcode ("mov","a,sp"); - emitcode ("subb","a,#0x%02x",ic->parmBytes & 0xff); - emitcode ("mov","sp,a"); - emitcode ("mov","a,#0x%02x",(ic->parmBytes >> 8) & 0xff); - emitcode ("subb","a,esp"); - emitcode ("mov","esp,a"); - } else { - int i; - if (ic->parmBytes > 3) { - emitcode ("mov", "a,%s", spname); - emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff); - emitcode ("mov", "%s,a", spname); - } else - for (i = 0; i < ic->parmBytes; i++) - emitcode ("dec", "%s", spname); - } - } - - /* if we hade saved some registers then unsave them */ - if (ic->regsSaved) - unsaveRegisters (ic); - - /* if register bank was saved then pop them */ - if (restoreBank) - unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE); -} - -/*-----------------------------------------------------------------*/ -/* genPcall - generates a call by pointer statement */ -/*-----------------------------------------------------------------*/ -static void -genPcall (iCode * ic) -{ - sym_link *dtype; - symbol *rlbl = newiTempLabel (NULL); - bool restoreBank=FALSE; - - D (emitcode (";", "genPcall "); - ); - - - /* 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 */ - dtype = operandType (IC_LEFT (ic)); - if (dtype && !IFFUNC_ISNAKED(dtype) && - IFFUNC_ISISR (currFunc->type) && - (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) { - saveRBank (FUNC_REGBANK (dtype), ic, TRUE); - restoreBank=TRUE; - } - - /* push the return address on to the stack */ - emitcode ("mov", "a,#%05d$", (rlbl->key + 100)); - emitcode ("push", "acc"); - 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, FALSE); - - pushSide (IC_LEFT (ic), FPTRSIZE); - - freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); - - /* if send set is not empty the assign */ - if (_G.sendSet) - { - iCode *sic; - - for (sic = setFirstItem (_G.sendSet); sic; - sic = setNextItem (_G.sendSet)) - { - int size, offset = 0; - - // we know that dpl(hxb) is the result, so - _startLazyDPSEvaluation (); - size=getSize(operandType(IC_LEFT(sic))); - if (size>1) { - aopOp (IC_LEFT (sic), sic, FALSE, TRUE); - } else { - aopOp (IC_LEFT (sic), sic, FALSE, FALSE); - } - while (size--) - { - char *l = aopGet (AOP (IC_LEFT (sic)), offset, - FALSE, FALSE, TRUE); - if (strcmp (l, fReturn[offset])) - { - emitcode ("mov", "%s,%s", - fReturn[offset], - l); - } - offset++; - } - _endLazyDPSEvaluation (); - freeAsmop (IC_LEFT (sic), NULL, sic, TRUE); - } - _G.sendSet = NULL; - } - - emitcode ("ret", ""); - emitcode ("", "%05d$:", (rlbl->key + 100)); - - - /* if we need assign a result value */ - if ((IS_ITEMP (IC_RESULT (ic)) && - (OP_SYMBOL (IC_RESULT (ic))->nRegs || - OP_SYMBOL (IC_RESULT (ic))->spildir)) || - IS_TRUE_SYMOP (IC_RESULT (ic))) - { - - _G.accInUse++; - aopOp (IC_RESULT (ic), ic, FALSE, TRUE); - _G.accInUse--; - - assignResultValue (IC_RESULT (ic)); - - freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); - } - - /* adjust the stack for parameters if - required */ - if (ic->parmBytes) - { - int i; - if (ic->parmBytes > 3) - { - emitcode ("mov", "a,%s", spname); - emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff); - emitcode ("mov", "%s,a", spname); - } - else - for (i = 0; i < ic->parmBytes; i++) - emitcode ("dec", "%s", spname); - - } - - /* if register bank was saved then unsave them */ - if (restoreBank) - unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE); - - /* if we hade saved some registers then - unsave them */ - if (ic->regsSaved) - unsaveRegisters (ic); - -} - -/*-----------------------------------------------------------------*/ -/* resultRemat - result is rematerializable */ -/*-----------------------------------------------------------------*/ -static int -resultRemat (iCode * ic) -{ - if (SKIP_IC (ic) || ic->op == IFX) - return 0; - - if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic))) - { - symbol *sym = OP_SYMBOL (IC_RESULT (ic)); - if (sym->remat && !POINTER_SET (ic)) - return 1; - } - - return 0; -} - -#if defined(__BORLANDC__) || defined(_MSC_VER) -#define STRCASECMP stricmp -#else -#define STRCASECMP strcasecmp -#endif - -/*-----------------------------------------------------------------*/ -/* inExcludeList - return 1 if the string is in exclude Reg list */ -/*-----------------------------------------------------------------*/ -static bool -inExcludeList (char *s) -{ - int i = 0; - - if (options.excludeRegs[i] && - STRCASECMP (options.excludeRegs[i], "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; -} - -/*-----------------------------------------------------------------*/ -/* genFunction - generated code for function entry */ -/*-----------------------------------------------------------------*/ -static void -genFunction (iCode * ic) -{ - symbol *sym; - sym_link *ftype; - bool switchedPSW = FALSE; - - D (emitcode (";", "genFunction ");); - - _G.nRegsSaved = 0; - /* create the function header */ - emitcode (";", "-----------------------------------------"); - emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name); - emitcode (";", "-----------------------------------------"); - - emitcode ("", "%s:", sym->rname); - ftype = operandType (IC_LEFT (ic)); - - if (IFFUNC_ISNAKED(ftype)) - { - emitcode(";", "naked function: no prologue."); - return; - } - - /* 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 */ - if (FUNC_REGBANK (ftype) != rbank) - { - int i; - - rbank = FUNC_REGBANK (ftype); - for (i = 0; i < ds390_nRegs; i++) - { - if (regs390[i].print) { - if (strcmp (regs390[i].base, "0") == 0) - emitcode ("", "%s = 0x%02x", - regs390[i].dname, - 8 * rbank + regs390[i].offset); - else - emitcode ("", "%s = %s + 0x%02x", - regs390[i].dname, - regs390[i].base, - 8 * rbank + regs390[i].offset); - } - } - } - - /* if this is an interrupt service routine then - save acc, b, dpl, dph */ - if (IFFUNC_ISISR (sym->type)) - { - - if (!inExcludeList ("acc")) - emitcode ("push", "acc"); - if (!inExcludeList ("b")) - emitcode ("push", "b"); - if (!inExcludeList ("dpl")) - 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"); - emitcode ("push", DP2_RESULT_REG); - } - } - /* if this isr has no bank i.e. is going to - run with bank 0 , then we need to save more - registers :-) */ - 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 (!IFFUNC_HASFCALL(sym->type)) - { - int i; - - /* if any registers used */ - if (sym->regsUsed) - { - /* 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))) - emitcode ("push", "%s", ds390_regWithIdx (i)->dname); - } - } - - } - else - { - /* this function has a function call cannot - determines register usage so we will have to push the - entire bank */ - 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 (IFFUNC_CALLEESAVES(sym->type)) - { - int i; - - /* if any registers used */ - if (sym->regsUsed) - { - /* 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))) - { - emitcode ("push", "%s", ds390_regWithIdx (i)->dname); - _G.nRegsSaved++; - } - } - } - } - } - - /* set the register bank to the desired value */ - if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type)) - && !switchedPSW) - { - emitcode ("push", "psw"); - emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff); - } - - if (IFFUNC_ISREENT (sym->type) || options.stackAuto) { - if (options.stack10bit) { - emitcode ("push","_bpx"); - emitcode ("push","_bpx+1"); - emitcode ("mov","_bpx,%s",spname); - emitcode ("mov","_bpx+1,esp"); - emitcode ("anl","_bpx+1,#3"); - } else { - if (options.useXstack) { - emitcode ("mov", "r0,%s", spname); - emitcode ("mov", "a,_bp"); - emitcode ("movx", "@r0,a"); - emitcode ("inc", "%s", spname); - } else { - /* set up the stack */ - emitcode ("push", "_bp"); /* save the callers stack */ - } - emitcode ("mov", "_bp,%s", spname); - } - } - - /* adjust the stack for the function */ - if (sym->stack) { - int i = sym->stack; - if (options.stack10bit) { - if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name); - assert (sym->recvSize <= 4); - emitcode ("mov","a,sp"); - emitcode ("add","a,#0x%02x", ((short) sym->stack & 0xff)); - emitcode ("mov","sp,a"); - emitcode ("mov","a,esp"); - emitcode ("addc","a,0x%02x", (((short) sym->stack) >> 8) & 0xff); - emitcode ("mov","esp,a"); - } else { - if (i > 256) - werror (W_STACK_OVERFLOW, sym->name); - - if (i > 3 && sym->recvSize < 4) { - - emitcode ("mov", "a,sp"); - emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff)); - emitcode ("mov", "sp,a"); - - } else - while (i--) - emitcode ("inc", "sp"); - } - } - - if (sym->xstack) - { - - emitcode ("mov", "a,_spx"); - emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff)); - emitcode ("mov", "_spx,a"); - } - -} - -/*-----------------------------------------------------------------*/ -/* genEndFunction - generates epilogue for functions */ -/*-----------------------------------------------------------------*/ -static void -genEndFunction (iCode * ic) -{ - symbol *sym = OP_SYMBOL (IC_LEFT (ic)); - - D (emitcode (";", "genEndFunction ");); - - if (IFFUNC_ISNAKED(sym->type)) - { - emitcode(";", "naked function: no epilogue."); - return; - } - - if (IFFUNC_ISREENT (sym->type) || options.stackAuto) { - if (options.stack10bit) { - emitcode ("mov", "sp,_bpx", spname); - emitcode ("mov", "esp,_bpx+1", spname); - } else { - emitcode ("mov", "%s,_bp", spname); - } - } - - /* if use external stack but some variables were - added to the local stack then decrement the - local stack */ - if (options.useXstack && sym->stack) { - emitcode ("mov", "a,sp"); - emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff); - emitcode ("mov", "sp,a"); - } - - - if ((IFFUNC_ISREENT (sym->type) || options.stackAuto)) { - if (options.useXstack) { - emitcode ("mov", "r0,%s", spname); - emitcode ("movx", "a,@r0"); - emitcode ("mov", "_bp,a"); - emitcode ("dec", "%s", spname); - } else { - if (options.stack10bit) { - emitcode ("pop", "_bpx+1"); - emitcode ("pop", "_bpx"); - } else { - emitcode ("pop", "_bp"); - } - } - } - - /* restore the register bank */ - 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 (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 (!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 (!IFFUNC_HASFCALL(sym->type)) - { - int i; - - /* if any registers used */ - if (sym->regsUsed) - { - /* 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))) - emitcode ("pop", "%s", ds390_regWithIdx (i)->dname); - } - } - - } - else - { - /* this function has a function call cannot - determines register usage so we will have to pop the - entire bank */ - unsaveRBank (0, ic, FALSE); - } - } - else - { - /* 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--) - { - if (savedBanks & (1 << ix)) - { - unsaveRBank(ix, NULL, FALSE); - } - } - - if (options.useXstack) - { - /* Restore bank AFTER calling unsaveRBank, - * since it can trash r0. - */ - emitcode ("pop", "psw"); - } - } - - if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx")) - { - if (options.stack10bit) - { - emitcode ("pop", DP2_RESULT_REG); - emitcode ("pop", "dpx1"); - emitcode ("pop", "dph1"); - emitcode ("pop", "dpl1"); - } - emitcode ("pop", "dps"); - emitcode ("pop", "dpx"); - } - if (!inExcludeList ("dph")) - emitcode ("pop", "dph"); - if (!inExcludeList ("dpl")) - emitcode ("pop", "dpl"); - if (!inExcludeList ("b")) - emitcode ("pop", "b"); - 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; - emitcode ("", "C$%s$%d$%d$%d ==.", - FileBaseName (ic->filename), currFunc->lastLine, - ic->level, ic->block); - if (IS_STATIC (currFunc->etype)) - emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name); - else - emitcode ("", "XG$%s$0$0 ==.", currFunc->name); - _G.debugLine = 0; - } - - emitcode ("reti", ""); - } - else - { - if (IFFUNC_ISCRITICAL (sym->type)) - emitcode ("setb", "ea"); - - if (IFFUNC_CALLEESAVES(sym->type)) - { - int i; - - /* if any registers used */ - if (sym->regsUsed) - { - /* 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))) - emitcode ("pop", "%s", ds390_regWithIdx (i)->dname); - } - } - - } - - /* if debug then send end of function */ - if (options.debug && currFunc) - { - _G.debugLine = 1; - emitcode ("", "C$%s$%d$%d$%d ==.", - FileBaseName (ic->filename), currFunc->lastLine, - ic->level, ic->block); - if (IS_STATIC (currFunc->etype)) - emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name); - else - emitcode ("", "XG$%s$0$0 ==.", currFunc->name); - _G.debugLine = 0; - } - - emitcode ("ret", ""); - } - -} - -/*-----------------------------------------------------------------*/ -/* genRet - generate code for return statement */ -/*-----------------------------------------------------------------*/ -static void -genRet (iCode * ic) -{ - int size, offset = 0, pushed = 0; - - D (emitcode (";", "genRet "); - ); - - /* if we have no return value then - just generate the "ret" */ - if (!IC_LEFT (ic)) - goto jumpret; - - /* we have something to return then - move the return value into place */ - aopOp (IC_LEFT (ic), ic, FALSE, - (IS_SYMOP(IC_LEFT(ic)) && OP_SYMBOL(IC_LEFT(ic))->ruonly ? FALSE :TRUE)); - size = AOP_SIZE (IC_LEFT (ic)); - - _startLazyDPSEvaluation (); - while (size--) - { - char *l; - if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) - { - l = aopGet (AOP (IC_LEFT (ic)), offset++, - FALSE, TRUE, FALSE); - emitcode ("push", "%s", l); - pushed++; - } - else - { - /* Since A is the last element of fReturn, - * is is OK to clobber it in the aopGet. - */ - l = aopGet (AOP (IC_LEFT (ic)), offset, - FALSE, FALSE, TRUE); - if (strcmp (fReturn[offset], l)) - emitcode ("mov", "%s,%s", fReturn[offset++], l); - } - } - _endLazyDPSEvaluation (); - - if (pushed) - { - while (pushed) - { - pushed--; - if (strcmp (fReturn[pushed], "a")) - emitcode ("pop", fReturn[pushed]); - else - emitcode ("pop", "acc"); - } - } - freeAsmop (IC_LEFT (ic), NULL, ic, TRUE); - -jumpret: - /* generate a jump to the return label - if the next is not the return statement */ - if (!(ic->next && ic->next->op == LABEL && - IC_LABEL (ic->next) == returnLabel)) - - emitcode ("ljmp", "%05d$", (returnLabel->key + 100)); - -} - -/*-----------------------------------------------------------------*/ -/* genLabel - generates a label */ -/*-----------------------------------------------------------------*/ -static void -genLabel (iCode * ic) -{ - /* special case never generate */ - if (IC_LABEL (ic) == entryLabel) - return; - - D (emitcode (";", "genLabel "); - ); - - emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100)); -} - -/*-----------------------------------------------------------------*/ -/* genGoto - generates a ljmp */ -/*-----------------------------------------------------------------*/ -static void -genGoto (iCode * ic) -{ - D (emitcode (";", "genGoto "); - ); - emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100)); -} - -/*-----------------------------------------------------------------*/ -/* findLabelBackwards: walks back through the iCode chain looking */ -/* for the given label. Returns number of iCode instructions */ -/* between that label and given ic. */ -/* Returns zero if label not found. */ -/*-----------------------------------------------------------------*/ -static int -findLabelBackwards (iCode * ic, int key) -{ - int count = 0; - - while (ic->prev) - { - ic = ic->prev; - count++; - - if (ic->op == LABEL && IC_LABEL (ic)->key == key) - { - /* printf("findLabelBackwards = %d\n", count); */ - return count; - } - } - - return 0; -} - -/*-----------------------------------------------------------------*/ -/* genPlusIncr :- does addition with increment if possible */ -/*-----------------------------------------------------------------*/ -static bool -genPlusIncr (iCode * ic) -{ - unsigned int icount; - unsigned int size = getDataSize (IC_RESULT (ic)); - - /* will try to generate an increment */ - /* if the right side is not a literal - we cannot */ - if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) - return FALSE; - - /* if the literal value of the right hand side - is greater than 4 then it is not worth it */ - if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4) - return FALSE; - - /* if increment 16 bits in register */ - if ( - AOP_TYPE (IC_LEFT (ic)) == AOP_REG && - AOP_TYPE (IC_RESULT (ic)) == AOP_REG && - sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) && - (size > 1) && - (icount == 1)) - { - symbol *tlbl; - int emitTlbl; - int labelRange; - - /* If the next instruction is a goto and the goto target - * is <= 5 instructions previous to this, we can generate - * jumps straight to that target. - */ - if (ic->next && ic->next->op == GOTO - && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0 - && labelRange <= 5) - { - emitcode (";", "tail increment optimized (range %d)", labelRange); - tlbl = IC_LABEL (ic->next); - emitTlbl = 0; - } - else - { - tlbl = newiTempLabel (NULL); - emitTlbl = 1; - } - emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)); - if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG || - IS_AOP_PREG (IC_RESULT (ic))) - emitcode ("cjne", "%s,#0x00,%05d$" - ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE) - ,tlbl->key + 100); - else - { - emitcode ("clr", "a"); - emitcode ("cjne", "a,%s,%05d$" - ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE) - ,tlbl->key + 100); - } - - emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)); - if (size > 2) - { - if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG || - IS_AOP_PREG (IC_RESULT (ic))) - emitcode ("cjne", "%s,#0x00,%05d$" - ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE) - ,tlbl->key + 100); - else - emitcode ("cjne", "a,%s,%05d$" - ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE) - ,tlbl->key + 100); - - emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)); - } - if (size > 3) - { - if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG || - IS_AOP_PREG (IC_RESULT (ic))) - emitcode ("cjne", "%s,#0x00,%05d$" - ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE) - ,tlbl->key + 100); - else - { - emitcode ("cjne", "a,%s,%05d$" - ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE) - ,tlbl->key + 100); - } - emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE)); - } - - if (emitTlbl) - { - emitcode ("", "%05d$:", tlbl->key + 100); - } - return TRUE; - } - - /* if the sizes are greater than 1 then we cannot */ - if (AOP_SIZE (IC_RESULT (ic)) > 1 || - AOP_SIZE (IC_LEFT (ic)) > 1) - return FALSE; - - /* we can if the aops of the left & result match or - if they are in registers and the registers are the - same */ - if ( - AOP_TYPE (IC_LEFT (ic)) == AOP_REG && - AOP_TYPE (IC_RESULT (ic)) == AOP_REG && - sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)))) - { - - if (icount > 3) - { - MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, TRUE)); - emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff); - aopPut (AOP (IC_RESULT (ic)), "a", 0); - } - else - { - - _startLazyDPSEvaluation (); - while (icount--) - { - emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, FALSE)); - } - _endLazyDPSEvaluation (); - } - - return TRUE; - } - - return FALSE; -} - -/*-----------------------------------------------------------------*/ -/* outBitAcc - output a bit in acc */ -/*-----------------------------------------------------------------*/ -static void -outBitAcc (operand * result) -{ - symbol *tlbl = newiTempLabel (NULL); - /* if the result is a bit */ - if (AOP_TYPE (result) == AOP_CRY) - { - aopPut (AOP (result), "a", 0); - } - else - { - emitcode ("jz", "%05d$", tlbl->key + 100); - emitcode ("mov", "a,%s", one); - emitcode ("", "%05d$:", tlbl->key + 100); - outAcc (result); - } -} - -/*-----------------------------------------------------------------*/ -/* genPlusBits - generates code for addition of two bits */ -/*-----------------------------------------------------------------*/ -static void -genPlusBits (iCode * ic) -{ - D (emitcode (";", "genPlusBits "); - ); - if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) - { - symbol *lbl = newiTempLabel (NULL); - emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir); - emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100)); - emitcode ("cpl", "c"); - emitcode ("", "%05d$:", (lbl->key + 100)); - outBitC (IC_RESULT (ic)); - } - else - { - emitcode ("clr", "a"); - emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir); - emitcode ("rlc", "a"); - emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir); - emitcode ("addc", "a,#0x00"); - outAcc (IC_RESULT (ic)); - } -} - -static void -adjustArithmeticResult (iCode * ic) -{ - if (opIsGptr (IC_RESULT (ic)) && - opIsGptr (IC_LEFT (ic)) && - !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic)))) - { - aopPut (AOP (IC_RESULT (ic)), - aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE), - GPTRSIZE - 1); - } - - if (opIsGptr (IC_RESULT (ic)) && - opIsGptr (IC_RIGHT (ic)) && - !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) - { - aopPut (AOP (IC_RESULT (ic)), - aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, FALSE), - GPTRSIZE - 1); - } - - if (opIsGptr (IC_RESULT (ic)) && - AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE && - AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE && - !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) && - !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic)))) - { - char buffer[5]; - sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic))))); - aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1); - } -} - -#if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors. - // Please don't bring it back without a really good reason. -// Macro to aopOp all three operands of an ic. Will fatal if this cannot be done -// (because all three operands are in far space). -#define AOP_OP_3(ic) \ - aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \ - aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \ - aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \ - (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \ - if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \ - AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \ - { \ - /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \ - fprintf(stderr, \ - "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \ - } -#endif - -// Macro to aopOp all three operands of an ic. If this cannot be done, -// the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter -// will be set TRUE. The caller must then handle the case specially, noting -// that the IC_RESULT operand is not aopOp'd. -#define AOP_OP_3_NOFATAL(ic, rc) \ - aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \ - aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR) || \ - (OP_SYMBOL(IC_RESULT(ic))->ruonly)); \ - if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \ - (isOperandInFarSpace(IC_RESULT(ic)) || OP_SYMBOL(IC_RESULT(ic))->ruonly )) \ - { \ - /* No can do; DPTR & DPTR2 in use, and we need another. */ \ - rc = TRUE; \ - } \ - else \ - { \ - aopOp (IC_RESULT(ic),ic,TRUE, (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) || \ - (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); \ - rc = FALSE; \ - if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR2 && \ - AOP_TYPE(IC_RESULT(ic)) == AOP_DPTR2) \ - { \ - /* werror(E_INTERNAL_ERROR,__FILE__,__LINE__, */ \ - fprintf(stderr, \ - "Ack: got unexpected DP2! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno); \ - } \ - } - -// aopOp the left & right operands of an ic. -#define AOP_OP_2(ic) \ - aopOp (IC_RIGHT(ic),ic,FALSE, FALSE); \ - aopOp (IC_LEFT(ic),ic,FALSE, (AOP_TYPE(IC_RIGHT(ic)) == AOP_DPTR)); - -// convienience macro. -#define AOP_SET_LOCALS(ic) \ - left = IC_LEFT(ic); \ - right = IC_RIGHT(ic); \ - result = IC_RESULT(ic); - - -// Given an integer value of pushedSize bytes on the stack, -// adjust it to be resultSize bytes, either by discarding -// the most significant bytes or by zero-padding. -// -// On exit from this macro, pushedSize will have been adjusted to -// equal resultSize, and ACC may be trashed. -#define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \ - /* If the pushed data is bigger than the result, \ - * simply discard unused bytes. Icky, but works. \ - */ \ - while (pushedSize > resultSize) \ - { \ - D (emitcode (";", "discarding unused result byte."););\ - emitcode ("pop", "acc"); \ - pushedSize--; \ - } \ - if (pushedSize < resultSize) \ - { \ - emitcode ("clr", "a"); \ - /* Conversly, we haven't pushed enough here. \ - * just zero-pad, and all is well. \ - */ \ - while (pushedSize < resultSize) \ - { \ - emitcode("push", "acc"); \ - pushedSize++; \ - } \ - } \ - assert(pushedSize == resultSize); - -/*-----------------------------------------------------------------*/ -/* genPlus - generates code for addition */ -/*-----------------------------------------------------------------*/ -static void -genPlus (iCode * ic) -{ - int size, offset = 0; - bool pushResult = FALSE; - int rSize; - - D (emitcode (";", "genPlus ");); - - /* special cases :- */ - if (isOperandEqual(IC_LEFT(ic),IC_RESULT(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); - if (size <= 9) { - while (size--) emitcode ("inc","dptr"); - } else { - emitcode ("mov","a,dpl"); - emitcode ("add","a,#0x%02x",size & 0xff); - emitcode ("mov","dpl,a"); - emitcode ("mov","a,dph"); - emitcode ("addc","a,#0x%02x",(size >> 8) & 0xff); - emitcode ("mov","dph,a"); - emitcode ("mov","a,dpx"); - emitcode ("addc","a,#0x%02x",(size >> 16) & 0xff); - emitcode ("mov","dpx,a"); - } - freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE); - return ; - } - if ( IS_SYMOP(IC_LEFT(ic)) && - OP_SYMBOL(IC_LEFT(ic))->remat && - isOperandInFarSpace(IC_RIGHT(ic))) { - operand *op = IC_RIGHT(ic); - IC_RIGHT(ic) = IC_LEFT(ic); - IC_LEFT(ic) = op; - } - - AOP_OP_3_NOFATAL (ic, pushResult); - if (pushResult) - { - D (emitcode (";", "genPlus: must push result: 3 ops in far space");); - } - - if (!pushResult) - { - /* if literal, literal on the right or - if left requires ACC or right is already - in ACC */ - if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) - || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic)))) - || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC) - { - operand *t = IC_RIGHT (ic); - IC_RIGHT (ic) = IC_LEFT (ic); - IC_LEFT (ic) = t; - emitcode (";", "Swapped plus args."); - } - - /* if both left & right are in bit - space */ - if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY && - AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY) - { - genPlusBits (ic); - goto release; - } - - /* if left in bit space & right literal */ - if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY && - AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT) - { - emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir); - /* if result in bit space */ - if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) - { - if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L) - emitcode ("cpl", "c"); - outBitC (IC_RESULT (ic)); - } - else - { - size = getDataSize (IC_RESULT (ic)); - _startLazyDPSEvaluation (); - while (size--) - { - MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE)); - emitcode ("addc", "a,#00"); - aopPut (AOP (IC_RESULT (ic)), "a", offset++); - } - _endLazyDPSEvaluation (); - } - goto release; - } - - /* if I can do an increment instead - of add then GOOD for ME */ - if (genPlusIncr (ic) == TRUE) - { - emitcode (";", "did genPlusIncr"); - goto release; - } - - } - size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic)); - - _startLazyDPSEvaluation (); - while (size--) - { - if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic))) - { - MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE)); - if (offset == 0) - emitcode ("add", "a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE)); - else - emitcode ("addc", "a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE)); - } - else - { - if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0)) - { - /* right is going to use ACC or we would have taken the - * above branch. - */ - assert(AOP_NEEDSACC(IC_RIGHT(ic))); - TR_AP("#3"); - D(emitcode(";", "+ AOP_ACC special case.");); - emitcode("xch", "a, %s", DP2_RESULT_REG); - } - MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, TRUE)); - if (offset == 0) - { - if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) - { - TR_AP("#4"); - emitcode("add", "a, %s", DP2_RESULT_REG); - } - else - { - emitcode ("add", "a,%s", - aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE, FALSE)); - } - } - else - { - emitcode ("addc", "a,%s", - aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, FALSE)); - } - } - if (!pushResult) - { - aopPut (AOP (IC_RESULT (ic)), "a", offset); - } - else - { - emitcode ("push", "acc"); - } - offset++; - } - _endLazyDPSEvaluation (); - - if (pushResult) - { - aopOp (IC_RESULT (ic), ic, TRUE, FALSE); - - size = getDataSize (IC_LEFT (ic)); - rSize = getDataSize (IC_RESULT (ic)); - - ADJUST_PUSHED_RESULT(size, rSize); - - _startLazyDPSEvaluation (); - while (size--) - { - emitcode ("pop", "acc"); - aopPut (AOP (IC_RESULT (ic)), "a", size); - } - _endLazyDPSEvaluation (); - } - - adjustArithmeticResult (ic); - -release: - freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genMinusDec :- does subtraction with deccrement if possible */ -/*-----------------------------------------------------------------*/ -static bool -genMinusDec (iCode * ic) -{ - unsigned int icount; - unsigned int size = getDataSize (IC_RESULT (ic)); - - /* will try to generate an increment */ - /* if the right side is not a literal - we cannot */ - if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) - return FALSE; - - /* if the literal value of the right hand side - is greater than 4 then it is not worth it */ - if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4) - return FALSE; - - /* if decrement 16 bits in register */ - if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG && - AOP_TYPE (IC_RESULT (ic)) == AOP_REG && - sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) && - (size > 1) && - (icount == 1)) - { - symbol *tlbl; - int emitTlbl; - int labelRange; - - /* If the next instruction is a goto and the goto target - * is <= 5 instructions previous to this, we can generate - * jumps straight to that target. - */ - if (ic->next && ic->next->op == GOTO - && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0 - && labelRange <= 5) - { - emitcode (";", "tail decrement optimized (range %d)", labelRange); - tlbl = IC_LABEL (ic->next); - emitTlbl = 0; - } - else - { - tlbl = newiTempLabel (NULL); - emitTlbl = 1; - } - - emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE)); - if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG || - AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR || - IS_AOP_PREG (IC_RESULT (ic))) - emitcode ("cjne", "%s,#0xff,%05d$" - ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE) - ,tlbl->key + 100); - else - { - emitcode ("mov", "a,#0xff"); - emitcode ("cjne", "a,%s,%05d$" - ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, FALSE) - ,tlbl->key + 100); - } - emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE)); - if (size > 2) - { - if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG || - AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR || - IS_AOP_PREG (IC_RESULT (ic))) - emitcode ("cjne", "%s,#0xff,%05d$" - ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE) - ,tlbl->key + 100); - else - { - emitcode ("cjne", "a,%s,%05d$" - ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, FALSE) - ,tlbl->key + 100); - } - emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE)); - } - if (size > 3) - { - if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG || - AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR || - IS_AOP_PREG (IC_RESULT (ic))) - emitcode ("cjne", "%s,#0xff,%05d$" - ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE) - ,tlbl->key + 100); - else - { - emitcode ("cjne", "a,%s,%05d$" - ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, FALSE) - ,tlbl->key + 100); - } - emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, FALSE)); - } - if (emitTlbl) - { - emitcode ("", "%05d$:", tlbl->key + 100); - } - return TRUE; - } - - /* if the sizes are greater than 1 then we cannot */ - if (AOP_SIZE (IC_RESULT (ic)) > 1 || - AOP_SIZE (IC_LEFT (ic)) > 1) - return FALSE; - - /* we can if the aops of the left & result match or - if they are in registers and the registers are the - same */ - if ( - AOP_TYPE (IC_LEFT (ic)) == AOP_REG && - AOP_TYPE (IC_RESULT (ic)) == AOP_REG && - sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic)))) - { - - _startLazyDPSEvaluation (); - while (icount--) - { - emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE)); - } - _endLazyDPSEvaluation (); - - return TRUE; - } - - return FALSE; -} - -/*-----------------------------------------------------------------*/ -/* addSign - complete with sign */ -/*-----------------------------------------------------------------*/ -static void -addSign (operand * result, int offset, int sign) -{ - int size = (getDataSize (result) - offset); - if (size > 0) - { - _startLazyDPSEvaluation(); - if (sign) - { - emitcode ("rlc", "a"); - emitcode ("subb", "a,acc"); - while (size--) - { - aopPut (AOP (result), "a", offset++); - } - } - else - { - while (size--) - { - aopPut (AOP (result), zero, offset++); - } - } - _endLazyDPSEvaluation(); - } -} - -/*-----------------------------------------------------------------*/ -/* genMinusBits - generates code for subtraction of two bits */ -/*-----------------------------------------------------------------*/ -static void -genMinusBits (iCode * ic) -{ - symbol *lbl = newiTempLabel (NULL); - - D (emitcode (";", "genMinusBits ");); - - if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) - { - emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir); - emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100)); - emitcode ("cpl", "c"); - emitcode ("", "%05d$:", (lbl->key + 100)); - outBitC (IC_RESULT (ic)); - } - else - { - emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir); - emitcode ("subb", "a,acc"); - emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100)); - emitcode ("inc", "a"); - emitcode ("", "%05d$:", (lbl->key + 100)); - aopPut (AOP (IC_RESULT (ic)), "a", 0); - addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic))))); - } -} - -/*-----------------------------------------------------------------*/ -/* genMinus - generates code for subtraction */ -/*-----------------------------------------------------------------*/ -static void -genMinus (iCode * ic) -{ - int size, offset = 0; - int rSize; - unsigned long lit = 0L; - bool pushResult = FALSE; - - D (emitcode (";", "genMinus ");); - - aopOp (IC_LEFT (ic), ic, FALSE, FALSE); - aopOp (IC_RIGHT (ic), ic, FALSE, TRUE); - if ((AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR) && - (AOP_TYPE (IC_RIGHT (ic)) == AOP_DPTR2)) - { - pushResult = TRUE; - } - else - { - aopOp (IC_RESULT (ic), ic, TRUE, AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR); - - /* special cases :- */ - /* if both left & right are in bit space */ - if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY && - AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY) - { - genMinusBits (ic); - goto release; - } - - /* if I can do an decrement instead - of subtract then GOOD for ME */ - if (genMinusDec (ic) == TRUE) - goto release; - - } - - size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic)); - - if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) - { - CLRC; - } - else - { - lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); - lit = -(long) lit; - } - - - /* if literal, add a,#-lit, else normal subb */ - _startLazyDPSEvaluation (); - while (size--) - { - MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, TRUE)); - if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) - emitcode ("subb", "a,%s", - aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, FALSE)); - else - { - /* first add without previous c */ - 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)); - } - } - - if (pushResult) - { - emitcode ("push", "acc"); - } - else - { - aopPut (AOP (IC_RESULT (ic)), "a", offset); - } - offset++; - } - _endLazyDPSEvaluation (); - - if (pushResult) - { - aopOp (IC_RESULT (ic), ic, TRUE, FALSE); - - size = getDataSize (IC_LEFT (ic)); - rSize = getDataSize (IC_RESULT (ic)); - - ADJUST_PUSHED_RESULT(size, rSize); - - _startLazyDPSEvaluation (); - while (size--) - { - emitcode ("pop", "acc"); - aopPut (AOP (IC_RESULT (ic)), "a", size); - } - _endLazyDPSEvaluation (); - } - - adjustArithmeticResult (ic); - -release: - freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); -} - - -/*-----------------------------------------------------------------*/ -/* genMultbits :- multiplication of bits */ -/*-----------------------------------------------------------------*/ -static void -genMultbits (operand * left, - operand * right, - operand * result, - iCode * ic) -{ - emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir); - emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir); - aopOp(result, ic, TRUE, FALSE); - outBitC (result); -} - - -/*-----------------------------------------------------------------*/ -/* genMultOneByte : 8*8=8/16 bit multiplication */ -/*-----------------------------------------------------------------*/ -static void -genMultOneByte (operand * left, - operand * right, - operand * result, - iCode * ic) -{ - sym_link *opetype = operandType (result); - symbol *lbl; - - - /* (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, TRUE)); - MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE)); - emitcode ("mul", "ab"); - - _G.accInUse++; - 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--; - if (AOP_SIZE(result)==2) - { - aopPut (AOP (result), "b", 1); - } - return; - } - - // we have to do a signed multiply - - emitcode (";", "signed"); - emitcode ("clr", "F0"); // reset sign flag - MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE)); - - 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"); - - 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 ((int) 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, TRUE)); - 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"); - - _G.accInUse++; - 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,%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 (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 ("", "%05d$:", lbl->key+100); - aopPut (AOP (result), "a", 0); - _G.accInUse--; - if (AOP_SIZE(result)==2) { - aopPut (AOP (result), "b", 1); - } -} - -/*-----------------------------------------------------------------*/ -/* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */ -/*-----------------------------------------------------------------*/ -static void genMultTwoByte (operand *left, operand *right, - operand *result, iCode *ic) -{ - sym_link *retype = getSpec(operandType(right)); - sym_link *letype = getSpec(operandType(left)); - int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype); - symbol *lbl; - - if (AOP_TYPE (left) == AOP_LIT) { - operand *t = right; - right = left; - left = t; - } - /* save EA bit in F1 */ - lbl = newiTempLabel(NULL); - emitcode ("setb","F1"); - emitcode ("jbc","EA,%05d$",lbl->key+100); - emitcode ("clr","F1"); - emitcode("","%05d$:",lbl->key+100); - - /* load up MB with right */ - if (!umult) { - emitcode("clr","F0"); - if (AOP_TYPE(right) == AOP_LIT) { - int val=floatFromVal (AOP (right)->aopu.aop_lit); - if (val < 0) { - emitcode("setb","F0"); - val = -val; - } - emitcode ("mov","mb,#0x%02x",val & 0xff); - emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff); - } else { - lbl = newiTempLabel(NULL); - emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE)); - emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE)); - emitcode ("jnb","acc.7,%05d$",lbl->key+100); - emitcode ("xch", "a,b"); - emitcode ("cpl","a"); - emitcode ("add", "a,#1"); - emitcode ("xch", "a,b"); - emitcode ("cpl", "a"); // msb - emitcode ("addc", "a,#0"); - emitcode ("setb","F0"); - emitcode ("","%05d$:",lbl->key+100); - emitcode ("mov","mb,b"); - emitcode ("mov","mb,a"); - } - } else { - emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE)); - emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE)); - } - /* load up MA with left */ - if (!umult) { - lbl = newiTempLabel(NULL); - emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE)); - emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE)); - emitcode ("jnb","acc.7,%05d$",lbl->key+100); - emitcode ("xch", "a,b"); - emitcode ("cpl","a"); - emitcode ("add", "a,#1"); - emitcode ("xch", "a,b"); - emitcode ("cpl", "a"); // msb - emitcode ("addc","a,#0"); - emitcode ("jbc","F0,%05d$",lbl->key+100); - emitcode ("setb","F0"); - emitcode ("","%05d$:",lbl->key+100); - emitcode ("mov","ma,b"); - emitcode ("mov","ma,a"); - } else { - emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE)); - emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE)); - } - /* wait for multiplication to finish */ - lbl = newiTempLabel(NULL); - emitcode("","%05d$:", lbl->key+100); - emitcode("mov","a,mcnt1"); - emitcode("anl","a,#0x80"); - emitcode("jnz","%05d$",lbl->key+100); - - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (right, NULL, ic,TRUE); - aopOp(result, ic, TRUE, FALSE); - - /* if unsigned then simple */ - if (umult) { - emitcode ("mov","a,ma"); - if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3); - emitcode ("mov","a,ma"); - if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2); - aopPut(AOP(result),"ma",1); - aopPut(AOP(result),"ma",0); - } else { - emitcode("push","ma"); - emitcode("push","ma"); - emitcode("push","ma"); - MOVA("ma"); - /* negate result if needed */ - lbl = newiTempLabel(NULL); - emitcode("jnb","F0,%05d$",lbl->key+100); - emitcode("cpl","a"); - emitcode("add","a,#1"); - emitcode("","%05d$:", lbl->key+100); - if (AOP_TYPE(result) == AOP_ACC) - { - D(emitcode(";", "ACC special case.");); - /* We know result is the only live aop, and - * it's obviously not a DPTR2, so AP is available. - */ - emitcode("mov", "%s,acc", DP2_RESULT_REG); - } - else - { - aopPut(AOP(result),"a",0); - } - - emitcode("pop","acc"); - lbl = newiTempLabel(NULL); - emitcode("jnb","F0,%05d$",lbl->key+100); - emitcode("cpl","a"); - emitcode("addc","a,#0"); - emitcode("","%05d$:", lbl->key+100); - aopPut(AOP(result),"a",1); - emitcode("pop","acc"); - if (AOP_SIZE(result) >= 3) { - lbl = newiTempLabel(NULL); - emitcode("jnb","F0,%05d$",lbl->key+100); - emitcode("cpl","a"); - emitcode("addc","a,#0"); - emitcode("","%05d$:", lbl->key+100); - aopPut(AOP(result),"a",2); - } - emitcode("pop","acc"); - if (AOP_SIZE(result) >= 4) { - lbl = newiTempLabel(NULL); - emitcode("jnb","F0,%05d$",lbl->key+100); - emitcode("cpl","a"); - emitcode("addc","a,#0"); - emitcode("","%05d$:", lbl->key+100); - aopPut(AOP(result),"a",3); - } - if (AOP_TYPE(result) == AOP_ACC) - { - /* We stashed the result away above. */ - emitcode("mov", "acc,%s", DP2_RESULT_REG); - } - - } - freeAsmop (result, NULL, ic, TRUE); - - /* restore EA bit in F1 */ - lbl = newiTempLabel(NULL); - emitcode ("jnb","F1,%05d$",lbl->key+100); - emitcode ("setb","EA"); - emitcode("","%05d$:",lbl->key+100); - return ; -} - -/*-----------------------------------------------------------------*/ -/* genMult - generates code for multiplication */ -/*-----------------------------------------------------------------*/ -static void -genMult (iCode * ic) -{ - operand *left = IC_LEFT (ic); - operand *right = IC_RIGHT (ic); - operand *result = IC_RESULT (ic); - - D (emitcode (";", "genMult ");); - - /* assign the amsops */ - AOP_OP_2 (ic); - - /* special cases first */ - /* both are bits */ - if (AOP_TYPE (left) == AOP_CRY && - AOP_TYPE (right) == AOP_CRY) - { - genMultbits (left, right, result, ic); - goto release; - } - - /* if both are of size == 1 */ - if (AOP_SIZE (left) == 1 && - AOP_SIZE (right) == 1) - { - genMultOneByte (left, right, result, ic); - goto release; - } - - if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) { - /* use the ds390 ARITHMETIC accel UNIT */ - genMultTwoByte (left, right, result, ic); - return ; - } - /* should have been converted to function call */ - assert (0); - -release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genDivbits :- division of bits */ -/*-----------------------------------------------------------------*/ -static void -genDivbits (operand * left, - operand * right, - operand * result, - iCode * ic) -{ - - char *l; - - /* the result must be bit */ - LOAD_AB_FOR_DIV (left, right, l); - emitcode ("div", "ab"); - emitcode ("rrc", "a"); - aopOp(result, ic, TRUE, FALSE); - - aopPut (AOP (result), "c", 0); -} - -/*-----------------------------------------------------------------*/ -/* genDivOneByte : 8 bit division */ -/*-----------------------------------------------------------------*/ -static void -genDivOneByte (operand * left, - operand * right, - operand * result, - iCode * ic) -{ - sym_link *opetype = operandType (result); - char *l; - symbol *lbl; - int size, offset; - - offset = 1; - /* signed or unsigned */ - if (SPEC_USIGN (opetype)) - { - /* 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--; - - 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 */ - l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE); - MOVA (l); - 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 */ - l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE); - MOVA (l); - lbl = newiTempLabel (NULL); - emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); - emitcode ("cpl", "a"); - emitcode ("inc", "a"); - emitcode ("", "%05d$:", (lbl->key + 100)); - emitcode ("mov", "b,a"); - - /* sign adjust left side */ - l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE); - MOVA (l); - - lbl = newiTempLabel (NULL); - emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); - emitcode ("cpl", "a"); - emitcode ("inc", "a"); - emitcode ("", "%05d$:", (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,%05d$", (lbl->key + 100)); - emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); - CLRC; - emitcode ("clr", "a"); - emitcode ("subb", "a,b"); - emitcode ("mov", "b,a"); - emitcode ("", "%05d$:", (lbl->key + 100)); - - /* now we are done */ - _G.accInUse++; - aopOp(result, ic, TRUE, FALSE); - - aopPut (AOP (result), "b", 0); - - size = AOP_SIZE (result) - 1; - - if (size > 0) - { - emitcode ("mov", "c,b.7"); - emitcode ("subb", "a,acc"); - } - while (size--) - { - aopPut (AOP (result), "a", offset++); - } - _G.accInUse--; - -} - -/*-----------------------------------------------------------------*/ -/* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */ -/*-----------------------------------------------------------------*/ -static void genDivTwoByte (operand *left, operand *right, - operand *result, iCode *ic) -{ - sym_link *retype = getSpec(operandType(right)); - sym_link *letype = getSpec(operandType(left)); - int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype); - symbol *lbl; - - /* save EA bit in F1 */ - lbl = newiTempLabel(NULL); - emitcode ("setb","F1"); - emitcode ("jbc","EA,%05d$",lbl->key+100); - emitcode ("clr","F1"); - emitcode("","%05d$:",lbl->key+100); - - /* load up MA with left */ - if (!umult) { - emitcode("clr","F0"); - lbl = newiTempLabel(NULL); - emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE)); - emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE)); - emitcode ("jnb","acc.7,%05d$",lbl->key+100); - emitcode ("xch", "a,b"); - emitcode ("cpl","a"); - emitcode ("add", "a,#1"); - emitcode ("xch", "a,b"); - emitcode ("cpl", "a"); // msb - emitcode ("addc","a,#0"); - emitcode ("setb","F0"); - emitcode ("","%05d$:",lbl->key+100); - emitcode ("mov","ma,b"); - emitcode ("mov","ma,a"); - } else { - emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE)); - emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE)); - } - - /* load up MB with right */ - if (!umult) { - if (AOP_TYPE(right) == AOP_LIT) { - int val=floatFromVal (AOP (right)->aopu.aop_lit); - if (val < 0) { - lbl = newiTempLabel(NULL); - emitcode ("jbc","F0,%05d$",lbl->key+100); - emitcode("setb","F0"); - emitcode ("","%05d$:",lbl->key+100); - val = -val; - } - emitcode ("mov","mb,#0x%02x",val & 0xff); - emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff); - } else { - lbl = newiTempLabel(NULL); - emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE)); - emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE)); - emitcode ("jnb","acc.7,%05d$",lbl->key+100); - emitcode ("xch", "a,b"); - emitcode ("cpl","a"); - emitcode ("add", "a,#1"); - emitcode ("xch", "a,b"); - emitcode ("cpl", "a"); // msb - emitcode ("addc", "a,#0"); - emitcode ("jbc","F0,%05d$",lbl->key+100); - emitcode ("setb","F0"); - emitcode ("","%05d$:",lbl->key+100); - emitcode ("mov","mb,b"); - emitcode ("mov","mb,a"); - } - } else { - emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE)); - emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE)); - } - - /* wait for multiplication to finish */ - lbl = newiTempLabel(NULL); - emitcode("","%05d$:", lbl->key+100); - emitcode("mov","a,mcnt1"); - emitcode("anl","a,#0x80"); - emitcode("jnz","%05d$",lbl->key+100); - - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (right, NULL, ic,TRUE); - aopOp(result, ic, TRUE, FALSE); - - /* if unsigned then simple */ - if (umult) { - aopPut(AOP(result),"ma",1); - aopPut(AOP(result),"ma",0); - } else { - emitcode("push","ma"); - MOVA("ma"); - /* negate result if needed */ - lbl = newiTempLabel(NULL); - emitcode("jnb","F0,%05d$",lbl->key+100); - emitcode("cpl","a"); - emitcode("add","a,#1"); - emitcode("","%05d$:", lbl->key+100); - aopPut(AOP(result),"a",0); - emitcode("pop","acc"); - lbl = newiTempLabel(NULL); - emitcode("jnb","F0,%05d$",lbl->key+100); - emitcode("cpl","a"); - emitcode("addc","a,#0"); - emitcode("","%05d$:", lbl->key+100); - aopPut(AOP(result),"a",1); - } - freeAsmop (result, NULL, ic, TRUE); - /* restore EA bit in F1 */ - lbl = newiTempLabel(NULL); - emitcode ("jnb","F1,%05d$",lbl->key+100); - emitcode ("setb","EA"); - emitcode("","%05d$:",lbl->key+100); - return ; -} - -/*-----------------------------------------------------------------*/ -/* genDiv - generates code for division */ -/*-----------------------------------------------------------------*/ -static void -genDiv (iCode * ic) -{ - operand *left = IC_LEFT (ic); - operand *right = IC_RIGHT (ic); - operand *result = IC_RESULT (ic); - - D (emitcode (";", "genDiv ");); - - /* assign the amsops */ - AOP_OP_2 (ic); - - /* special cases first */ - /* both are bits */ - if (AOP_TYPE (left) == AOP_CRY && - AOP_TYPE (right) == AOP_CRY) - { - genDivbits (left, right, result, ic); - goto release; - } - - /* if both are of size == 1 */ - if (AOP_SIZE (left) == 1 && - AOP_SIZE (right) == 1) - { - genDivOneByte (left, right, result, ic); - goto release; - } - - if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) { - /* use the ds390 ARITHMETIC accel UNIT */ - genDivTwoByte (left, right, result, ic); - return ; - } - /* should have been converted to function call */ - assert (0); -release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genModbits :- modulus of bits */ -/*-----------------------------------------------------------------*/ -static void -genModbits (operand * left, - operand * right, - operand * result, - iCode * ic) -{ - - char *l; - - /* the result must be bit */ - LOAD_AB_FOR_DIV (left, right, l); - emitcode ("div", "ab"); - emitcode ("mov", "a,b"); - emitcode ("rrc", "a"); - aopOp(result, ic, TRUE, FALSE); - aopPut (AOP (result), "c", 0); -} - -/*-----------------------------------------------------------------*/ -/* genModOneByte : 8 bit modulus */ -/*-----------------------------------------------------------------*/ -static void -genModOneByte (operand * left, - operand * right, - operand * result, - iCode * ic) -{ - sym_link *opetype = operandType (result); - char *l; - symbol *lbl; - - /* signed or unsigned */ - if (SPEC_USIGN (opetype)) - { - /* unsigned is easy */ - LOAD_AB_FOR_DIV (left, right, l); - emitcode ("div", "ab"); - aopOp(result, ic, TRUE, FALSE); - aopPut (AOP (result), "b", 0); - return; - } - - /* signed is a little bit more difficult */ - - /* save the signs of the operands */ - l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE); - MOVA (l); - - 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 */ - l = aopGet (AOP (right), 0, FALSE, FALSE, TRUE); - MOVA (l); - - lbl = newiTempLabel (NULL); - emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); - emitcode ("cpl", "a"); - emitcode ("inc", "a"); - emitcode ("", "%05d$:", (lbl->key + 100)); - emitcode ("mov", "b,a"); - - /* sign adjust left side */ - l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE); - MOVA (l); - - lbl = newiTempLabel (NULL); - emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); - emitcode ("cpl", "a"); - emitcode ("inc", "a"); - emitcode ("", "%05d$:", (lbl->key + 100)); - - /* now the multiplication */ - 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,%05d$", (lbl->key + 100)); - emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100)); - CLRC; - emitcode ("clr", "a"); - emitcode ("subb", "a,b"); - emitcode ("mov", "b,a"); - emitcode ("", "%05d$:", (lbl->key + 100)); - - /* now we are done */ - aopOp(result, ic, TRUE, FALSE); - aopPut (AOP (result), "b", 0); - -} - -/*-----------------------------------------------------------------*/ -/* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */ -/*-----------------------------------------------------------------*/ -static void genModTwoByte (operand *left, operand *right, - operand *result, iCode *ic) -{ - sym_link *retype = getSpec(operandType(right)); - sym_link *letype = getSpec(operandType(left)); - int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype); - symbol *lbl; - - /* load up MA with left */ - /* save EA bit in F1 */ - lbl = newiTempLabel(NULL); - emitcode ("setb","F1"); - emitcode ("jbc","EA,%05d$",lbl->key+100); - emitcode ("clr","F1"); - emitcode("","%05d$:",lbl->key+100); - - if (!umult) { - lbl = newiTempLabel(NULL); - emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE)); - emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE)); - emitcode ("jnb","acc.7,%05d$",lbl->key+100); - emitcode ("xch", "a,b"); - emitcode ("cpl","a"); - emitcode ("add", "a,#1"); - emitcode ("xch", "a,b"); - emitcode ("cpl", "a"); // msb - emitcode ("addc","a,#0"); - emitcode ("","%05d$:",lbl->key+100); - emitcode ("mov","ma,b"); - emitcode ("mov","ma,a"); - } else { - emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE)); - emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE)); - } - - /* load up MB with right */ - if (!umult) { - if (AOP_TYPE(right) == AOP_LIT) { - int val=floatFromVal (AOP (right)->aopu.aop_lit); - if (val < 0) { - val = -val; - } - emitcode ("mov","mb,#0x%02x",val & 0xff); - emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff); - } else { - lbl = newiTempLabel(NULL); - emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE)); - emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE)); - emitcode ("jnb","acc.7,%05d$",lbl->key+100); - emitcode ("xch", "a,b"); - emitcode ("cpl","a"); - emitcode ("add", "a,#1"); - emitcode ("xch", "a,b"); - emitcode ("cpl", "a"); // msb - emitcode ("addc", "a,#0"); - emitcode ("","%05d$:",lbl->key+100); - emitcode ("mov","mb,b"); - emitcode ("mov","mb,a"); - } - } else { - emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE)); - emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE)); - } - - /* wait for multiplication to finish */ - lbl = newiTempLabel(NULL); - emitcode("","%05d$:", lbl->key+100); - emitcode("mov","a,mcnt1"); - emitcode("anl","a,#0x80"); - emitcode("jnz","%05d$",lbl->key+100); - - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (right, NULL, ic,TRUE); - aopOp(result, ic, TRUE, FALSE); - - aopPut(AOP(result),"mb",1); - aopPut(AOP(result),"mb",0); - freeAsmop (result, NULL, ic, TRUE); - - /* restore EA bit in F1 */ - lbl = newiTempLabel(NULL); - emitcode ("jnb","F1,%05d$",lbl->key+100); - emitcode ("setb","EA"); - emitcode("","%05d$:",lbl->key+100); - return ; -} - -/*-----------------------------------------------------------------*/ -/* genMod - generates code for division */ -/*-----------------------------------------------------------------*/ -static void -genMod (iCode * ic) -{ - operand *left = IC_LEFT (ic); - operand *right = IC_RIGHT (ic); - operand *result = IC_RESULT (ic); - - D (emitcode (";", "genMod "); ); - - /* assign the amsops */ - AOP_OP_2 (ic); - - /* special cases first */ - /* both are bits */ - if (AOP_TYPE (left) == AOP_CRY && - AOP_TYPE (right) == AOP_CRY) - { - genModbits (left, right, result, ic); - goto release; - } - - /* if both are of size == 1 */ - if (AOP_SIZE (left) == 1 && - AOP_SIZE (right) == 1) - { - genModOneByte (left, right, result, ic); - goto release; - } - - if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) { - /* use the ds390 ARITHMETIC accel UNIT */ - genModTwoByte (left, right, result, ic); - return ; - } - - /* should have been converted to function call */ - assert (0); - -release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genIfxJump :- will create a jump depending on the ifx */ -/*-----------------------------------------------------------------*/ -static void -genIfxJump (iCode * ic, char *jval) -{ - symbol *jlbl; - symbol *tlbl = newiTempLabel (NULL); - char *inst; - - D (emitcode (";", "genIfxJump "); - ); - - /* if true label then we jump if condition - supplied is true */ - if (IC_TRUE (ic)) - { - jlbl = IC_TRUE (ic); - inst = ((strcmp (jval, "a") == 0 ? "jz" : - (strcmp (jval, "c") == 0 ? "jnc" : "jnb"))); - } - else - { - /* false label is present */ - jlbl = IC_FALSE (ic); - inst = ((strcmp (jval, "a") == 0 ? "jnz" : - (strcmp (jval, "c") == 0 ? "jc" : "jb"))); - } - if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0) - emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100)); - else - emitcode (inst, "%05d$", tlbl->key + 100); - emitcode ("ljmp", "%05d$", jlbl->key + 100); - emitcode ("", "%05d$:", tlbl->key + 100); - - /* mark the icode as generated */ - ic->generated = 1; -} - -/*-----------------------------------------------------------------*/ -/* genCmp :- greater or less than comparison */ -/*-----------------------------------------------------------------*/ -static void -genCmp (operand * left, operand * right, - iCode * ic, iCode * ifx, int sign) -{ - int size, offset = 0; - unsigned long lit = 0L; - operand *result; - - D (emitcode (";", "genCmp"); - ); - - result = IC_RESULT (ic); - - /* if left & right are bit variables */ - if (AOP_TYPE (left) == AOP_CRY && - AOP_TYPE (right) == AOP_CRY) - { - emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir); - emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir); - } - else - { - /* subtract right from left if at the - end the carry flag is set then we know that - left is greater than right */ - size = max (AOP_SIZE (left), AOP_SIZE (right)); - - /* if unsigned char cmp with lit, do cjne left,#right,zz */ - if ((size == 1) && !sign && - (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR)) - { - symbol *lbl = newiTempLabel (NULL); - emitcode ("cjne", "%s,%s,%05d$", - aopGet (AOP (left), offset, FALSE, FALSE, FALSE), - aopGet (AOP (right), offset, FALSE, FALSE, FALSE), - lbl->key + 100); - emitcode ("", "%05d$:", lbl->key + 100); - } - else - { - if (AOP_TYPE (right) == AOP_LIT) - { - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); - /* optimize if(x < 0) or if(x >= 0) */ - if (lit == 0L) - { - if (!sign) - { - CLRC; - } - else - { - MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE)); - - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - - aopOp (result, ic, FALSE, FALSE); - - if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx) - { - freeAsmop (result, NULL, ic, TRUE); - genIfxJump (ifx, "acc.7"); - return; - } - else - { - emitcode ("rlc", "a"); - } - goto release_freedLR; - } - goto release; - } - } - CLRC; - while (size--) - { - emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset); - MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE)); - emitcode (";", "genCmp #2"); - if (sign && (size == 0)) - { - emitcode (";", "genCmp #3"); - emitcode ("xrl", "a,#0x80"); - if (AOP_TYPE (right) == AOP_LIT) - { - unsigned long lit = (unsigned long) - floatFromVal (AOP (right)->aopu.aop_lit); - emitcode (";", "genCmp #3.1"); - emitcode ("subb", "a,#0x%02x", - 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL)); - } - else - { - emitcode (";", "genCmp #3.2"); - if (AOP_NEEDSACC (right)) - { - emitcode ("push", "acc"); - } - emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, - FALSE, FALSE, FALSE)); - emitcode ("xrl", "b,#0x80"); - if (AOP_NEEDSACC (right)) - { - emitcode ("pop", "acc"); - } - emitcode ("subb", "a,b"); - } - } - else - { - const char *s; - - emitcode (";", "genCmp #4"); - if (AOP_NEEDSACC (right)) - { - /* Yuck!! */ - emitcode (";", "genCmp #4.1"); - emitcode ("xch", "a, b"); - MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, TRUE)); - emitcode ("xch", "a, b"); - s = "b"; - } - else - { - emitcode (";", "genCmp #4.2"); - s = aopGet (AOP (right), offset++, FALSE, FALSE, FALSE); - } - - emitcode ("subb", "a,%s", s); - } - } - } - } - -release: -/* Don't need the left & right operands any more; do need the result. */ - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - - aopOp (result, ic, FALSE, FALSE); - -release_freedLR: - - if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) - { - outBitC (result); - } - else - { - /* if the result is used in the next - ifx conditional branch then generate - code a little differently */ - if (ifx) - { - genIfxJump (ifx, "c"); - } - else - { - outBitC (result); - } - /* leave the result in acc */ - } - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genCmpGt :- greater than comparison */ -/*-----------------------------------------------------------------*/ -static void -genCmpGt (iCode * ic, iCode * ifx) -{ - operand *left, *right; - sym_link *letype, *retype; - int sign; - - D (emitcode (";", "genCmpGt "); - ); - - left = IC_LEFT (ic); - right = IC_RIGHT (ic); - - letype = getSpec (operandType (left)); - retype = getSpec (operandType (right)); - sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype)); - - /* assign the left & right amsops */ - AOP_OP_2 (ic); - - genCmp (right, left, ic, ifx, sign); -} - -/*-----------------------------------------------------------------*/ -/* genCmpLt - less than comparisons */ -/*-----------------------------------------------------------------*/ -static void -genCmpLt (iCode * ic, iCode * ifx) -{ - operand *left, *right; - sym_link *letype, *retype; - int sign; - - D (emitcode (";", "genCmpLt ");); - - left = IC_LEFT (ic); - right = IC_RIGHT (ic); - - letype = getSpec (operandType (left)); - retype = getSpec (operandType (right)); - sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype)); - - /* assign the left & right amsops */ - AOP_OP_2 (ic); - - genCmp (left, right, ic, ifx, sign); -} - -/*-----------------------------------------------------------------*/ -/* gencjneshort - compare and jump if not equal */ -/*-----------------------------------------------------------------*/ -static void -gencjneshort (operand * left, operand * right, symbol * lbl) -{ - int size = max (AOP_SIZE (left), AOP_SIZE (right)); - int offset = 0; - unsigned long lit = 0L; - - D (emitcode (";", "gencjneshort"); - ); - - /* if the left side is a literal or - if the right is in a pointer register and left - is not */ - if ((AOP_TYPE (left) == AOP_LIT) || - (IS_AOP_PREG (right) && !IS_AOP_PREG (left))) - { - operand *t = right; - right = left; - left = t; - } - - if (AOP_TYPE (right) == AOP_LIT) - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); - - if (opIsGptr (left) || opIsGptr (right)) - { - /* We are comparing a generic pointer to something. - * Exclude the generic type byte from the comparison. - */ - size--; - D (emitcode (";", "cjneshort: generic ptr special case."); - ) - } - - - /* if the right side is a literal then anything goes */ - if (AOP_TYPE (right) == AOP_LIT && - AOP_TYPE (left) != AOP_DIR) - { - while (size--) - { - char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("cjne", "a,%s,%05d$", - aopGet (AOP (right), offset, FALSE, FALSE, FALSE), - lbl->key + 100); - offset++; - } - } - - /* if the right side is in a register or in direct space or - if the left is a pointer register & right is not */ - else if (AOP_TYPE (right) == AOP_REG || - AOP_TYPE (right) == AOP_DIR || - (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) || - (IS_AOP_PREG (left) && !IS_AOP_PREG (right))) - { - while (size--) - { - MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE)); - if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) && - ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0)) - emitcode ("jnz", "%05d$", lbl->key + 100); - else - emitcode ("cjne", "a,%s,%05d$", - aopGet (AOP (right), offset, FALSE, TRUE, FALSE), - lbl->key + 100); - offset++; - } - } - else - { - /* right is a pointer reg need both a & b */ - while (size--) - { - char *l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE); - if (strcmp (l, "b")) - emitcode ("mov", "b,%s", l); - MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); - emitcode ("cjne", "a,b,%05d$", lbl->key + 100); - offset++; - } - } -} - -/*-----------------------------------------------------------------*/ -/* gencjne - compare and jump if not equal */ -/*-----------------------------------------------------------------*/ -static void -gencjne (operand * left, operand * right, symbol * lbl) -{ - symbol *tlbl = newiTempLabel (NULL); - - D (emitcode (";", "gencjne"); - ); - - gencjneshort (left, right, lbl); - - emitcode ("mov", "a,%s", one); - emitcode ("sjmp", "%05d$", tlbl->key + 100); - emitcode ("", "%05d$:", lbl->key + 100); - emitcode ("clr", "a"); - emitcode ("", "%05d$:", tlbl->key + 100); -} - -/*-----------------------------------------------------------------*/ -/* genCmpEq - generates code for equal to */ -/*-----------------------------------------------------------------*/ -static void -genCmpEq (iCode * ic, iCode * ifx) -{ - operand *left, *right, *result; - - D (emitcode (";", "genCmpEq "); - ); - - AOP_OP_2 (ic); - AOP_SET_LOCALS (ic); - - /* if literal, literal on the right or - if the right is in a pointer register and left - is not */ - if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) || - (IS_AOP_PREG (right) && !IS_AOP_PREG (left))) - { - operand *t = IC_RIGHT (ic); - IC_RIGHT (ic) = IC_LEFT (ic); - IC_LEFT (ic) = t; - } - - if (ifx && /* !AOP_SIZE(result) */ - OP_SYMBOL (result) && - OP_SYMBOL (result)->regType == REG_CND) - { - symbol *tlbl; - /* if they are both bit variables */ - if (AOP_TYPE (left) == AOP_CRY && - ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT))) - { - if (AOP_TYPE (right) == AOP_LIT) - { - unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); - if (lit == 0L) - { - emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir); - emitcode ("cpl", "c"); - } - else if (lit == 1L) - { - emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir); - } - else - { - emitcode ("clr", "c"); - } - /* AOP_TYPE(right) == AOP_CRY */ - } - else - { - symbol *lbl = newiTempLabel (NULL); - emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir); - emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100)); - emitcode ("cpl", "c"); - emitcode ("", "%05d$:", (lbl->key + 100)); - } - /* if true label then we jump if condition - supplied is true */ - tlbl = newiTempLabel (NULL); - if (IC_TRUE (ifx)) - { - emitcode ("jnc", "%05d$", tlbl->key + 100); - emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100); - } - else - { - emitcode ("jc", "%05d$", tlbl->key + 100); - emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100); - } - emitcode ("", "%05d$:", tlbl->key + 100); - } - else - { - tlbl = newiTempLabel (NULL); - gencjneshort (left, right, tlbl); - if (IC_TRUE (ifx)) - { - emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100); - emitcode ("", "%05d$:", tlbl->key + 100); - } - else - { - symbol *lbl = newiTempLabel (NULL); - emitcode ("sjmp", "%05d$", lbl->key + 100); - emitcode ("", "%05d$:", tlbl->key + 100); - emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100); - emitcode ("", "%05d$:", lbl->key + 100); - } - } - /* mark the icode as generated */ - ifx->generated = 1; - - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - return; - } - - /* if they are both bit variables */ - if (AOP_TYPE (left) == AOP_CRY && - ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT))) - { - if (AOP_TYPE (right) == AOP_LIT) - { - unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit); - if (lit == 0L) - { - emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir); - emitcode ("cpl", "c"); - } - else if (lit == 1L) - { - emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir); - } - else - { - emitcode ("clr", "c"); - } - /* AOP_TYPE(right) == AOP_CRY */ - } - else - { - symbol *lbl = newiTempLabel (NULL); - emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir); - emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100)); - emitcode ("cpl", "c"); - emitcode ("", "%05d$:", (lbl->key + 100)); - } - - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - - aopOp (result, ic, TRUE, FALSE); - - /* c = 1 if egal */ - if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) - { - outBitC (result); - goto release; - } - if (ifx) - { - genIfxJump (ifx, "c"); - goto release; - } - /* if the result is used in an arithmetic operation - then put the result in place */ - outBitC (result); - } - else - { - gencjne (left, right, newiTempLabel (NULL)); - - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - - aopOp (result, ic, TRUE, FALSE); - - if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) - { - aopPut (AOP (result), "a", 0); - goto release; - } - if (ifx) - { - genIfxJump (ifx, "a"); - goto release; - } - /* if the result is used in an arithmetic operation - then put the result in place */ - if (AOP_TYPE (result) != AOP_CRY) - outAcc (result); - /* leave the result in acc */ - } - -release: - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* ifxForOp - returns the icode containing the ifx for operand */ -/*-----------------------------------------------------------------*/ -static iCode * -ifxForOp (operand * op, iCode * ic) -{ - /* if true symbol then needs to be assigned */ - if (IS_TRUE_SYMOP (op)) - return NULL; - - /* if this has register type condition and - the next instruction is ifx with the same operand - and live to of the operand is upto the ifx only then */ - if (ic->next && - ic->next->op == IFX && - IC_COND (ic->next)->key == op->key && - OP_SYMBOL (op)->liveTo <= ic->next->seq) - return ic->next; - - 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 + */ - 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; - } - /* if GOTO or IFX */ - if (lic->op == IFX || lic->op == GOTO) break; - lic = lic->next; - } - return NULL; -} - -/*-----------------------------------------------------------------*/ -/* genAndOp - for && operation */ -/*-----------------------------------------------------------------*/ -static void -genAndOp (iCode * ic) -{ - operand *left, *right, *result; - symbol *tlbl; - - D (emitcode (";", "genAndOp ");); - - /* note here that && operations that are in an - if statement are taken away by backPatchLabels - only those used in arthmetic operations remain */ - AOP_OP_2 (ic); - AOP_SET_LOCALS (ic); - - /* if both are bit variables */ - if (AOP_TYPE (left) == AOP_CRY && - AOP_TYPE (right) == AOP_CRY) - { - emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir); - emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir); - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - - aopOp (result,ic,FALSE, FALSE); - outBitC (result); - } - else - { - tlbl = newiTempLabel (NULL); - toBoolean (left); - emitcode ("jz", "%05d$", tlbl->key + 100); - toBoolean (right); - emitcode ("", "%05d$:", tlbl->key + 100); - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - - aopOp (result,ic,FALSE, FALSE); - outBitAcc (result); - } - freeAsmop (result, NULL, ic, TRUE); -} - - -/*-----------------------------------------------------------------*/ -/* genOrOp - for || operation */ -/*-----------------------------------------------------------------*/ -static void -genOrOp (iCode * ic) -{ - operand *left, *right, *result; - symbol *tlbl; - - D (emitcode (";", "genOrOp ");); - - /* note here that || operations that are in an - if statement are taken away by backPatchLabels - only those used in arthmetic operations remain */ - AOP_OP_2 (ic); - AOP_SET_LOCALS (ic); - - /* if both are bit variables */ - if (AOP_TYPE (left) == AOP_CRY && - AOP_TYPE (right) == AOP_CRY) - { - emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir); - emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir); - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - - aopOp (result,ic,FALSE, FALSE); - - outBitC (result); - } - else - { - tlbl = newiTempLabel (NULL); - toBoolean (left); - emitcode ("jnz", "%05d$", tlbl->key + 100); - toBoolean (right); - emitcode ("", "%05d$:", tlbl->key + 100); - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - - aopOp (result,ic,FALSE, FALSE); - - outBitAcc (result); - } - - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* isLiteralBit - test if lit == 2^n */ -/*-----------------------------------------------------------------*/ -static int -isLiteralBit (unsigned long lit) -{ - unsigned long pw[32] = - {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L, - 0x100L, 0x200L, 0x400L, 0x800L, - 0x1000L, 0x2000L, 0x4000L, 0x8000L, - 0x10000L, 0x20000L, 0x40000L, 0x80000L, - 0x100000L, 0x200000L, 0x400000L, 0x800000L, - 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L, - 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L}; - int idx; - - for (idx = 0; idx < 32; idx++) - if (lit == pw[idx]) - return idx + 1; - return 0; -} - -/*-----------------------------------------------------------------*/ -/* continueIfTrue - */ -/*-----------------------------------------------------------------*/ -static void -continueIfTrue (iCode * ic) -{ - if (IC_TRUE (ic)) - emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100); - ic->generated = 1; -} - -/*-----------------------------------------------------------------*/ -/* jmpIfTrue - */ -/*-----------------------------------------------------------------*/ -static void -jumpIfTrue (iCode * ic) -{ - if (!IC_TRUE (ic)) - emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100); - ic->generated = 1; -} - -/*-----------------------------------------------------------------*/ -/* jmpTrueOrFalse - */ -/*-----------------------------------------------------------------*/ -static void -jmpTrueOrFalse (iCode * ic, symbol * tlbl) -{ - // ugly but optimized by peephole - if (IC_TRUE (ic)) - { - symbol *nlbl = newiTempLabel (NULL); - emitcode ("sjmp", "%05d$", nlbl->key + 100); - emitcode ("", "%05d$:", tlbl->key + 100); - emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100); - emitcode ("", "%05d$:", nlbl->key + 100); - } - else - { - emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100); - emitcode ("", "%05d$:", tlbl->key + 100); - } - ic->generated = 1; -} - -// Generate code to perform a bit-wise logic operation -// on two operands in far space (assumed to already have been -// aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result -// in far space. This requires pushing the result on the stack -// then popping it into the result. -static void -genFarFarLogicOp(iCode *ic, char *logicOp) -{ - int size, resultSize, compSize; - int offset = 0; - - TR_AP("#5"); - D(emitcode(";", "%s special case for 3 far operands.", logicOp);); - compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ? - AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic)); - - _startLazyDPSEvaluation(); - for (size = compSize; (size--); offset++) - { - MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, TRUE)); - emitcode ("mov", "%s, acc", DP2_RESULT_REG); - MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, TRUE)); - - emitcode (logicOp, "a,%s", DP2_RESULT_REG); - emitcode ("push", "acc"); - } - _endLazyDPSEvaluation(); - - freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE); - freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE); - aopOp (IC_RESULT(ic),ic,TRUE, FALSE); - - resultSize = AOP_SIZE(IC_RESULT(ic)); - - ADJUST_PUSHED_RESULT(compSize, resultSize); - - _startLazyDPSEvaluation(); - while (compSize--) - { - emitcode ("pop", "acc"); - aopPut (AOP (IC_RESULT (ic)), "a", compSize); - } - _endLazyDPSEvaluation(); - freeAsmop(IC_RESULT (ic), NULL, ic, TRUE); -} - - -/*-----------------------------------------------------------------*/ -/* genAnd - code for and */ -/*-----------------------------------------------------------------*/ -static void -genAnd (iCode * ic, iCode * ifx) -{ - operand *left, *right, *result; - int size, offset = 0; - unsigned long lit = 0L; - int bytelit = 0; - char buffer[10]; - bool pushResult; - - D (emitcode (";", "genAnd ");); - - AOP_OP_3_NOFATAL (ic, pushResult); - AOP_SET_LOCALS (ic); - - if (pushResult) - { - genFarFarLogicOp(ic, "anl"); - return; - } - -#ifdef DEBUG_TYPE - emitcode ("", "; Type res[%d] = l[%d]&r[%d]", - AOP_TYPE (result), - AOP_TYPE (left), AOP_TYPE (right)); - emitcode ("", "; Size res[%d] = l[%d]&r[%d]", - AOP_SIZE (result), - AOP_SIZE (left), AOP_SIZE (right)); -#endif - - /* if left is a literal & right is not then exchange them */ - if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) -#ifdef LOGIC_OPS_BROKEN - || AOP_NEEDSACC (left) -#endif - ) - { - operand *tmp = right; - right = left; - left = tmp; - } - - /* if result = right then exchange them */ - if (sameRegs (AOP (result), AOP (right))) - { - operand *tmp = right; - right = left; - left = tmp; - } - - /* if right is bit then exchange them */ - if (AOP_TYPE (right) == AOP_CRY && - AOP_TYPE (left) != AOP_CRY) - { - operand *tmp = right; - right = left; - left = tmp; - } - if (AOP_TYPE (right) == AOP_LIT) - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); - - size = AOP_SIZE (result); - - // if(bit & yy) - // result = bit & yy; - if (AOP_TYPE (left) == AOP_CRY) - { - // c = bit & literal; - if (AOP_TYPE (right) == AOP_LIT) - { - if (lit & 1) - { - if (size && sameRegs (AOP (result), AOP (left))) - // no change - goto release; - emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir); - } - else - { - // bit(result) = 0; - if (size && (AOP_TYPE (result) == AOP_CRY)) - { - emitcode ("clr", "%s", AOP (result)->aopu.aop_dir); - goto release; - } - if ((AOP_TYPE (result) == AOP_CRY) && ifx) - { - jumpIfTrue (ifx); - goto release; - } - emitcode ("clr", "c"); - } - } - else - { - if (AOP_TYPE (right) == AOP_CRY) - { - // c = bit & bit; - emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir); - emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir); - } - else - { - // c = bit & val; - MOVA (aopGet (AOP (right), 0, FALSE, FALSE, TRUE)); - // c = lsb - emitcode ("rrc", "a"); - emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir); - } - } - // bit = c - // val = c - if (size) - outBitC (result); - // if(bit & ...) - else if ((AOP_TYPE (result) == AOP_CRY) && ifx) - genIfxJump (ifx, "c"); - goto release; - } - - // if(val & 0xZZ) - size = 0, ifx != FALSE - - // bit = val & 0xZZ - size = 1, ifx = FALSE - - if ((AOP_TYPE (right) == AOP_LIT) && - (AOP_TYPE (result) == AOP_CRY) && - (AOP_TYPE (left) != AOP_CRY)) - { - int posbit = isLiteralBit (lit); - /* left & 2^n */ - if (posbit) - { - posbit--; - MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, TRUE)); - // bit = left & 2^n - if (size) - emitcode ("mov", "c,acc.%d", posbit & 0x07); - // if(left & 2^n) - else - { - if (ifx) - { - sprintf (buffer, "acc.%d", posbit & 0x07); - genIfxJump (ifx, buffer); - } - goto release; - } - } - else - { - symbol *tlbl = newiTempLabel (NULL); - int sizel = AOP_SIZE (left); - if (size) - emitcode ("setb", "c"); - while (sizel--) - { - if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L) - { - MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE)); - // byte == 2^n ? - if ((posbit = isLiteralBit (bytelit)) != 0) - emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100); - else - { - if (bytelit != 0x0FFL) - emitcode ("anl", "a,%s", - aopGet (AOP (right), offset, FALSE, TRUE, FALSE)); - emitcode ("jnz", "%05d$", tlbl->key + 100); - } - } - offset++; - } - // bit = left & literal - if (size) - { - emitcode ("clr", "c"); - emitcode ("", "%05d$:", tlbl->key + 100); - } - // if(left & literal) - else - { - if (ifx) - jmpTrueOrFalse (ifx, tlbl); - goto release; - } - } - outBitC (result); - goto release; - } - - /* if left is same as result */ - if (sameRegs (AOP (result), AOP (left))) - { - for (; size--; offset++) - { - if (AOP_TYPE (right) == AOP_LIT) - { - if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF) - continue; - else if (bytelit == 0) - aopPut (AOP (result), zero, offset); - else if (IS_AOP_PREG (result)) - { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); - emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE)); - aopPut (AOP (result), "a", offset); - } - else - emitcode ("anl", "%s,%s", - aopGet (AOP (left), offset, FALSE, TRUE, FALSE), - aopGet (AOP (right), offset, FALSE, FALSE, FALSE)); - } - else - { - if (AOP_TYPE (left) == AOP_ACC) - emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE)); - else - { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); - if (IS_AOP_PREG (result)) - { - emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE)); - aopPut (AOP (result), "a", offset); - - } - else - emitcode ("anl", "%s,a", - aopGet (AOP (left), offset, FALSE, TRUE, FALSE)); - } - } - } - } - else - { - // left & result in different registers - if (AOP_TYPE (result) == AOP_CRY) - { - // result = bit - // if(size), result in bit - // if(!size && ifx), conditional oper: if(left & right) - symbol *tlbl = newiTempLabel (NULL); - int sizer = min (AOP_SIZE (left), AOP_SIZE (right)); - if (size) - emitcode ("setb", "c"); - while (sizer--) - { - if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) { - emitcode ("anl", "a,%s", - aopGet (AOP (right), offset, FALSE, FALSE, FALSE)); - } else { - if (AOP_TYPE(left)==AOP_ACC) { - emitcode("mov", "b,a"); - MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); - emitcode("anl", "a,b"); - }else { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); - emitcode ("anl", "a,%s", - aopGet (AOP (left), offset, FALSE, FALSE, FALSE)); - } - } - emitcode ("jnz", "%05d$", tlbl->key + 100); - offset++; - } - if (size) - { - CLRC; - emitcode ("", "%05d$:", tlbl->key + 100); - outBitC (result); - } - else if (ifx) - jmpTrueOrFalse (ifx, tlbl); - } - else - { - for (; (size--); offset++) - { - // normal case - // result = left & right - if (AOP_TYPE (right) == AOP_LIT) - { - if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF) - { - aopPut (AOP (result), - aopGet (AOP (left), offset, FALSE, FALSE, FALSE), - offset); - continue; - } - else if (bytelit == 0) - { - aopPut (AOP (result), zero, offset); - continue; - } - D (emitcode (";", "better literal AND.");); - MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE)); - emitcode ("anl", "a, %s", aopGet (AOP (right), offset, - FALSE, FALSE, FALSE)); - - } - else - { - // faster than result <- left, anl result,right - // and better if result is SFR - if (AOP_TYPE (left) == AOP_ACC) - { - emitcode ("anl", "a,%s", aopGet (AOP (right), offset, - FALSE, FALSE, FALSE)); - } - else - { - char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE); - if (!strcmp(rOp, "a") || !strcmp(rOp, "acc")) - { - emitcode("mov", "b,a"); - rOp = "b"; - } - - MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE)); - emitcode ("anl", "a,%s", rOp); - } - } - aopPut (AOP (result), "a", offset); - } - } - } - -release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (result, NULL, ic, TRUE); -} - - -/*-----------------------------------------------------------------*/ -/* genOr - code for or */ -/*-----------------------------------------------------------------*/ -static void -genOr (iCode * ic, iCode * ifx) -{ - operand *left, *right, *result; - int size, offset = 0; - unsigned long lit = 0L; - bool pushResult; - - D (emitcode (";", "genOr ");); - - AOP_OP_3_NOFATAL (ic, pushResult); - AOP_SET_LOCALS (ic); - - if (pushResult) - { - genFarFarLogicOp(ic, "orl"); - return; - } - - -#ifdef DEBUG_TYPE - emitcode ("", "; Type res[%d] = l[%d]&r[%d]", - AOP_TYPE (result), - AOP_TYPE (left), AOP_TYPE (right)); - emitcode ("", "; Size res[%d] = l[%d]&r[%d]", - AOP_SIZE (result), - AOP_SIZE (left), AOP_SIZE (right)); -#endif - - /* if left is a literal & right is not then exchange them */ - if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) -#ifdef LOGIC_OPS_BROKEN - || AOP_NEEDSACC (left) // I think this is a net loss now. -#endif - ) - { - operand *tmp = right; - right = left; - left = tmp; - } - - /* if result = right then exchange them */ - if (sameRegs (AOP (result), AOP (right))) - { - operand *tmp = right; - right = left; - left = tmp; - } - - /* if right is bit then exchange them */ - if (AOP_TYPE (right) == AOP_CRY && - AOP_TYPE (left) != AOP_CRY) - { - operand *tmp = right; - right = left; - left = tmp; - } - if (AOP_TYPE (right) == AOP_LIT) - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); - - size = AOP_SIZE (result); - - // if(bit | yy) - // xx = bit | yy; - if (AOP_TYPE (left) == AOP_CRY) - { - if (AOP_TYPE (right) == AOP_LIT) - { - // c = bit & literal; - if (lit) - { - // lit != 0 => result = 1 - if (AOP_TYPE (result) == AOP_CRY) - { - if (size) - emitcode ("setb", "%s", AOP (result)->aopu.aop_dir); - else if (ifx) - continueIfTrue (ifx); - goto release; - } - emitcode ("setb", "c"); - } - else - { - // lit == 0 => result = left - if (size && sameRegs (AOP (result), AOP (left))) - goto release; - emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir); - } - } - else - { - if (AOP_TYPE (right) == AOP_CRY) - { - // c = bit | bit; - emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir); - emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir); - } - else - { - // c = bit | val; - symbol *tlbl = newiTempLabel (NULL); - if (!((AOP_TYPE (result) == AOP_CRY) && ifx)) - emitcode ("setb", "c"); - emitcode ("jb", "%s,%05d$", - AOP (left)->aopu.aop_dir, tlbl->key + 100); - toBoolean (right); - emitcode ("jnz", "%05d$", tlbl->key + 100); - if ((AOP_TYPE (result) == AOP_CRY) && ifx) - { - jmpTrueOrFalse (ifx, tlbl); - goto release; - } - else - { - CLRC; - emitcode ("", "%05d$:", tlbl->key + 100); - } - } - } - // bit = c - // val = c - if (size) - outBitC (result); - // if(bit | ...) - else if ((AOP_TYPE (result) == AOP_CRY) && ifx) - genIfxJump (ifx, "c"); - goto release; - } - - // if(val | 0xZZ) - size = 0, ifx != FALSE - - // bit = val | 0xZZ - size = 1, ifx = FALSE - - if ((AOP_TYPE (right) == AOP_LIT) && - (AOP_TYPE (result) == AOP_CRY) && - (AOP_TYPE (left) != AOP_CRY)) - { - if (lit) - { - // result = 1 - if (size) - emitcode ("setb", "%s", AOP (result)->aopu.aop_dir); - else - continueIfTrue (ifx); - goto release; - } - else - { - // lit = 0, result = boolean(left) - if (size) - emitcode ("setb", "c"); - toBoolean (right); - if (size) - { - symbol *tlbl = newiTempLabel (NULL); - emitcode ("jnz", "%05d$", tlbl->key + 100); - CLRC; - emitcode ("", "%05d$:", tlbl->key + 100); - } - else - { - genIfxJump (ifx, "a"); - goto release; - } - } - outBitC (result); - goto release; - } - - /* if left is same as result */ - if (sameRegs (AOP (result), AOP (left))) - { - for (; size--; offset++) - { - if (AOP_TYPE (right) == AOP_LIT) - { - if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L) - { - continue; - } - else - { - if (IS_AOP_PREG (left)) - { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); - emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE)); - aopPut (AOP (result), "a", offset); - } - else - { - emitcode ("orl", "%s,%s", - aopGet (AOP (left), offset, FALSE, TRUE, FALSE), - aopGet (AOP (right), offset, FALSE, FALSE, FALSE)); - } - } - } - else - { - if (AOP_TYPE (left) == AOP_ACC) - { - emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE)); - } - else - { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); - if (IS_AOP_PREG (left)) - { - emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE)); - aopPut (AOP (result), "a", offset); - } - else - { - emitcode ("orl", "%s,a", - aopGet (AOP (left), offset, FALSE, TRUE, FALSE)); - } - } - } - } - } - else - { - // left & result in different registers - if (AOP_TYPE (result) == AOP_CRY) - { - // result = bit - // if(size), result in bit - // if(!size && ifx), conditional oper: if(left | right) - symbol *tlbl = newiTempLabel (NULL); - int sizer = max (AOP_SIZE (left), AOP_SIZE (right)); - if (size) - emitcode ("setb", "c"); - while (sizer--) - { - if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) { - emitcode ("orl", "a,%s", - aopGet (AOP (right), offset, FALSE, FALSE, FALSE)); - } else { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); - emitcode ("orl", "a,%s", - aopGet (AOP (left), offset, FALSE, FALSE, FALSE)); - } - emitcode ("jnz", "%05d$", tlbl->key + 100); - offset++; - } - if (size) - { - CLRC; - emitcode ("", "%05d$:", tlbl->key + 100); - outBitC (result); - } - else if (ifx) - jmpTrueOrFalse (ifx, tlbl); - } - else - { - _startLazyDPSEvaluation(); - for (; (size--); offset++) - { - // normal case - // result = left & right - if (AOP_TYPE (right) == AOP_LIT) - { - if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L) - { - aopPut (AOP (result), - aopGet (AOP (left), offset, FALSE, FALSE, FALSE), - offset); - continue; - } - D (emitcode (";", "better literal OR.");); - MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE)); - emitcode ("orl", "a, %s", aopGet (AOP (right), offset, - FALSE, FALSE, FALSE)); - - } - else - { - // faster than result <- left, anl result,right - // and better if result is SFR - if (AOP_TYPE (left) == AOP_ACC) - { - emitcode ("orl", "a,%s", aopGet (AOP (right), offset, - FALSE, FALSE, FALSE)); - } - else - { - char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE); - - if (!strcmp(rOp, "a") || !strcmp(rOp, "acc")) - { - emitcode("mov", "b,a"); - rOp = "b"; - } - - MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE)); - emitcode ("orl", "a,%s", rOp); - } - } - aopPut (AOP (result), "a", offset); - } - _endLazyDPSEvaluation(); - } - } - -release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genXor - code for xclusive or */ -/*-----------------------------------------------------------------*/ -static void -genXor (iCode * ic, iCode * ifx) -{ - operand *left, *right, *result; - int size, offset = 0; - unsigned long lit = 0L; - bool pushResult; - - D (emitcode (";", "genXor ");); - - AOP_OP_3_NOFATAL (ic, pushResult); - AOP_SET_LOCALS (ic); - - if (pushResult) - { - genFarFarLogicOp(ic, "xrl"); - return; - } - -#ifdef DEBUG_TYPE - emitcode ("", "; Type res[%d] = l[%d]&r[%d]", - AOP_TYPE (result), - AOP_TYPE (left), AOP_TYPE (right)); - emitcode ("", "; Size res[%d] = l[%d]&r[%d]", - AOP_SIZE (result), - AOP_SIZE (left), AOP_SIZE (right)); -#endif - - /* if left is a literal & right is not || - if left needs acc & right does not */ - if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) -#ifdef LOGIC_OPS_BROKEN - || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)) -#endif - ) - { - operand *tmp = right; - right = left; - left = tmp; - } - - /* if result = right then exchange them */ - if (sameRegs (AOP (result), AOP (right))) - { - operand *tmp = right; - right = left; - left = tmp; - } - - /* if right is bit then exchange them */ - if (AOP_TYPE (right) == AOP_CRY && - AOP_TYPE (left) != AOP_CRY) - { - operand *tmp = right; - right = left; - left = tmp; - } - if (AOP_TYPE (right) == AOP_LIT) - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); - - size = AOP_SIZE (result); - - // if(bit ^ yy) - // xx = bit ^ yy; - if (AOP_TYPE (left) == AOP_CRY) - { - if (AOP_TYPE (right) == AOP_LIT) - { - // c = bit & literal; - if (lit >> 1) - { - // lit>>1 != 0 => result = 1 - if (AOP_TYPE (result) == AOP_CRY) - { - if (size) - emitcode ("setb", "%s", AOP (result)->aopu.aop_dir); - else if (ifx) - continueIfTrue (ifx); - goto release; - } - emitcode ("setb", "c"); - } - else - { - // lit == (0 or 1) - if (lit == 0) - { - // lit == 0, result = left - if (size && sameRegs (AOP (result), AOP (left))) - goto release; - emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir); - } - else - { - // lit == 1, result = not(left) - if (size && sameRegs (AOP (result), AOP (left))) - { - emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir); - goto release; - } - else - { - emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir); - emitcode ("cpl", "c"); - } - } - } - - } - else - { - // right != literal - symbol *tlbl = newiTempLabel (NULL); - if (AOP_TYPE (right) == AOP_CRY) - { - // c = bit ^ bit; - emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir); - } - else - { - int sizer = AOP_SIZE (right); - // c = bit ^ val - // if val>>1 != 0, result = 1 - emitcode ("setb", "c"); - while (sizer) - { - MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, TRUE)); - if (sizer == 1) - // test the msb of the lsb - emitcode ("anl", "a,#0xfe"); - emitcode ("jnz", "%05d$", tlbl->key + 100); - sizer--; - } - // val = (0,1) - emitcode ("rrc", "a"); - } - emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100)); - emitcode ("cpl", "c"); - emitcode ("", "%05d$:", (tlbl->key + 100)); - } - // bit = c - // val = c - if (size) - outBitC (result); - // if(bit | ...) - else if ((AOP_TYPE (result) == AOP_CRY) && ifx) - genIfxJump (ifx, "c"); - goto release; - } - - if (sameRegs (AOP (result), AOP (left))) - { - /* if left is same as result */ - for (; size--; offset++) - { - if (AOP_TYPE (right) == AOP_LIT) - { - if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L) - continue; - else if (IS_AOP_PREG (left)) - { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); - emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE)); - aopPut (AOP (result), "a", offset); - } - else - emitcode ("xrl", "%s,%s", - aopGet (AOP (left), offset, FALSE, TRUE, FALSE), - aopGet (AOP (right), offset, FALSE, FALSE, FALSE)); - } - else - { - if (AOP_TYPE (left) == AOP_ACC) - emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE)); - else - { - MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE)); - if (IS_AOP_PREG (left)) - { - emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE, FALSE)); - aopPut (AOP (result), "a", offset); - } - else - emitcode ("xrl", "%s,a", - aopGet (AOP (left), offset, FALSE, TRUE, FALSE)); - } - } - } - } - else - { - // left & result in different registers - if (AOP_TYPE (result) == AOP_CRY) - { - // result = bit - // if(size), result in bit - // if(!size && ifx), conditional oper: if(left ^ right) - symbol *tlbl = newiTempLabel (NULL); - int sizer = max (AOP_SIZE (left), AOP_SIZE (right)); - - if (size) - emitcode ("setb", "c"); - while (sizer--) - { - if ((AOP_TYPE (right) == AOP_LIT) && - (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)) - { - MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE)); - } - else - { - if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) { - emitcode ("xrl", "a,%s", - aopGet (AOP (right), offset, FALSE, FALSE, FALSE)); - } else { - char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE); - if (!strcmp(rOp, "a") || !strcmp(rOp, "acc")) - { - emitcode("mov", "b,a"); - rOp = "b"; - } - - MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE)); - emitcode ("xrl", "a,%s", rOp); - } - } - emitcode ("jnz", "%05d$", tlbl->key + 100); - offset++; - } - if (size) - { - CLRC; - emitcode ("", "%05d$:", tlbl->key + 100); - outBitC (result); - } - else if (ifx) - jmpTrueOrFalse (ifx, tlbl); - } - else - { - for (; (size--); offset++) - { - // normal case - // result = left & right - if (AOP_TYPE (right) == AOP_LIT) - { - if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L) - { - aopPut (AOP (result), - aopGet (AOP (left), offset, FALSE, FALSE, FALSE), - offset); - continue; - } - D (emitcode (";", "better literal XOR.");); - MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE)); - emitcode ("xrl", "a, %s", aopGet (AOP (right), offset, - FALSE, FALSE, FALSE)); - } - else - { - // faster than result <- left, anl result,right - // and better if result is SFR - if (AOP_TYPE (left) == AOP_ACC) - { - emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, - FALSE, FALSE, FALSE)); - } - else - { - char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE); - if (!strcmp(rOp, "a") || !strcmp(rOp, "acc")) - { - emitcode("mov", "b,a"); - rOp = "b"; - } - - MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE)); - emitcode ("xrl", "a,%s", rOp); - } - } - aopPut (AOP (result), "a", offset); - } - } - - } - -release: - freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE)); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genInline - write the inline code out */ -/*-----------------------------------------------------------------*/ -static void -genInline (iCode * ic) -{ - char *buffer, *bp, *bp1; - - D (emitcode (";", "genInline "); - ); - - _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 */ - while (*bp) - { - if (*bp == '\n') - { - *bp++ = '\0'; - emitcode (bp1, ""); - bp1 = bp; - } - else - { - if (*bp == ':') - { - bp++; - *bp = '\0'; - bp++; - emitcode (bp1, ""); - bp1 = bp; - } - else - bp++; - } - } - if (bp1 != bp) - emitcode (bp1, ""); - /* emitcode("",buffer); */ - _G.inLine -= (!options.asmpeep); -} - -/*-----------------------------------------------------------------*/ -/* genRRC - rotate right with carry */ -/*-----------------------------------------------------------------*/ -static void -genRRC (iCode * ic) -{ - operand *left, *result; - int size, offset = 0; - char *l; - - D (emitcode (";", "genRRC "); - ); - - /* rotate right with carry */ - left = IC_LEFT (ic); - result = IC_RESULT (ic); - aopOp (left, ic, FALSE, FALSE); - aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR); - - /* move it to the result */ - size = AOP_SIZE (result); - offset = size - 1; - CLRC; - - _startLazyDPSEvaluation (); - while (size--) - { - l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("rrc", "a"); - if (AOP_SIZE (result) > 1) - aopPut (AOP (result), "a", offset--); - } - _endLazyDPSEvaluation (); - - /* now we need to put the carry into the - highest order byte of the result */ - if (AOP_SIZE (result) > 1) - { - l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, TRUE); - MOVA (l); - } - emitcode ("mov", "acc.7,c"); - aopPut (AOP (result), "a", AOP_SIZE (result) - 1); - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genRLC - generate code for rotate left with carry */ -/*-----------------------------------------------------------------*/ -static void -genRLC (iCode * ic) -{ - operand *left, *result; - int size, offset = 0; - char *l; - - D (emitcode (";", "genRLC "); - ); - - /* rotate right with carry */ - left = IC_LEFT (ic); - result = IC_RESULT (ic); - aopOp (left, ic, FALSE, FALSE); - aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR); - - /* move it to the result */ - size = AOP_SIZE (result); - offset = 0; - if (size--) - { - l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("add", "a,acc"); - if (AOP_SIZE (result) > 1) - { - aopPut (AOP (result), "a", offset++); - } - - _startLazyDPSEvaluation (); - while (size--) - { - l = aopGet (AOP (left), offset, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("rlc", "a"); - if (AOP_SIZE (result) > 1) - aopPut (AOP (result), "a", offset++); - } - _endLazyDPSEvaluation (); - } - /* now we need to put the carry into the - highest order byte of the result */ - if (AOP_SIZE (result) > 1) - { - l = aopGet (AOP (result), 0, FALSE, FALSE, TRUE); - MOVA (l); - } - emitcode ("mov", "acc.0,c"); - aopPut (AOP (result), "a", 0); - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genGetHbit - generates code get highest order bit */ -/*-----------------------------------------------------------------*/ -static void -genGetHbit (iCode * ic) -{ - operand *left, *result; - left = IC_LEFT (ic); - result = IC_RESULT (ic); - aopOp (left, ic, FALSE, FALSE); - aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR); - - D (emitcode (";", "genGetHbit "); - ); - - /* get the highest order byte into a */ - MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, TRUE)); - if (AOP_TYPE (result) == AOP_CRY) - { - emitcode ("rlc", "a"); - outBitC (result); - } - else - { - emitcode ("rl", "a"); - emitcode ("anl", "a,#0x01"); - outAcc (result); - } - - - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* AccRol - rotate left accumulator by known count */ -/*-----------------------------------------------------------------*/ -static void -AccRol (int shCount) -{ - shCount &= 0x0007; // shCount : 0..7 - - switch (shCount) - { - case 0: - break; - case 1: - emitcode ("rl", "a"); - break; - case 2: - emitcode ("rl", "a"); - emitcode ("rl", "a"); - break; - case 3: - emitcode ("swap", "a"); - emitcode ("rr", "a"); - break; - case 4: - emitcode ("swap", "a"); - break; - case 5: - emitcode ("swap", "a"); - emitcode ("rl", "a"); - break; - case 6: - emitcode ("rr", "a"); - emitcode ("rr", "a"); - break; - case 7: - emitcode ("rr", "a"); - break; - } -} - -/*-----------------------------------------------------------------*/ -/* AccLsh - left shift accumulator by known count */ -/*-----------------------------------------------------------------*/ -static void -AccLsh (int shCount) -{ - if (shCount != 0) - { - if (shCount == 1) - emitcode ("add", "a,acc"); - else if (shCount == 2) - { - emitcode ("add", "a,acc"); - emitcode ("add", "a,acc"); - } - else - { - /* rotate left accumulator */ - AccRol (shCount); - /* and kill the lower order bits */ - emitcode ("anl", "a,#0x%02x", SLMask[shCount]); - } - } -} - -/*-----------------------------------------------------------------*/ -/* AccRsh - right shift accumulator by known count */ -/*-----------------------------------------------------------------*/ -static void -AccRsh (int shCount) -{ - if (shCount != 0) - { - if (shCount == 1) - { - CLRC; - emitcode ("rrc", "a"); - } - else - { - /* rotate right accumulator */ - AccRol (8 - shCount); - /* and kill the higher order bits */ - emitcode ("anl", "a,#0x%02x", SRMask[shCount]); - } - } -} - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* AccSRsh - signed right shift accumulator by known count */ -/*-----------------------------------------------------------------*/ -static void -AccSRsh (int shCount) -{ - symbol *tlbl; - if (shCount != 0) - { - if (shCount == 1) - { - emitcode ("mov", "c,acc.7"); - emitcode ("rrc", "a"); - } - else if (shCount == 2) - { - emitcode ("mov", "c,acc.7"); - emitcode ("rrc", "a"); - emitcode ("mov", "c,acc.7"); - emitcode ("rrc", "a"); - } - else - { - tlbl = newiTempLabel (NULL); - /* rotate right accumulator */ - AccRol (8 - shCount); - /* and kill the higher order bits */ - emitcode ("anl", "a,#0x%02x", SRMask[shCount]); - emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100); - emitcode ("orl", "a,#0x%02x", - (unsigned char) ~SRMask[shCount]); - emitcode ("", "%05d$:", tlbl->key + 100); - } - } -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* shiftR1Left2Result - shift right one byte from left to result */ -/*-----------------------------------------------------------------*/ -static void -shiftR1Left2Result (operand * left, int offl, - operand * result, int offr, - int shCount, int sign) -{ - MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE)); - /* shift right accumulator */ - if (sign) - AccSRsh (shCount); - else - AccRsh (shCount); - aopPut (AOP (result), "a", offr); -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* shiftL1Left2Result - shift left one byte from left to result */ -/*-----------------------------------------------------------------*/ -static void -shiftL1Left2Result (operand * left, int offl, - operand * result, int offr, int shCount) -{ - MOVA(aopGet (AOP (left), offl, FALSE, FALSE, TRUE)); - /* shift left accumulator */ - AccLsh (shCount); - aopPut (AOP (result), "a", offr); -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* movLeft2Result - move byte from left to result */ -/*-----------------------------------------------------------------*/ -static void -movLeft2Result (operand * left, int offl, - operand * result, int offr, int sign) -{ - char *l; - if (!sameRegs (AOP (left), AOP (result)) || (offl != offr)) - { - l = aopGet (AOP (left), offl, FALSE, FALSE, TRUE); - - if (*l == '@' && (IS_AOP_PREG (result))) - { - emitcode ("mov", "a,%s", l); - aopPut (AOP (result), "a", offr); - } - else - { - if (!sign) - { - aopPut (AOP (result), l, offr); - } - else - { - /* MSB sign in acc.7 ! */ - if (getDataSize (left) == offl + 1) - { - emitcode ("mov", "a,%s", l); - aopPut (AOP (result), "a", offr); - } - } - } - } -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* AccAXRrl1 - right rotate c->a:x->c by 1 */ -/*-----------------------------------------------------------------*/ -static void -AccAXRrl1 (char *x) -{ - emitcode ("rrc", "a"); - emitcode ("xch", "a,%s", x); - emitcode ("rrc", "a"); - emitcode ("xch", "a,%s", x); -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -//REMOVE ME!!! -/*-----------------------------------------------------------------*/ -/* AccAXLrl1 - left rotate c<-a:x<-c by 1 */ -/*-----------------------------------------------------------------*/ -static void -AccAXLrl1 (char *x) -{ - emitcode ("xch", "a,%s", x); - emitcode ("rlc", "a"); - emitcode ("xch", "a,%s", x); - emitcode ("rlc", "a"); -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* AccAXLsh1 - left shift a:x<-0 by 1 */ -/*-----------------------------------------------------------------*/ -static void -AccAXLsh1 (char *x) -{ - emitcode ("xch", "a,%s", x); - emitcode ("add", "a,acc"); - emitcode ("xch", "a,%s", x); - emitcode ("rlc", "a"); -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* AccAXLsh - left shift a:x by known count (0..7) */ -/*-----------------------------------------------------------------*/ -static void -AccAXLsh (char *x, int shCount) -{ - switch (shCount) - { - case 0: - break; - case 1: - AccAXLsh1 (x); - break; - case 2: - AccAXLsh1 (x); - AccAXLsh1 (x); - break; - case 3: - case 4: - case 5: // AAAAABBB:CCCCCDDD - - AccRol (shCount); // BBBAAAAA:CCCCCDDD - - emitcode ("anl", "a,#0x%02x", - SLMask[shCount]); // BBB00000:CCCCCDDD - - emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000 - - AccRol (shCount); // DDDCCCCC:BBB00000 - - emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC - - emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC - - emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC - - emitcode ("anl", "a,#0x%02x", - SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC - - emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000 - - emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000 - - 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 - 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 - - emitcode ("anl", "a,#0x%02x", - SRMask[shCount]); // 0000000B:CCCCCCCD - - emitcode ("mov", "c,acc.0"); // c = B - - emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B - - AccAXRrl1 (x); // BCCCCCCC:D0000000 - - break; - default: - break; - } -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -//REMOVE ME!!! -/*-----------------------------------------------------------------*/ -/* AccAXRsh - right shift a:x known count (0..7) */ -/*-----------------------------------------------------------------*/ -static void -AccAXRsh (char *x, int shCount) -{ - switch (shCount) - { - case 0: - break; - case 1: - CLRC; - AccAXRrl1 (x); // 0->a:x - - break; - case 2: - CLRC; - AccAXRrl1 (x); // 0->a:x - - CLRC; - AccAXRrl1 (x); // 0->a:x - - break; - case 3: - case 4: - case 5: // AAAAABBB:CCCCCDDD = a:x - - AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC - - emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA - - AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA - - emitcode ("anl", "a,#0x%02x", - SRMask[shCount]); // 000CCCCC:BBBAAAAA - - emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA - - emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA) - - emitcode ("anl", "a,#0x%02x", - SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA) - - emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA - - emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA - - emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC - - break; - case 6: // AABBBBBB:CCDDDDDD - - emitcode ("mov", "c,acc.7"); - AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA - - AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA - - emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC - - emitcode ("anl", "a,#0x%02x", - SRMask[shCount]); // 000000AA:BBBBBBCC - - break; - case 7: // ABBBBBBB:CDDDDDDD - - emitcode ("mov", "c,acc.7"); // c = A - - AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA - - emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC - - emitcode ("anl", "a,#0x%02x", - SRMask[shCount]); // 0000000A:BBBBBBBC - - break; - default: - break; - } -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* AccAXRshS - right shift signed a:x known count (0..7) */ -/*-----------------------------------------------------------------*/ -static void -AccAXRshS (char *x, int shCount) -{ - symbol *tlbl; - switch (shCount) - { - case 0: - break; - case 1: - emitcode ("mov", "c,acc.7"); - AccAXRrl1 (x); // s->a:x - - break; - case 2: - emitcode ("mov", "c,acc.7"); - AccAXRrl1 (x); // s->a:x - - emitcode ("mov", "c,acc.7"); - AccAXRrl1 (x); // s->a:x - - break; - case 3: - case 4: - case 5: // AAAAABBB:CCCCCDDD = a:x - - tlbl = newiTempLabel (NULL); - AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD - - emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA - - AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA - - emitcode ("anl", "a,#0x%02x", - SRMask[shCount]); // 000CCCCC:BBBAAAAA - - emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA - - emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA) - - emitcode ("anl", "a,#0x%02x", - SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA) - - emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA - - emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA - - emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC - - emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100); - emitcode ("orl", "a,#0x%02x", - (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC - - emitcode ("", "%05d$:", tlbl->key + 100); - break; // SSSSAAAA:BBBCCCCC - - case 6: // AABBBBBB:CCDDDDDD - - tlbl = newiTempLabel (NULL); - emitcode ("mov", "c,acc.7"); - AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA - - AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA - - emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC - - emitcode ("anl", "a,#0x%02x", - SRMask[shCount]); // 000000AA:BBBBBBCC - - emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100); - emitcode ("orl", "a,#0x%02x", - (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC - - emitcode ("", "%05d$:", tlbl->key + 100); - break; - case 7: // ABBBBBBB:CDDDDDDD - - tlbl = newiTempLabel (NULL); - emitcode ("mov", "c,acc.7"); // c = A - - AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA - - emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC - - emitcode ("anl", "a,#0x%02x", - SRMask[shCount]); // 0000000A:BBBBBBBC - - emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100); - emitcode ("orl", "a,#0x%02x", - (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC - - emitcode ("", "%05d$:", tlbl->key + 100); - break; - default: - break; - } -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -static void -_loadLeftIntoAx(char **lsb, - operand *left, - operand *result, - int offl, - int offr) -{ - // Get the initial value from left into a pair of registers. - // MSB must be in A, LSB can be any register. - // - // If the result is held in registers, it is an optimization - // if the LSB can be held in the register which will hold the, - // result LSB since this saves us from having to copy it into - // the result following AccAXLsh. - // - // If the result is addressed indirectly, this is not a gain. - if (AOP_NEEDSACC(result)) - { - char *leftByte; - - _startLazyDPSEvaluation(); - if (AOP_TYPE(left) == AOP_DPTR2) - { - // Get MSB in A. - MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE)); - // get LSB in DP2_RESULT_REG. - leftByte = aopGet(AOP(left), offl, FALSE, FALSE, FALSE); - assert(!strcmp(leftByte, DP2_RESULT_REG)); - } - else - { - // get LSB into DP2_RESULT_REG - leftByte = aopGet (AOP(left), offl, FALSE, FALSE, TRUE); - if (strcmp(leftByte, DP2_RESULT_REG)) - { - TR_AP("#7"); - emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte); - } - // And MSB in A. - leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, TRUE); - assert(strcmp(leftByte, DP2_RESULT_REG)); - MOVA(leftByte); - } - _endLazyDPSEvaluation(); - *lsb = DP2_RESULT_REG; - } - else - { - if (sameRegs (AOP (result), AOP (left)) && - ((offl + MSB16) == offr)) - { - /* don't crash result[offr] */ - MOVA(aopGet(AOP(left), offl, FALSE, FALSE, TRUE)); - emitcode ("xch", "a,%s", - aopGet(AOP(left), offl + MSB16, FALSE, FALSE, FALSE)); - } - else - { - movLeft2Result (left, offl, result, offr, 0); - MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, TRUE)); - } - *lsb = aopGet(AOP (result), offr, FALSE, FALSE, FALSE); - assert(strcmp(*lsb,"a")); - } -} - -static void -_storeAxResults(char *lsb, - operand *result, - int offr) -{ - _startLazyDPSEvaluation(); - if (AOP_NEEDSACC(result)) - { - /* We have to explicitly update the result LSB. - */ - emitcode("xch","a,%s", lsb); - aopPut(AOP(result), "a", offr); - emitcode("mov","a,%s", lsb); - } - if (getDataSize (result) > 1) - { - aopPut (AOP (result), "a", offr + MSB16); - } - _endLazyDPSEvaluation(); -} - -/*-----------------------------------------------------------------*/ -/* shiftL2Left2Result - shift left two bytes from left to result */ -/*-----------------------------------------------------------------*/ -static void -shiftL2Left2Result (operand * left, int offl, - operand * result, int offr, int shCount) -{ - char *lsb; - - _loadLeftIntoAx(&lsb, left, result, offl, offr); - - AccAXLsh (lsb, shCount); - - _storeAxResults(lsb, result, offr); -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* shiftR2Left2Result - shift right two bytes from left to result */ -/*-----------------------------------------------------------------*/ -static void -shiftR2Left2Result (operand * left, int offl, - operand * result, int offr, - int shCount, int sign) -{ - char *lsb; - - _loadLeftIntoAx(&lsb, left, result, offl, offr); - - /* a:x >> shCount (x = lsb(result)) */ - if (sign) - { - AccAXRshS(lsb, shCount); - } - else - { - AccAXRsh(lsb, shCount); - } - - _storeAxResults(lsb, result, offr); -} -#endif - -#if 0 -//REMOVE ME!!! -/*-----------------------------------------------------------------*/ -/* shiftLLeftOrResult - shift left one byte from left, or to result */ -/*-----------------------------------------------------------------*/ -static void -shiftLLeftOrResult (operand * left, int offl, - operand * result, int offr, int shCount) -{ - MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE)); - /* shift left accumulator */ - AccLsh (shCount); - /* or with result */ - emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE)); - /* back to result */ - aopPut (AOP (result), "a", offr); -} -#endif - -#if 0 -//REMOVE ME!!! -/*-----------------------------------------------------------------*/ -/* shiftRLeftOrResult - shift right one byte from left,or to result */ -/*-----------------------------------------------------------------*/ -static void -shiftRLeftOrResult (operand * left, int offl, - operand * result, int offr, int shCount) -{ - MOVA (aopGet (AOP (left), offl, FALSE, FALSE, TRUE)); - /* shift right accumulator */ - AccRsh (shCount); - /* or with result */ - emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE, FALSE)); - /* back to result */ - aopPut (AOP (result), "a", offr); -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* genlshOne - left shift a one byte quantity by known count */ -/*-----------------------------------------------------------------*/ -static void -genlshOne (operand * result, operand * left, int shCount) -{ - D (emitcode (";", "genlshOne ");); - shiftL1Left2Result (left, LSB, result, LSB, shCount); -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* genlshTwo - left shift two bytes by known amount != 0 */ -/*-----------------------------------------------------------------*/ -static void -genlshTwo (operand * result, operand * left, int shCount) -{ - int size; - - D (emitcode (";", "genlshTwo ");); - - size = getDataSize (result); - - /* if shCount >= 8 */ - if (shCount >= 8) - { - shCount -= 8; - - _startLazyDPSEvaluation(); - - if (size > 1) - { - if (shCount) - { - _endLazyDPSEvaluation(); - shiftL1Left2Result (left, LSB, result, MSB16, shCount); - aopPut (AOP (result), zero, LSB); - } - else - { - movLeft2Result (left, LSB, result, MSB16, 0); - aopPut (AOP (result), zero, LSB); - _endLazyDPSEvaluation(); - } - } - else - { - aopPut (AOP (result), zero, LSB); - _endLazyDPSEvaluation(); - } - } - - /* 1 <= shCount <= 7 */ - else - { - if (size == 1) - { - shiftL1Left2Result (left, LSB, result, LSB, shCount); - } - else - { - shiftL2Left2Result (left, LSB, result, LSB, shCount); - } - } -} -#endif - -#if 0 -//REMOVE ME!!! -/*-----------------------------------------------------------------*/ -/* shiftLLong - shift left one long from left to result */ -/* offl = LSB or MSB16 */ -/*-----------------------------------------------------------------*/ -static void -shiftLLong (operand * left, operand * result, int offr) -{ - char *l; - int size = AOP_SIZE (result); - - if (size >= LSB + offr) - { - l = aopGet (AOP (left), LSB, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("add", "a,acc"); - if (sameRegs (AOP (left), AOP (result)) && - size >= MSB16 + offr && offr != LSB) - emitcode ("xch", "a,%s", - aopGet (AOP (left), LSB + offr, FALSE, FALSE, FALSE)); - else - aopPut (AOP (result), "a", LSB + offr); - } - - if (size >= MSB16 + offr) - { - if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB)) - { - l = aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE); - MOVA (l); - } - emitcode ("rlc", "a"); - if (sameRegs (AOP (left), AOP (result)) && - size >= MSB24 + offr && offr != LSB) - emitcode ("xch", "a,%s", - aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, FALSE)); - else - aopPut (AOP (result), "a", MSB16 + offr); - } - - if (size >= MSB24 + offr) - { - if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB)) - { - l = aopGet (AOP (left), MSB24, FALSE, FALSE, TRUE); - MOVA (l); - } - emitcode ("rlc", "a"); - if (sameRegs (AOP (left), AOP (result)) && - size >= MSB32 + offr && offr != LSB) - emitcode ("xch", "a,%s", - aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, FALSE)); - else - aopPut (AOP (result), "a", MSB24 + offr); - } - - if (size > MSB32 + offr) - { - if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB)) - { - l = aopGet (AOP (left), MSB32, FALSE, FALSE, TRUE); - MOVA (l); - } - emitcode ("rlc", "a"); - aopPut (AOP (result), "a", MSB32 + offr); - } - if (offr != LSB) - aopPut (AOP (result), zero, LSB); -} -#endif - -#if 0 -//REMOVE ME!!! -/*-----------------------------------------------------------------*/ -/* genlshFour - shift four byte by a known amount != 0 */ -/*-----------------------------------------------------------------*/ -static void -genlshFour (operand * result, operand * left, int shCount) -{ - int size; - - D (emitcode (";", "genlshFour "); - ); - - size = AOP_SIZE (result); - - /* if shifting more that 3 bytes */ - if (shCount >= 24) - { - shCount -= 24; - if (shCount) - /* lowest order of left goes to the highest - order of the destination */ - shiftL1Left2Result (left, LSB, result, MSB32, shCount); - else - movLeft2Result (left, LSB, result, MSB32, 0); - aopPut (AOP (result), zero, LSB); - aopPut (AOP (result), zero, MSB16); - aopPut (AOP (result), zero, MSB24); - return; - } - - /* more than two bytes */ - else if (shCount >= 16) - { - /* lower order two bytes goes to higher order two bytes */ - shCount -= 16; - /* if some more remaining */ - if (shCount) - shiftL2Left2Result (left, LSB, result, MSB24, shCount); - else - { - movLeft2Result (left, MSB16, result, MSB32, 0); - movLeft2Result (left, LSB, result, MSB24, 0); - } - aopPut (AOP (result), zero, MSB16); - aopPut (AOP (result), zero, LSB); - return; - } - - /* if more than 1 byte */ - else if (shCount >= 8) - { - /* lower order three bytes goes to higher order three bytes */ - shCount -= 8; - if (size == 2) - { - if (shCount) - shiftL1Left2Result (left, LSB, result, MSB16, shCount); - else - movLeft2Result (left, LSB, result, MSB16, 0); - } - else - { /* size = 4 */ - if (shCount == 0) - { - movLeft2Result (left, MSB24, result, MSB32, 0); - movLeft2Result (left, MSB16, result, MSB24, 0); - movLeft2Result (left, LSB, result, MSB16, 0); - aopPut (AOP (result), zero, LSB); - } - else if (shCount == 1) - shiftLLong (left, result, MSB16); - else - { - shiftL2Left2Result (left, MSB16, result, MSB24, shCount); - shiftL1Left2Result (left, LSB, result, MSB16, shCount); - shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount); - aopPut (AOP (result), zero, LSB); - } - } - } - - /* 1 <= shCount <= 7 */ - else if (shCount <= 2) - { - shiftLLong (left, result, LSB); - if (shCount == 2) - shiftLLong (result, result, LSB); - } - /* 3 <= shCount <= 7, optimize */ - else - { - shiftL2Left2Result (left, MSB24, result, MSB24, shCount); - shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount); - shiftL2Left2Result (left, LSB, result, LSB, shCount); - } -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* genLeftShiftLiteral - left shifting by known count */ -/*-----------------------------------------------------------------*/ -static bool -genLeftShiftLiteral (operand * left, - operand * right, - operand * result, - iCode * ic) -{ - int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit); - int size; - - size = getSize (operandType (result)); - - D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size);); - - /* We only handle certain easy cases so far. */ - if ((shCount != 0) - && (shCount < (size * 8)) - && (size != 1) - && (size != 2)) - { - D(emitcode (";", "genLeftShiftLiteral wimping out");); - return FALSE; - } - - freeAsmop (right, NULL, ic, TRUE); - - aopOp(left, ic, FALSE, FALSE); - aopOp(result, ic, FALSE, (AOP_TYPE(left) == AOP_DPTR)); - -#if 1 // debug spew - if (IS_SYMOP(left) && OP_SYMBOL(left)->aop) - { - emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left)); - if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc) - { - emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname); - } - } - if (IS_SYMOP(result) && OP_SYMBOL(result)->aop) - { - emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result)); - if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc) - { - emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname); - } - } -#endif - -#if VIEW_SIZE - emitcode ("; shift left ", "result %d, left %d", size, - AOP_SIZE (left)); -#endif - - /* I suppose that the left size >= result size */ - if (shCount == 0) - { - _startLazyDPSEvaluation(); - while (size--) - { - movLeft2Result (left, size, result, size, 0); - } - _endLazyDPSEvaluation(); - } - else if (shCount >= (size * 8)) - { - _startLazyDPSEvaluation(); - while (size--) - { - aopPut (AOP (result), zero, size); - } - _endLazyDPSEvaluation(); - } - else - { - switch (size) - { - case 1: - genlshOne (result, left, shCount); - break; - - case 2: - genlshTwo (result, left, shCount); - break; -#if 0 - case 4: - genlshFour (result, left, shCount); - break; -#endif - default: - fprintf(stderr, "*** ack! mystery literal shift!\n"); - break; - } - } - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); - return TRUE; -} -#endif - -/*-----------------------------------------------------------------*/ -/* genLeftShift - generates code for left shifting */ -/*-----------------------------------------------------------------*/ -static void -genLeftShift (iCode * ic) -{ - operand *left, *right, *result; - int size, offset; - char *l; - symbol *tlbl, *tlbl1; - - D (emitcode (";", "genLeftShift ");); - - right = IC_RIGHT (ic); - left = IC_LEFT (ic); - result = IC_RESULT (ic); - - aopOp (right, ic, FALSE, FALSE); - - -#ifdef BETTER_LITERAL_SHIFT - /* if the shift count is known then do it - as efficiently as possible */ - if (AOP_TYPE (right) == AOP_LIT) - { - if (genLeftShiftLiteral (left, right, result, ic)) - { - return; - } - } -#endif - - /* shift count is unknown then we have to form - a loop get the loop count in B : Note: we take - only the lower order byte since shifting - more that 32 bits make no sense anyway, ( the - largest size of an object can be only 32 bits ) */ - - if (AOP_TYPE (right) == AOP_LIT) - { - /* Really should be handled by genLeftShiftLiteral, - * but since I'm too lazy to fix that today, at least we can make - * some small improvement. - */ - emitcode("mov", "b,#0x%02x", - ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1); - } - else - { - emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE)); - emitcode ("inc", "b"); - } - freeAsmop (right, NULL, ic, TRUE); - aopOp (left, ic, FALSE, FALSE); - aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR); - - /* now move the left to the result if they are not the - same */ - if (!sameRegs (AOP (left), AOP (result)) && - AOP_SIZE (result) > 1) - { - - size = AOP_SIZE (result); - offset = 0; - _startLazyDPSEvaluation (); - while (size--) - { - l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE); - if (*l == '@' && (IS_AOP_PREG (result))) - { - - emitcode ("mov", "a,%s", l); - aopPut (AOP (result), "a", offset); - } - else - aopPut (AOP (result), l, offset); - offset++; - } - _endLazyDPSEvaluation (); - } - - tlbl = newiTempLabel (NULL); - size = AOP_SIZE (result); - offset = 0; - tlbl1 = newiTempLabel (NULL); - - /* if it is only one byte then */ - if (size == 1) - { - symbol *tlbl1 = newiTempLabel (NULL); - - l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("sjmp", "%05d$", tlbl1->key + 100); - emitcode ("", "%05d$:", tlbl->key + 100); - emitcode ("add", "a,acc"); - emitcode ("", "%05d$:", tlbl1->key + 100); - emitcode ("djnz", "b,%05d$", tlbl->key + 100); - aopPut (AOP (result), "a", 0); - goto release; - } - - reAdjustPreg (AOP (result)); - - emitcode ("sjmp", "%05d$", tlbl1->key + 100); - emitcode ("", "%05d$:", tlbl->key + 100); - l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("add", "a,acc"); - aopPut (AOP (result), "a", offset++); - _startLazyDPSEvaluation (); - while (--size) - { - l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("rlc", "a"); - aopPut (AOP (result), "a", offset++); - } - _endLazyDPSEvaluation (); - reAdjustPreg (AOP (result)); - - emitcode ("", "%05d$:", tlbl1->key + 100); - emitcode ("djnz", "b,%05d$", tlbl->key + 100); -release: - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); -} - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* genrshOne - right shift a one byte quantity by known count */ -/*-----------------------------------------------------------------*/ -static void -genrshOne (operand * result, operand * left, - int shCount, int sign) -{ - D (emitcode (";", "genrshOne");); - shiftR1Left2Result (left, LSB, result, LSB, shCount, sign); -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* genrshTwo - right shift two bytes by known amount != 0 */ -/*-----------------------------------------------------------------*/ -static void -genrshTwo (operand * result, operand * left, - int shCount, int sign) -{ - D (emitcode (";", "genrshTwo");); - - /* if shCount >= 8 */ - if (shCount >= 8) - { - shCount -= 8; - _startLazyDPSEvaluation(); - if (shCount) - { - shiftR1Left2Result (left, MSB16, result, LSB, - shCount, sign); - } - else - { - movLeft2Result (left, MSB16, result, LSB, sign); - } - addSign (result, MSB16, sign); - _endLazyDPSEvaluation(); - } - - /* 1 <= shCount <= 7 */ - else - { - shiftR2Left2Result (left, LSB, result, LSB, shCount, sign); - } -} -#endif - -#if 0 -//REMOVE ME!!! -/*-----------------------------------------------------------------*/ -/* shiftRLong - shift right one long from left to result */ -/* offl = LSB or MSB16 */ -/*-----------------------------------------------------------------*/ -static void -shiftRLong (operand * left, int offl, - operand * result, int sign) -{ - 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 (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"); - - 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); - - if (offl == LSB) - { - MOVA (aopGet (AOP (left), LSB, FALSE, FALSE)); - emitcode ("rrc", "a"); - aopPut (AOP (result), "a", LSB); - } -} -#endif - -#if 0 -//REMOVE ME!!! -/*-----------------------------------------------------------------*/ -/* genrshFour - shift four byte by a known amount != 0 */ -/*-----------------------------------------------------------------*/ -static void -genrshFour (operand * result, operand * left, - int shCount, int sign) -{ - D (emitcode (";", "genrshFour"); - ); - - /* if shifting more that 3 bytes */ - if (shCount >= 24) - { - shCount -= 24; - if (shCount) - shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign); - else - movLeft2Result (left, MSB32, result, LSB, sign); - addSign (result, MSB16, sign); - } - else if (shCount >= 16) - { - shCount -= 16; - if (shCount) - shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign); - else - { - movLeft2Result (left, MSB24, result, LSB, 0); - movLeft2Result (left, MSB32, result, MSB16, sign); - } - addSign (result, MSB24, sign); - } - else if (shCount >= 8) - { - shCount -= 8; - if (shCount == 1) - shiftRLong (left, MSB16, result, sign); - else if (shCount == 0) - { - movLeft2Result (left, MSB16, result, LSB, 0); - movLeft2Result (left, MSB24, result, MSB16, 0); - movLeft2Result (left, MSB32, result, MSB24, sign); - addSign (result, MSB32, sign); - } - else - { - shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0); - shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount); - /* the last shift is signed */ - shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign); - addSign (result, MSB32, sign); - } - } - else - { /* 1 <= shCount <= 7 */ - if (shCount <= 2) - { - shiftRLong (left, LSB, result, sign); - if (shCount == 2) - shiftRLong (result, LSB, result, sign); - } - else - { - shiftR2Left2Result (left, LSB, result, LSB, shCount, 0); - shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount); - shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign); - } - } -} -#endif - -#ifdef BETTER_LITERAL_SHIFT -/*-----------------------------------------------------------------*/ -/* genRightShiftLiteral - right shifting by known count */ -/*-----------------------------------------------------------------*/ -static bool -genRightShiftLiteral (operand * left, - operand * right, - operand * result, - iCode * ic, - int sign) -{ - int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit); - int size; - - size = getSize (operandType (result)); - - D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size);); - - /* We only handle certain easy cases so far. */ - if ((shCount != 0) - && (shCount < (size * 8)) - && (size != 1) - && (size != 2)) - { - D(emitcode (";", "genRightShiftLiteral wimping out");); - return FALSE; - } - - freeAsmop (right, NULL, ic, TRUE); - - aopOp (left, ic, FALSE, FALSE); - aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR); - -#if VIEW_SIZE - emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result), - AOP_SIZE (left)); -#endif - - /* test the LEFT size !!! */ - - /* I suppose that the left size >= result size */ - if (shCount == 0) - { - size = getDataSize (result); - _startLazyDPSEvaluation(); - while (size--) - { - movLeft2Result (left, size, result, size, 0); - } - _endLazyDPSEvaluation(); - } - else if (shCount >= (size * 8)) - { - if (sign) - { - /* get sign in acc.7 */ - MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, TRUE)); - } - addSign (result, LSB, sign); - } - else - { - switch (size) - { - case 1: - genrshOne (result, left, shCount, sign); - break; - - case 2: - genrshTwo (result, left, shCount, sign); - break; -#if 0 - case 4: - genrshFour (result, left, shCount, sign); - break; -#endif - default: - break; - } - - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); - } - return TRUE; -} -#endif - -/*-----------------------------------------------------------------*/ -/* genSignedRightShift - right shift of signed number */ -/*-----------------------------------------------------------------*/ -static void -genSignedRightShift (iCode * ic) -{ - operand *right, *left, *result; - int size, offset; - char *l; - symbol *tlbl, *tlbl1; - - D (emitcode (";", "genSignedRightShift ");); - - /* we do it the hard way put the shift count in b - and loop thru preserving the sign */ - - right = IC_RIGHT (ic); - left = IC_LEFT (ic); - result = IC_RESULT (ic); - - aopOp (right, ic, FALSE, FALSE); - -#ifdef BETTER_LITERAL_SHIFT - if (AOP_TYPE (right) == AOP_LIT) - { - if (genRightShiftLiteral (left, right, result, ic, 1)) - { - return; - } - } -#endif - /* shift count is unknown then we have to form - a loop get the loop count in B : Note: we take - only the lower order byte since shifting - more that 32 bits make no sense anyway, ( the - largest size of an object can be only 32 bits ) */ - - if (AOP_TYPE (right) == AOP_LIT) - { - /* Really should be handled by genRightShiftLiteral, - * but since I'm too lazy to fix that today, at least we can make - * some small improvement. - */ - emitcode("mov", "b,#0x%02x", - ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1); - } - else - { - emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE)); - emitcode ("inc", "b"); - } - freeAsmop (right, NULL, ic, TRUE); - aopOp (left, ic, FALSE, FALSE); - aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR); - - /* now move the left to the result if they are not the - same */ - if (!sameRegs (AOP (left), AOP (result)) && - AOP_SIZE (result) > 1) - { - - size = AOP_SIZE (result); - offset = 0; - _startLazyDPSEvaluation (); - while (size--) - { - l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE); - if (*l == '@' && IS_AOP_PREG (result)) - { - - emitcode ("mov", "a,%s", l); - aopPut (AOP (result), "a", offset); - } - else - aopPut (AOP (result), l, offset); - offset++; - } - _endLazyDPSEvaluation (); - } - - /* mov the highest order bit to OVR */ - tlbl = newiTempLabel (NULL); - tlbl1 = newiTempLabel (NULL); - - size = AOP_SIZE (result); - offset = size - 1; - emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE, FALSE)); - emitcode ("rlc", "a"); - emitcode ("mov", "ov,c"); - /* if it is only one byte then */ - if (size == 1) - { - l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("sjmp", "%05d$", tlbl1->key + 100); - emitcode ("", "%05d$:", tlbl->key + 100); - emitcode ("mov", "c,ov"); - emitcode ("rrc", "a"); - emitcode ("", "%05d$:", tlbl1->key + 100); - emitcode ("djnz", "b,%05d$", tlbl->key + 100); - aopPut (AOP (result), "a", 0); - goto release; - } - - reAdjustPreg (AOP (result)); - emitcode ("sjmp", "%05d$", tlbl1->key + 100); - emitcode ("", "%05d$:", tlbl->key + 100); - emitcode ("mov", "c,ov"); - _startLazyDPSEvaluation (); - while (size--) - { - l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("rrc", "a"); - aopPut (AOP (result), "a", offset--); - } - _endLazyDPSEvaluation (); - reAdjustPreg (AOP (result)); - emitcode ("", "%05d$:", tlbl1->key + 100); - emitcode ("djnz", "b,%05d$", tlbl->key + 100); - -release: - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genRightShift - generate code for right shifting */ -/*-----------------------------------------------------------------*/ -static void -genRightShift (iCode * ic) -{ - operand *right, *left, *result; - sym_link *retype; - int size, offset; - char *l; - symbol *tlbl, *tlbl1; - - D (emitcode (";", "genRightShift ");); - - /* if signed then we do it the hard way preserve the - sign bit moving it inwards */ - retype = getSpec (operandType (IC_RESULT (ic))); - - if (!SPEC_USIGN (retype)) - { - genSignedRightShift (ic); - return; - } - - /* signed & unsigned types are treated the same : i.e. the - signed is NOT propagated inwards : quoting from the - ANSI - standard : "for E1 >> E2, is equivalent to division - by 2**E2 if unsigned or if it has a non-negative value, - otherwise the result is implementation defined ", MY definition - is that the sign does not get propagated */ - - right = IC_RIGHT (ic); - left = IC_LEFT (ic); - result = IC_RESULT (ic); - - aopOp (right, ic, FALSE, FALSE); - -#ifdef BETTER_LITERAL_SHIFT - /* if the shift count is known then do it - as efficiently as possible */ - if (AOP_TYPE (right) == AOP_LIT) - { - if (genRightShiftLiteral (left, right, result, ic, 0)) - { - return; - } - } -#endif - - /* shift count is unknown then we have to form - a loop get the loop count in B : Note: we take - only the lower order byte since shifting - more that 32 bits make no sense anyway, ( the - largest size of an object can be only 32 bits ) */ - - if (AOP_TYPE (right) == AOP_LIT) - { - /* Really should be handled by genRightShiftLiteral, - * but since I'm too lazy to fix that today, at least we can make - * some small improvement. - */ - emitcode("mov", "b,#0x%02x", - ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1); - } - else - { - emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE)); - emitcode ("inc", "b"); - } - freeAsmop (right, NULL, ic, TRUE); - aopOp (left, ic, FALSE, FALSE); - aopOp (result, ic, FALSE, AOP_TYPE (left) == AOP_DPTR); - - /* now move the left to the result if they are not the - same */ - if (!sameRegs (AOP (left), AOP (result)) && - AOP_SIZE (result) > 1) - { - - size = AOP_SIZE (result); - offset = 0; - _startLazyDPSEvaluation (); - while (size--) - { - l = aopGet (AOP (left), offset, FALSE, TRUE, FALSE); - if (*l == '@' && IS_AOP_PREG (result)) - { - - emitcode ("mov", "a,%s", l); - aopPut (AOP (result), "a", offset); - } - else - aopPut (AOP (result), l, offset); - offset++; - } - _endLazyDPSEvaluation (); - } - - tlbl = newiTempLabel (NULL); - tlbl1 = newiTempLabel (NULL); - size = AOP_SIZE (result); - offset = size - 1; - - /* if it is only one byte then */ - if (size == 1) - { - l = aopGet (AOP (left), 0, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("sjmp", "%05d$", tlbl1->key + 100); - emitcode ("", "%05d$:", tlbl->key + 100); - CLRC; - emitcode ("rrc", "a"); - emitcode ("", "%05d$:", tlbl1->key + 100); - emitcode ("djnz", "b,%05d$", tlbl->key + 100); - aopPut (AOP (result), "a", 0); - goto release; - } - - reAdjustPreg (AOP (result)); - emitcode ("sjmp", "%05d$", tlbl1->key + 100); - emitcode ("", "%05d$:", tlbl->key + 100); - CLRC; - _startLazyDPSEvaluation (); - while (size--) - { - l = aopGet (AOP (result), offset, FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("rrc", "a"); - aopPut (AOP (result), "a", offset--); - } - _endLazyDPSEvaluation (); - reAdjustPreg (AOP (result)); - - emitcode ("", "%05d$:", tlbl1->key + 100); - emitcode ("djnz", "b,%05d$", tlbl->key + 100); - -release: - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genUnpackBits - generates code for unpacking bits */ -/*-----------------------------------------------------------------*/ -static void -genUnpackBits (operand * result, char *rname, int ptype) -{ - int shCnt; - int rlen = 0; - sym_link *etype; - int offset = 0; - - D (emitcode (";", "genUnpackBits "); - ); - - etype = getSpec (operandType (result)); - - /* read the first byte */ - switch (ptype) - { - - case POINTER: - case IPOINTER: - emitcode ("mov", "a,@%s", rname); - break; - - case PPOINTER: - emitcode ("movx", "a,@%s", rname); - break; - - case FPOINTER: - emitcode ("movx", "a,@dptr"); - break; - - case CPOINTER: - emitcode ("clr", "a"); - emitcode ("movc", "a,@a+dptr"); - break; - - case GPOINTER: - emitcode ("lcall", "__gptrget"); - 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)) || - (SPEC_BLEN (etype) <= 8)) - { - - /* shift right acc */ - AccRsh (shCnt); - - emitcode ("anl", "a,#0x%02x", - ((unsigned char) -1) >> (8 - SPEC_BLEN (etype))); - aopPut (AOP (result), "a", offset); - return; - } - - /* 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; - - case GPOINTER: - emitcode ("inc", "dptr"); - emitcode ("lcall", "__gptrget"); - break; - } - - rlen -= 8; - /* if we are done */ - if (rlen < 8) - break; - - aopPut (AOP (result), "a", offset++); - - } - - if (rlen) - { - emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (rlen)); - aopPut (AOP (result), "a", offset); - } - - return; -} - - -/*-----------------------------------------------------------------*/ -/* genDataPointerGet - generates code when ptr offset is known */ -/*-----------------------------------------------------------------*/ -static void -genDataPointerGet (operand * left, - operand * result, - iCode * ic) -{ - char *l; - char buffer[256]; - int size, offset = 0; - aopOp (result, ic, TRUE, FALSE); - - /* get the string representation of the name */ - l = aopGet (AOP (left), 0, FALSE, TRUE, FALSE); - size = AOP_SIZE (result); - _startLazyDPSEvaluation (); - while (size--) - { - if (offset) - sprintf (buffer, "(%s + %d)", l + 1, offset); - else - sprintf (buffer, "%s", l + 1); - aopPut (AOP (result), buffer, offset++); - } - _endLazyDPSEvaluation (); - - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genNearPointerGet - emitcode for near pointer fetch */ -/*-----------------------------------------------------------------*/ -static void -genNearPointerGet (operand * left, - operand * result, - iCode * ic, - iCode *pi) -{ - asmop *aop = NULL; - regs *preg = NULL; - char *rname; - sym_link *rtype, *retype, *letype; - sym_link *ltype = operandType (left); - char buffer[80]; - - rtype = operandType (result); - retype = getSpec (rtype); - letype = getSpec (ltype); - - aopOp (left, ic, FALSE, FALSE); - - /* if left is rematerialisable and - result is not bit 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) && - DCL_TYPE (ltype) == POINTER) - { - genDataPointerGet (left, result, ic); - return; - } - - /* if the value is already in a pointer register - then don't need anything more */ - if (!AOP_INPREG (AOP (left))) - { - /* otherwise get a free pointer register */ - aop = newAsmop (0); - preg = getFreePtr (ic, &aop, FALSE); - emitcode ("mov", "%s,%s", - preg->name, - aopGet (AOP (left), 0, FALSE, TRUE, FALSE)); - rname = preg->name; - } - else - rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE); - - freeAsmop (left, NULL, ic, TRUE); - aopOp (result, ic, FALSE, FALSE); - - /* if bitfield then unpack the bits */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) - genUnpackBits (result, rname, POINTER); - else - { - /* we have can just get the values */ - int size = AOP_SIZE (result); - int offset = 0; - - while (size--) - { - if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK) - { - - emitcode ("mov", "a,@%s", rname); - aopPut (AOP (result), "a", offset); - } - else - { - sprintf (buffer, "@%s", rname); - aopPut (AOP (result), buffer, offset); - } - offset++; - if (size || pi) - emitcode ("inc", "%s", rname); - } - } - - /* now some housekeeping stuff */ - if (aop) - { - /* we had to allocate for this iCode */ - if (pi) { /* post increment present */ - aopPut(AOP ( left ),rname,0); - } - freeAsmop (NULL, aop, ic, TRUE); - } - else - { - /* we did not allocate which means left - already in a pointer register, then - 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) && - !pi) - { - int size = AOP_SIZE (result) - 1; - while (size--) - emitcode ("dec", "%s", rname); - } - } - - /* done */ - freeAsmop (result, NULL, ic, TRUE); - if (pi) pi->generated = 1; -} - -/*-----------------------------------------------------------------*/ -/* genPagedPointerGet - emitcode for paged pointer fetch */ -/*-----------------------------------------------------------------*/ -static void -genPagedPointerGet (operand * left, - operand * result, - iCode * ic, - iCode * pi) -{ - asmop *aop = NULL; - regs *preg = NULL; - char *rname; - sym_link *rtype, *retype, *letype; - - rtype = operandType (result); - retype = getSpec (rtype); - letype = getSpec (operandType (left)); - aopOp (left, ic, FALSE, FALSE); - - /* if the value is already in a pointer register - then don't need anything more */ - if (!AOP_INPREG (AOP (left))) - { - /* otherwise get a free pointer register */ - aop = newAsmop (0); - preg = getFreePtr (ic, &aop, FALSE); - emitcode ("mov", "%s,%s", - preg->name, - aopGet (AOP (left), 0, FALSE, TRUE, FALSE)); - rname = preg->name; - } - else - rname = aopGet (AOP (left), 0, FALSE, FALSE, FALSE); - - freeAsmop (left, NULL, ic, TRUE); - aopOp (result, ic, FALSE, FALSE); - - /* if bitfield then unpack the bits */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) - genUnpackBits (result, rname, PPOINTER); - else - { - /* we have can just get the values */ - int size = AOP_SIZE (result); - int offset = 0; - - while (size--) - { - - emitcode ("movx", "a,@%s", rname); - aopPut (AOP (result), "a", offset); - - offset++; - - if (size || pi) - emitcode ("inc", "%s", rname); - } - } - - /* now some housekeeping stuff */ - if (aop) - { - /* we had to allocate for this iCode */ - if (pi) aopPut ( AOP (left), rname, 0); - freeAsmop (NULL, aop, ic, TRUE); - } - else - { - /* we did not allocate which means left - already in a pointer register, then - 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) && - !pi) - { - int size = AOP_SIZE (result) - 1; - while (size--) - emitcode ("dec", "%s", rname); - } - } - - /* done */ - freeAsmop (result, NULL, ic, TRUE); - if (pi) pi->generated = 1; -} - -/*-----------------------------------------------------------------*/ -/* genFarPointerGet - gget value from far space */ -/*-----------------------------------------------------------------*/ -static void -genFarPointerGet (operand * left, - operand * result, iCode * ic, iCode *pi) -{ - int size, offset, dopi=1; - sym_link *retype = getSpec (operandType (result)); - sym_link *letype = getSpec (operandType (left)); - D (emitcode (";", "genFarPointerGet"); - ); - - aopOp (left, ic, FALSE, FALSE); - - /* if the operand is already in dptr - then we do nothing else we move the value to dptr */ - if (AOP_TYPE (left) != AOP_STR) - { - /* if this is remateriazable */ - if (AOP_TYPE (left) == AOP_IMMD) - { - emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE)); - } - else - { - /* we need to get it byte by byte */ - _startLazyDPSEvaluation (); - if (AOP_TYPE (left) != AOP_DPTR) - { - emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE)); - emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE)); - if (options.model == MODEL_FLAT24) - emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE)); - } - else - { - /* We need to generate a load to DPTR indirect through DPTR. */ - D (emitcode (";", "genFarPointerGet -- indirection special case."); - ); - emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE)); - emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE)); - if (options.model == MODEL_FLAT24) - emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE)); - emitcode ("pop", "dph"); - emitcode ("pop", "dpl"); - dopi =0; - } - _endLazyDPSEvaluation (); - } - } - /* so dptr know contains the address */ - aopOp (result, ic, FALSE, TRUE); - - /* if bit then unpack */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) - genUnpackBits (result, "dptr", FPOINTER); - else - { - size = AOP_SIZE (result); - offset = 0; - - _startLazyDPSEvaluation (); - while (size--) - { - - genSetDPTR (0); - _flushLazyDPS (); - - emitcode ("movx", "a,@dptr"); - if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD)) - emitcode ("inc", "dptr"); - - aopPut (AOP (result), "a", offset++); - } - _endLazyDPSEvaluation (); - } - if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) { - aopPut ( AOP (left), "dpl", 0); - aopPut ( AOP (left), "dph", 1); - if (options.model == MODEL_FLAT24) - aopPut ( AOP (left), "dpx", 2); - pi->generated = 1; - } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 && - (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) { - - size = AOP_SIZE (result) - 1; - while (size--) emitcode ("lcall","__decdptr"); - } - - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* emitcodePointerGet - gget value from code space */ -/*-----------------------------------------------------------------*/ -static void -emitcodePointerGet (operand * left, - operand * result, iCode * ic, iCode *pi) -{ - int size, offset, dopi=1; - sym_link *retype = getSpec (operandType (result)); - - aopOp (left, ic, FALSE, FALSE); - - /* if the operand is already in dptr - then we do nothing else we move the value to dptr */ - if (AOP_TYPE (left) != AOP_STR) - { - /* if this is remateriazable */ - if (AOP_TYPE (left) == AOP_IMMD) - { - emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE)); - } - else - { /* we need to get it byte by byte */ - _startLazyDPSEvaluation (); - if (AOP_TYPE (left) != AOP_DPTR) - { - emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE)); - emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE)); - if (options.model == MODEL_FLAT24) - emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE)); - } - else - { - /* We need to generate a load to DPTR indirect through DPTR. */ - D (emitcode (";", "gencodePointerGet -- indirection special case."); - ); - emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, TRUE)); - emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, TRUE)); - if (options.model == MODEL_FLAT24) - emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE)); - emitcode ("pop", "dph"); - emitcode ("pop", "dpl"); - dopi=0; - } - _endLazyDPSEvaluation (); - } - } - /* so dptr know contains the address */ - aopOp (result, ic, FALSE, TRUE); - - /* if bit then unpack */ - if (IS_BITVAR (retype)) - genUnpackBits (result, "dptr", CPOINTER); - else - { - size = AOP_SIZE (result); - offset = 0; - - _startLazyDPSEvaluation (); - while (size--) - { - genSetDPTR (0); - _flushLazyDPS (); - - emitcode ("clr", "a"); - emitcode ("movc", "a,@a+dptr"); - if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD)) - emitcode ("inc", "dptr"); - aopPut (AOP (result), "a", offset++); - } - _endLazyDPSEvaluation (); - } - if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) { - aopPut ( AOP (left), "dpl", 0); - aopPut ( AOP (left), "dph", 1); - if (options.model == MODEL_FLAT24) - aopPut ( AOP (left), "dpx", 2); - pi->generated = 1; - } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 && - (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) { - - size = AOP_SIZE (result) - 1; - while (size--) emitcode ("lcall","__decdptr"); - } - - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genGenPointerGet - gget value from generic pointer space */ -/*-----------------------------------------------------------------*/ -static void -genGenPointerGet (operand * left, - operand * result, iCode * ic, iCode * pi) -{ - int size, offset; - sym_link *retype = getSpec (operandType (result)); - sym_link *letype = getSpec (operandType (left)); - - D (emitcode (";", "genGenPointerGet "); ); - - aopOp (left, ic, FALSE, (OP_SYMBOL(left)->ruonly ? FALSE : TRUE)); - - /* if the operand is already in dptr - then we do nothing else we move the value to dptr */ - if (AOP_TYPE (left) != AOP_STR) - { - /* if this is remateriazable */ - if (AOP_TYPE (left) == AOP_IMMD) - { - emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, FALSE)); - if (AOP(left)->aopu.aop_immd.from_cast_remat) - emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, FALSE)); - else - emitcode ("mov", "b,#%d", pointerCode (retype)); - } - else - { /* we need to get it byte by byte */ - _startLazyDPSEvaluation (); - if (AOP(left)->type==AOP_DPTR2) { - char *l; - l=aopGet(AOP(left),0,FALSE,FALSE,TRUE); - genSetDPTR(0); - _flushLazyDPS(); - emitcode ("mov", "dpl,%s", l); - l=aopGet(AOP(left),1,FALSE,FALSE,TRUE); - genSetDPTR(0); - _flushLazyDPS(); - emitcode ("mov", "dph,%s", l); - if (options.model == MODEL_FLAT24) { - l=aopGet(AOP(left),2,FALSE,FALSE,TRUE); - genSetDPTR(0); - _flushLazyDPS(); - emitcode ("mov", "dpx,%s", l); - emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE)); - } else { - emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE)); - } - } else { - emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,TRUE)); - emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,TRUE)); - if (options.model == MODEL_FLAT24) { - emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE)); - emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,TRUE)); - } else { - emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,TRUE)); - } - } - _endLazyDPSEvaluation (); - } - } - /* so dptr know contains the address */ - aopOp (result, ic, FALSE, TRUE); - - /* if bit then unpack */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) - genUnpackBits (result, "dptr", GPOINTER); - else - { - size = AOP_SIZE (result); - offset = 0; - - while (size--) - { - emitcode ("lcall", "__gptrget"); - aopPut (AOP (result), "a", offset++); - if (size || (pi && AOP_TYPE (left) != AOP_IMMD)) - emitcode ("inc", "dptr"); - } - } - - if (pi && AOP_TYPE (left) != AOP_IMMD) { - aopPut ( AOP (left), "dpl", 0); - aopPut ( AOP (left), "dph", 1); - if (options.model == MODEL_FLAT24) { - aopPut ( AOP (left), "dpx", 2); - aopPut ( AOP (left), "b", 3); - } else aopPut ( AOP (left), "b", 2); - pi->generated = 1; - } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 && - (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) { - - size = AOP_SIZE (result) - 1; - while (size--) emitcode ("lcall","__decdptr"); - } - - freeAsmop (left, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genPointerGet - generate code for pointer get */ -/*-----------------------------------------------------------------*/ -static void -genPointerGet (iCode * ic, iCode *pi) -{ - operand *left, *result; - sym_link *type, *etype; - int p_type; - - D (emitcode (";", "genPointerGet "); - ); - - left = IC_LEFT (ic); - result = IC_RESULT (ic); - - /* depending on the type of pointer we need to - move it to the correct pointer register */ - type = operandType (left); - etype = getSpec (type); - /* if left is of type of pointer then it is simple */ - if (IS_PTR (type) && !IS_FUNC (type->next)) - p_type = DCL_TYPE (type); - else - { - /* we have to go by the storage class */ - p_type = PTR_TYPE (SPEC_OCLS (etype)); - } - /* special case when cast remat */ - if (p_type == GPOINTER && OP_SYMBOL(left)->remat && - IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) { - left = IC_RIGHT(OP_SYMBOL(left)->rematiCode); - type = type = operandType (left); - p_type = DCL_TYPE (type); - } - /* now that we have the pointer type we assign - the pointer values */ - switch (p_type) - { - - case POINTER: - case IPOINTER: - genNearPointerGet (left, result, ic, pi); - break; - - case PPOINTER: - genPagedPointerGet (left, result, ic, pi); - break; - - case FPOINTER: - genFarPointerGet (left, result, ic, pi); - break; - - case CPOINTER: - emitcodePointerGet (left, result, ic, pi); - break; - - case GPOINTER: - genGenPointerGet (left, result, ic, pi); - break; - } - -} - -/*-----------------------------------------------------------------*/ -/* genPackBits - generates code for packed bit storage */ -/*-----------------------------------------------------------------*/ -static void -genPackBits (sym_link * etype, - operand * right, - char *rname, int p_type) -{ - int shCount = 0; - int offset = 0; - int rLen = 0; - int blen, bstr; - char *l; - - blen = SPEC_BLEN (etype); - bstr = SPEC_BSTR (etype); - - l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE); - MOVA (l); - - /* if the bit lenth is less than or */ - /* it exactly fits a byte then */ - if (SPEC_BLEN (etype) <= 8) - { - shCount = SPEC_BSTR (etype); - - /* shift left acc */ - AccLsh (shCount); - - 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,#0x%02x", (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) - { - case POINTER: - emitcode ("mov", "@%s,a", rname); - break; - - case FPOINTER: - emitcode ("movx", "@dptr,a"); - break; - - case GPOINTER: - emitcode ("lcall", "__gptrput"); - break; - } - - /* 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) - { - - l = aopGet (AOP (right), offset++, FALSE, TRUE, FALSE); - - 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); - } - - MOVA (l); - - /* last last was not complete */ - 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,#0x%02x", ((unsigned char) -1 << rLen)); - emitcode ("orl", "a,b"); - } - - 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 */ -/*-----------------------------------------------------------------*/ -static void -genDataPointerSet (operand * right, - operand * result, - iCode * ic) -{ - int size, offset = 0; - char *l, buffer[256]; - - aopOp (right, ic, FALSE, FALSE); - - l = aopGet (AOP (result), 0, FALSE, TRUE, FALSE); - size = AOP_SIZE (right); - while (size--) - { - if (offset) - sprintf (buffer, "(%s + %d)", l + 1, offset); - else - sprintf (buffer, "%s", l + 1); - emitcode ("mov", "%s,%s", buffer, - aopGet (AOP (right), offset++, FALSE, FALSE, FALSE)); - } - - freeAsmop (right, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genNearPointerSet - emitcode for near pointer put */ -/*-----------------------------------------------------------------*/ -static void -genNearPointerSet (operand * right, - operand * result, - iCode * ic, - iCode * pi) -{ - asmop *aop = NULL; - regs *preg = NULL; - char *rname, *l; - sym_link *retype, *letype; - sym_link *ptype = operandType (result); - - retype = getSpec (operandType (right)); - letype = getSpec (ptype); - - aopOp (result, ic, FALSE, FALSE); - - /* if the result is rematerializable & - in data space & not a bit variable */ - if (AOP_TYPE (result) == AOP_IMMD && - DCL_TYPE (ptype) == POINTER && - !IS_BITVAR (retype) && - !IS_BITVAR (letype)) - { - 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, FALSE)); - rname = preg->name; - } - else - rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE); - - 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); - else - { - /* we have can just get the values */ - int size = AOP_SIZE (right); - int offset = 0; - - while (size--) - { - l = aopGet (AOP (right), offset, FALSE, TRUE, FALSE); - if (*l == '@') - { - MOVA (l); - emitcode ("mov", "@%s,a", rname); - } - else - emitcode ("mov", "@%s,%s", rname, l); - if (size || pi) - emitcode ("inc", "%s", rname); - offset++; - } - } - - /* now some housekeeping stuff */ - if (aop) - { - /* we had to allocate for this iCode */ - if (pi) aopPut (AOP (result),rname,0); - freeAsmop (NULL, aop, ic, TRUE); - } - else - { - /* we did not allocate which means left - already in a pointer register, then - 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) && - !pi) - { - int size = AOP_SIZE (right) - 1; - while (size--) - emitcode ("dec", "%s", rname); - } - } - - /* done */ - if (pi) pi->generated = 1; - freeAsmop (result, NULL, ic, TRUE); - freeAsmop (right, NULL, ic, TRUE); - - -} - -/*-----------------------------------------------------------------*/ -/* genPagedPointerSet - emitcode for Paged pointer put */ -/*-----------------------------------------------------------------*/ -static void -genPagedPointerSet (operand * right, - operand * result, - iCode * ic, - iCode *pi) -{ - asmop *aop = NULL; - regs *preg = NULL; - char *rname, *l; - sym_link *retype, *letype; - - retype = getSpec (operandType (right)); - letype = getSpec (operandType (result)); - - aopOp (result, ic, FALSE, FALSE); - - /* 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, FALSE)); - rname = preg->name; - } - else - rname = aopGet (AOP (result), 0, FALSE, FALSE, FALSE); - - 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); - else - { - /* we have can just get the values */ - int size = AOP_SIZE (right); - int offset = 0; - - while (size--) - { - l = aopGet (AOP (right), offset, FALSE, TRUE, TRUE); - - MOVA (l); - emitcode ("movx", "@%s,a", rname); - - if (size || pi) - emitcode ("inc", "%s", rname); - - offset++; - } - } - - /* now some housekeeping stuff */ - if (aop) - { - if (pi) aopPut (AOP (result),rname,0); - /* we had to allocate for this iCode */ - freeAsmop (NULL, aop, ic, TRUE); - } - else - { - /* we did not allocate which means left - already in a pointer register, then - 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) && - !pi) - { - int size = AOP_SIZE (right) - 1; - while (size--) - emitcode ("dec", "%s", rname); - } - } - - /* done */ - if (pi) pi->generated = 1; - freeAsmop (result, NULL, ic, TRUE); - freeAsmop (right, NULL, ic, TRUE); - - -} - -/*-----------------------------------------------------------------*/ -/* genFarPointerSet - set value from far space */ -/*-----------------------------------------------------------------*/ -static void -genFarPointerSet (operand * right, - operand * result, iCode * ic, iCode *pi) -{ - int size, offset, dopi=1; - sym_link *retype = getSpec (operandType (right)); - sym_link *letype = getSpec (operandType (result)); - - aopOp (result, ic, FALSE, FALSE); - - /* if the operand is already in dptr - then we do nothing else we move the value to dptr */ - if (AOP_TYPE (result) != AOP_STR) - { - /* if this is remateriazable */ - if (AOP_TYPE (result) == AOP_IMMD) - emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE)); - else - { - /* we need to get it byte by byte */ - _startLazyDPSEvaluation (); - if (AOP_TYPE (result) != AOP_DPTR) - { - emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE)); - emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE)); - if (options.model == MODEL_FLAT24) - emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE)); - } - else - { - /* We need to generate a load to DPTR indirect through DPTR. */ - D (emitcode (";", "genFarPointerSet -- indirection special case."); - ); - emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, TRUE)); - emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, TRUE)); - if (options.model == MODEL_FLAT24) - emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE)); - emitcode ("pop", "dph"); - emitcode ("pop", "dpl"); - dopi=0; - } - _endLazyDPSEvaluation (); - } - } - /* so dptr know contains the address */ - aopOp (right, ic, FALSE, TRUE); - - /* if bit then unpack */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) - genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER); - else - { - size = AOP_SIZE (right); - offset = 0; - - _startLazyDPSEvaluation (); - while (size--) - { - char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE); - MOVA (l); - - genSetDPTR (0); - _flushLazyDPS (); - - emitcode ("movx", "@dptr,a"); - if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD)) - emitcode ("inc", "dptr"); - } - _endLazyDPSEvaluation (); - } - - if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) { - aopPut (AOP(result),"dpl",0); - aopPut (AOP(result),"dph",1); - if (options.model == MODEL_FLAT24) - aopPut (AOP(result),"dpx",2); - pi->generated=1; - } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 && - (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) { - - size = AOP_SIZE (right) - 1; - while (size--) emitcode ("lcall","__decdptr"); - } - freeAsmop (result, NULL, ic, TRUE); - freeAsmop (right, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genGenPointerSet - set value from generic pointer space */ -/*-----------------------------------------------------------------*/ -static void -genGenPointerSet (operand * right, - operand * result, iCode * ic, iCode *pi) -{ - int size, offset; - sym_link *retype = getSpec (operandType (right)); - sym_link *letype = getSpec (operandType (result)); - - aopOp (result, ic, FALSE, OP_SYMBOL(result)->ruonly ? FALSE : TRUE); - - /* if the operand is already in dptr - then we do nothing else we move the value to dptr */ - if (AOP_TYPE (result) != AOP_STR) - { - _startLazyDPSEvaluation (); - /* if this is remateriazable */ - if (AOP_TYPE (result) == AOP_IMMD) - { - emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, FALSE)); - if (AOP(result)->aopu.aop_immd.from_cast_remat) - emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, FALSE)); - else - emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, FALSE)); - } - else - { /* we need to get it byte by byte */ - emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, TRUE)); - emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, TRUE)); - if (options.model == MODEL_FLAT24) { - emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE)); - emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, TRUE)); - } else { - emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, TRUE)); - } - } - _endLazyDPSEvaluation (); - } - /* so dptr know contains the address */ - aopOp (right, ic, FALSE, TRUE); - - /* if bit then unpack */ - if (IS_BITVAR (retype) || IS_BITVAR (letype)) - genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER); - else - { - size = AOP_SIZE (right); - offset = 0; - - _startLazyDPSEvaluation (); - while (size--) - { - char *l = aopGet (AOP (right), offset++, FALSE, FALSE, TRUE); - MOVA (l); - - genSetDPTR (0); - _flushLazyDPS (); - - emitcode ("lcall", "__gptrput"); - if (size || (pi && AOP_TYPE (result) != AOP_IMMD)) - emitcode ("inc", "dptr"); - } - _endLazyDPSEvaluation (); - } - - if (pi && AOP_TYPE (result) != AOP_IMMD) { - aopPut (AOP(result),"dpl",0); - aopPut (AOP(result),"dph",1); - if (options.model == MODEL_FLAT24) { - aopPut (AOP(result),"dpx",2); - aopPut (AOP(result),"b",3); - } else { - aopPut (AOP(result),"b",2); - } - pi->generated=1; - } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 && - (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) { - - size = AOP_SIZE (right) - 1; - while (size--) emitcode ("lcall","__decdptr"); - } - freeAsmop (result, NULL, ic, TRUE); - freeAsmop (right, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genPointerSet - stores the value into a pointer location */ -/*-----------------------------------------------------------------*/ -static void -genPointerSet (iCode * ic, iCode *pi) -{ - operand *right, *result; - sym_link *type, *etype; - int p_type; - - D (emitcode (";", "genPointerSet "); - ); - - right = IC_RIGHT (ic); - result = IC_RESULT (ic); - - /* depending on the type of pointer we need to - move it to the correct pointer register */ - type = operandType (result); - etype = getSpec (type); - /* if left is of type of pointer then it is simple */ - if (IS_PTR (type) && !IS_FUNC (type->next)) - { - p_type = DCL_TYPE (type); - } - else - { - /* we have to go by the storage class */ - p_type = PTR_TYPE (SPEC_OCLS (etype)); - } - /* special case when cast remat */ - if (p_type == GPOINTER && OP_SYMBOL(result)->remat && - IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) { - result = IC_RIGHT(OP_SYMBOL(result)->rematiCode); - type = type = operandType (result); - p_type = DCL_TYPE (type); - } - - /* now that we have the pointer type we assign - the pointer values */ - switch (p_type) - { - - case POINTER: - case IPOINTER: - genNearPointerSet (right, result, ic, pi); - break; - - case PPOINTER: - genPagedPointerSet (right, result, ic, pi); - break; - - case FPOINTER: - genFarPointerSet (right, result, ic, pi); - break; - - case GPOINTER: - genGenPointerSet (right, result, ic, pi); - break; - } - -} - -/*-----------------------------------------------------------------*/ -/* genIfx - generate code for Ifx statement */ -/*-----------------------------------------------------------------*/ -static void -genIfx (iCode * ic, iCode * popIc) -{ - operand *cond = IC_COND (ic); - int isbit = 0; - - D (emitcode (";", "genIfx ");); - - aopOp (cond, ic, FALSE, FALSE); - - /* get the value into acc */ - if (AOP_TYPE (cond) != AOP_CRY) - toBoolean (cond); - else - isbit = 1; - /* the result is now in the accumulator */ - freeAsmop (cond, NULL, ic, TRUE); - - /* if there was something to be popped then do it */ - if (popIc) - genIpop (popIc); - - /* if the condition is a bit variable */ - if (isbit && IS_ITEMP (cond) && - SPIL_LOC (cond)) - genIfxJump (ic, SPIL_LOC (cond)->rname); - else if (isbit && !IS_ITEMP (cond)) - genIfxJump (ic, OP_SYMBOL (cond)->rname); - else - genIfxJump (ic, "a"); - - ic->generated = 1; -} - -/*-----------------------------------------------------------------*/ -/* genAddrOf - generates code for address of */ -/*-----------------------------------------------------------------*/ -static void -genAddrOf (iCode * ic) -{ - symbol *sym = OP_SYMBOL (IC_LEFT (ic)); - int size, offset; - - D (emitcode (";", "genAddrOf "); - ); - - aopOp (IC_RESULT (ic), ic, FALSE, FALSE); - - /* if the operand is on the stack then we - need to get the stack offset of this - variable */ - if (sym->onStack) { - - /* if 10 bit stack */ - if (options.stack10bit) { - /* if it has an offset then we need to compute it */ - emitcode ("subb", "a,#0x%02x", - -((sym->stack < 0) ? - ((short) (sym->stack - _G.nRegsSaved)) : - ((short) sym->stack)) & 0xff); - emitcode ("mov","b,a"); - emitcode ("mov","a,#0x%02x",(-((sym->stack < 0) ? - ((short) (sym->stack - _G.nRegsSaved)) : - ((short) sym->stack)) >> 8) & 0xff); - if (sym->stack) { - emitcode ("mov", "a,_bpx"); - emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ? - ((char) (sym->stack - _G.nRegsSaved)) : - ((char) sym->stack )) & 0xff); - emitcode ("mov", "b,a"); - emitcode ("mov", "a,_bpx+1"); - emitcode ("addc","a,#0x%02x", (((sym->stack < 0) ? - ((short) (sym->stack - _G.nRegsSaved)) : - ((short) sym->stack )) >> 8) & 0xff); - aopPut (AOP (IC_RESULT (ic)), "b", 0); - aopPut (AOP (IC_RESULT (ic)), "a", 1); - aopPut (AOP (IC_RESULT (ic)), "#0x40", 2); - } else { - /* we can just move _bp */ - aopPut (AOP (IC_RESULT (ic)), "_bpx", 0); - aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1); - aopPut (AOP (IC_RESULT (ic)), "#0x40", 2); - } - } else { - /* if it has an offset then we need to compute it */ - if (sym->stack) { - emitcode ("mov", "a,_bp"); - emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff)); - aopPut (AOP (IC_RESULT (ic)), "a", 0); - } else { - /* we can just move _bp */ - aopPut (AOP (IC_RESULT (ic)), "_bp", 0); - } - /* 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--) { - aopPut (AOP (IC_RESULT (ic)), zero, offset++); - } - } - goto release; - } - - /* object not on stack then we need the name */ - size = AOP_SIZE (IC_RESULT (ic)); - offset = 0; - - while (size--) - { - char s[SDCC_NAME_MAX]; - if (offset) - sprintf (s, "#(%s >> %d)", - sym->rname, - offset * 8); - else - sprintf (s, "#%s", sym->rname); - aopPut (AOP (IC_RESULT (ic)), s, offset++); - } - -release: - freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); - -} - -/*-----------------------------------------------------------------*/ -/* genArrayInit - generates code for address of */ -/*-----------------------------------------------------------------*/ -static void -genArrayInit (iCode * ic) -{ - literalList *iLoop; - int ix, count; - int elementSize = 0, eIndex; - unsigned val, lastVal; - sym_link *type; - operand *left=IC_LEFT(ic); - - D (emitcode (";", "genArrayInit ");); - - aopOp (IC_LEFT(ic), ic, FALSE, FALSE); - - if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) - { - // Load immediate value into DPTR. - emitcode("mov", "dptr, %s", - aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, TRUE)); - } - else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR) - { -#if 0 - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "Unexpected operand to genArrayInit.\n"); - exit(1); -#else - // a regression because of SDCCcse.c:1.52 - emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, TRUE)); - emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, TRUE)); - if (options.model == MODEL_FLAT24) - emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, TRUE)); -#endif - } - - type = operandType(IC_LEFT(ic)); - - if (type && type->next) - { - elementSize = getSize(type->next); - } - else - { - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "can't determine element size in genArrayInit.\n"); - exit(1); - } - - iLoop = IC_ARRAYILIST(ic); - lastVal = 0xffff; - - while (iLoop) - { - bool firstpass = TRUE; - - emitcode(";", "store %d x 0x%x to DPTR (element size %d)", - iLoop->count, (int)iLoop->literalValue, elementSize); - - ix = iLoop->count; - - while (ix) - { - symbol *tlbl = NULL; - - count = ix > 256 ? 256 : ix; - - if (count > 1) - { - tlbl = newiTempLabel (NULL); - if (firstpass || (count & 0xff)) - { - emitcode("mov", "b, #0x%x", count & 0xff); - } - - emitcode ("", "%05d$:", tlbl->key + 100); - } - - firstpass = FALSE; - - for (eIndex = 0; eIndex < elementSize; eIndex++) - { - val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff; - if (val != lastVal) - { - emitcode("mov", "a, #0x%x", val); - lastVal = val; - } - - emitcode("movx", "@dptr, a"); - emitcode("inc", "dptr"); - } - - if (count > 1) - { - emitcode("djnz", "b, %05d$", tlbl->key + 100); - } - - ix -= count; - } - - iLoop = iLoop->next; - } - - freeAsmop (IC_LEFT(ic), NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genFarFarAssign - assignment when both are in far space */ -/*-----------------------------------------------------------------*/ -static void -genFarFarAssign (operand * result, operand * right, iCode * ic) -{ - int size = AOP_SIZE (right); - int offset = 0; - symbol *rSym = NULL; - - if (size == 1) - { - /* quick & easy case. */ - D(emitcode(";","genFarFarAssign (1 byte case)");); - MOVA(aopGet(AOP(right), 0, FALSE, FALSE, TRUE)); - freeAsmop (right, NULL, ic, FALSE); - /* now assign DPTR to result */ - _G.accInUse++; - aopOp(result, ic, FALSE, FALSE); - _G.accInUse--; - aopPut(AOP(result), "a", 0); - freeAsmop(result, NULL, ic, FALSE); - return; - } - - /* See if we've got an underlying symbol to abuse. */ - if (IS_SYMOP(result) && OP_SYMBOL(result)) - { - if (IS_TRUE_SYMOP(result)) - { - rSym = OP_SYMBOL(result); - } - else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc) - { - rSym = OP_SYMBOL(result)->usl.spillLoc; - } - } - - if (size > 1 && rSym && rSym->rname && !rSym->onStack) - { - /* We can use the '390 auto-toggle feature to good effect here. */ - - D(emitcode(";","genFarFarAssign (390 auto-toggle fun)");); - emitcode("mov", "dps, #0x21"); /* Select DPTR2 & auto-toggle. */ - emitcode ("mov", "dptr,#%s", rSym->rname); - /* DP2 = result, DP1 = right, DP1 is current. */ - while (size) - { - emitcode("movx", "a,@dptr"); - emitcode("movx", "@dptr,a"); - if (--size) - { - emitcode("inc", "dptr"); - emitcode("inc", "dptr"); - } - } - emitcode("mov", "dps, #0"); - freeAsmop (right, NULL, ic, FALSE); -#if 0 -some alternative code for processors without auto-toggle -no time to test now, so later well put in...kpb - D(emitcode(";","genFarFarAssign (dual-dptr fun)");); - emitcode("mov", "dps, #0x01"); /* Select DPTR2. */ - emitcode ("mov", "dptr,#%s", rSym->rname); - /* DP2 = result, DP1 = right, DP1 is current. */ - while (size) - { - --size; - emitcode("movx", "a,@dptr"); - if (size) - emitcode("inc", "dptr"); - emitcode("inc", "dps"); - emitcode("movx", "@dptr,a"); - if (size) - emitcode("inc", "dptr"); - emitcode("inc", "dps"); - } - emitcode("mov", "dps, #0"); - freeAsmop (right, NULL, ic, FALSE); -#endif - } - else - { - D (emitcode (";", "genFarFarAssign");); - aopOp (result, ic, TRUE, TRUE); - - _startLazyDPSEvaluation (); - - while (size--) - { - aopPut (AOP (result), - aopGet (AOP (right), offset, FALSE, FALSE, FALSE), offset); - offset++; - } - _endLazyDPSEvaluation (); - freeAsmop (result, NULL, ic, FALSE); - freeAsmop (right, NULL, ic, FALSE); - } -} - -/*-----------------------------------------------------------------*/ -/* genAssign - generate code for assignment */ -/*-----------------------------------------------------------------*/ -static void -genAssign (iCode * ic) -{ - operand *result, *right; - int size, offset; - unsigned long lit = 0L; - - D (emitcode (";", "genAssign "); - ); - - result = IC_RESULT (ic); - right = IC_RIGHT (ic); - - /* if they are the same */ - if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic))) - return; - - aopOp (right, ic, FALSE, FALSE); - - emitcode (";", "genAssign: resultIsFar = %s", - isOperandInFarSpace (result) ? - "TRUE" : "FALSE"); - - /* special case both in far space */ - if ((AOP_TYPE (right) == AOP_DPTR || - AOP_TYPE (right) == AOP_DPTR2) && - /* IS_TRUE_SYMOP(result) && */ - isOperandInFarSpace (result)) - { - genFarFarAssign (result, right, ic); - return; - } - - aopOp (result, ic, TRUE, FALSE); - - /* if they are the same registers */ - if (sameRegs (AOP (right), AOP (result))) - goto release; - - /* if the result is a bit */ - if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */ - { - /* if the right size is a literal then - we know what the value is */ - if (AOP_TYPE (right) == AOP_LIT) - { - if (((int) operandLitValue (right))) - aopPut (AOP (result), one, 0); - else - aopPut (AOP (result), zero, 0); - goto release; - } - - /* the right is also a bit variable */ - if (AOP_TYPE (right) == AOP_CRY) - { - emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir); - aopPut (AOP (result), "c", 0); - goto release; - } - - /* we need to or */ - toBoolean (right); - aopPut (AOP (result), "a", 0); - goto release; - } - - /* bit variables done */ - /* general case */ - size = AOP_SIZE (result); - offset = 0; - if (AOP_TYPE (right) == AOP_LIT) - lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit); - - if ((size > 1) && - (AOP_TYPE (result) != AOP_REG) && - (AOP_TYPE (right) == AOP_LIT) && - !IS_FLOAT (operandType (right))) - { - _startLazyDPSEvaluation (); - while (size && ((unsigned int) (lit >> (offset * 8)) != 0)) - { - aopPut (AOP (result), - aopGet (AOP (right), offset, FALSE, FALSE, TRUE), - offset); - offset++; - size--; - } - /* And now fill the rest with zeros. */ - if (size) - { - emitcode ("clr", "a"); - } - while (size--) - { - aopPut (AOP (result), "a", offset++); - } - _endLazyDPSEvaluation (); - } - else - { - _startLazyDPSEvaluation (); - while (size--) - { - aopPut (AOP (result), - aopGet (AOP (right), offset, FALSE, FALSE, FALSE), - offset); - offset++; - } - _endLazyDPSEvaluation (); - } - -release: - freeAsmop (right, NULL, ic, FALSE); - freeAsmop (result, NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genJumpTab - generates code for jump table */ -/*-----------------------------------------------------------------*/ -static void -genJumpTab (iCode * ic) -{ - symbol *jtab; - char *l; - - D (emitcode (";", "genJumpTab "); - ); - - aopOp (IC_JTCOND (ic), ic, FALSE, FALSE); - /* get the condition into accumulator */ - l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, TRUE); - MOVA (l); - /* multiply by four! */ - emitcode ("add", "a,acc"); - emitcode ("add", "a,acc"); - freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE); - - jtab = newiTempLabel (NULL); - emitcode ("mov", "dptr,#%05d$", jtab->key + 100); - emitcode ("jmp", "@a+dptr"); - emitcode ("", "%05d$:", jtab->key + 100); - /* now generate the jump labels */ - for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab; - jtab = setNextItem (IC_JTLABELS (ic))) - emitcode ("ljmp", "%05d$", jtab->key + 100); - -} - -/*-----------------------------------------------------------------*/ -/* genCast - gen code for casting */ -/*-----------------------------------------------------------------*/ -static void -genCast (iCode * ic) -{ - operand *result = IC_RESULT (ic); - sym_link *ctype = operandType (IC_LEFT (ic)); - sym_link *rtype = operandType (IC_RIGHT (ic)); - 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 (right, ic, FALSE, FALSE); - 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 the right size is a literal then - we know what the value is */ - if (AOP_TYPE (right) == AOP_LIT) - { - if (((int) operandLitValue (right))) - aopPut (AOP (result), one, 0); - else - aopPut (AOP (result), zero, 0); - - goto release; - } - - /* the right is also a bit variable */ - if (AOP_TYPE (right) == AOP_CRY) - { - emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir); - aopPut (AOP (result), "c", 0); - goto release; - } - - /* we need to or */ - toBoolean (right); - aopPut (AOP (result), "a", 0); - goto release; - } - - /* if they are the same size : or less */ - if (AOP_SIZE (result) <= AOP_SIZE (right)) - { - - /* if they are in the same place */ - if (sameRegs (AOP (right), AOP (result))) - goto release; - - /* if they in different places then copy */ - size = AOP_SIZE (result); - offset = 0; - _startLazyDPSEvaluation (); - while (size--) - { - aopPut (AOP (result), - aopGet (AOP (right), offset, FALSE, FALSE, FALSE), - offset); - offset++; - } - _endLazyDPSEvaluation (); - goto release; - } - - - /* if the result is of type pointer */ - if (IS_PTR (ctype)) - { - - int p_type; - sym_link *type = operandType (right); - - /* pointer to generic pointer */ - if (IS_GENPTR (ctype)) - { - char *l = zero; - - if (IS_PTR (type)) - { - p_type = DCL_TYPE (type); - } - else - { -#if OLD_CAST_BEHAVIOR - /* KV: we are converting a non-pointer type to - * a generic pointer. This (ifdef'd out) code - * says that the resulting generic pointer - * should have the same class as the storage - * location of the non-pointer variable. - * - * For example, converting an int (which happens - * to be stored in DATA space) to a pointer results - * in a DATA generic pointer; if the original int - * in XDATA space, so will be the resulting pointer. - * - * I don't like that behavior, and thus this change: - * all such conversions will be forced to XDATA and - * throw a warning. If you want some non-XDATA - * type, or you want to suppress the warning, you - * must go through an intermediate cast, like so: - * - * char _generic *gp = (char _xdata *)(intVar); - */ - sym_link *etype = getSpec (type); - - /* we have to go by the storage class */ - if (SPEC_OCLS (etype) != generic) - { - p_type = PTR_TYPE (SPEC_OCLS (etype)); - } - else -#endif - { - /* Converting unknown class (i.e. register variable) - * to generic pointer. This is not good, but - * we'll make a guess (and throw a warning). - */ - p_type = FPOINTER; - werror (W_INT_TO_GEN_PTR_CAST); - } - } - - /* the first two bytes are known */ - size = GPTRSIZE - 1; - offset = 0; - _startLazyDPSEvaluation (); - while (size--) - { - aopPut (AOP (result), - aopGet (AOP (right), offset, FALSE, FALSE, FALSE), - offset); - offset++; - } - _endLazyDPSEvaluation (); - - /* the last byte depending on type */ - switch (p_type) - { - case IPOINTER: - case POINTER: - l = zero; - break; - case FPOINTER: - l = one; - break; - case CPOINTER: - l = "#0x02"; - break; - case PPOINTER: - l = "#0x03"; - break; - - default: - /* this should never happen */ - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "got unknown pointer type"); - exit (1); - } - aopPut (AOP (result), l, GPTRSIZE - 1); - goto release; - } - - /* just copy the pointers */ - size = AOP_SIZE (result); - offset = 0; - _startLazyDPSEvaluation (); - while (size--) - { - aopPut (AOP (result), - aopGet (AOP (right), offset, FALSE, FALSE, FALSE), - offset); - offset++; - } - _endLazyDPSEvaluation (); - goto release; - } - - /* so we now know that the size of destination is greater - than the size of the source */ - /* we move to result for the size of source */ - size = AOP_SIZE (right); - offset = 0; - _startLazyDPSEvaluation (); - while (size--) - { - aopPut (AOP (result), - aopGet (AOP (right), offset, FALSE, FALSE, FALSE), - offset); - offset++; - } - _endLazyDPSEvaluation (); - - /* now depending on the sign of the source && destination */ - size = AOP_SIZE (result) - AOP_SIZE (right); - /* if unsigned or not an integral type */ - /* 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) - { - while (size--) - { - aopPut (AOP (result), zero, offset++); - } - } - else - { - /* we need to extend the sign :{ */ - char *l = aopGet (AOP (right), AOP_SIZE (right) - 1, - FALSE, FALSE, TRUE); - MOVA (l); - emitcode ("rlc", "a"); - emitcode ("subb", "a,acc"); - while (size--) - aopPut (AOP (result), "a", offset++); - } - - /* we are done hurray !!!! */ - -release: - freeAsmop (right, NULL, ic, TRUE); - freeAsmop (result, NULL, ic, TRUE); - -} - -/*-----------------------------------------------------------------*/ -/* genDjnz - generate decrement & jump if not zero instrucion */ -/*-----------------------------------------------------------------*/ -static int -genDjnz (iCode * ic, iCode * ifx) -{ - symbol *lbl, *lbl1; - if (!ifx) - return 0; - - /* if the if condition has a false label - then we cannot save */ - if (IC_FALSE (ifx)) - return 0; - - /* if the minus is not of the form - a = a - 1 */ - if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) || - !IS_OP_LITERAL (IC_RIGHT (ic))) - return 0; - - if (operandLitValue (IC_RIGHT (ic)) != 1) - return 0; - - /* if the size of this greater than one then no - saving */ - if (getSize (operandType (IC_RESULT (ic))) > 1) - return 0; - - /* otherwise we can save BIG */ - D(emitcode(";", "genDjnz");); - - lbl = newiTempLabel (NULL); - lbl1 = newiTempLabel (NULL); - - aopOp (IC_RESULT (ic), ic, FALSE, FALSE); - - 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, TRUE); - - 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, FALSE)); - emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, FALSE)); - emitcode ("jnz", "%05d$", lbl->key + 100); - } - else - { - emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, FALSE), - lbl->key + 100); - } - emitcode ("sjmp", "%05d$", lbl1->key + 100); - emitcode ("", "%05d$:", lbl->key + 100); - emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100); - emitcode ("", "%05d$:", lbl1->key + 100); - - freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); - ifx->generated = 1; - return 1; -} - -/*-----------------------------------------------------------------*/ -/* genReceive - generate code for a receive iCode */ -/*-----------------------------------------------------------------*/ -static void -genReceive (iCode * ic) -{ - - D (emitcode (";", "genReceive "); - ); - - if (isOperandInFarSpace (IC_RESULT (ic)) && - (OP_SYMBOL (IC_RESULT (ic))->isspilt || - IS_TRUE_SYMOP (IC_RESULT (ic)))) - { - int size = getSize (operandType (IC_RESULT (ic))); - int offset = fReturnSizeDS390 - size; - while (size--) - { - emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeDS390 - offset - 1], "a") ? - fReturn[fReturnSizeDS390 - offset - 1] : "acc")); - offset++; - } - aopOp (IC_RESULT (ic), ic, FALSE, FALSE); - size = AOP_SIZE (IC_RESULT (ic)); - offset = 0; - while (size--) - { - emitcode ("pop", "acc"); - aopPut (AOP (IC_RESULT (ic)), "a", offset++); - } - - } - else - { - _G.accInUse++; - aopOp (IC_RESULT (ic), ic, FALSE, FALSE); - _G.accInUse--; - assignResultValue (IC_RESULT (ic)); - } - - freeAsmop (IC_RESULT (ic), NULL, ic, TRUE); -} - -/*-----------------------------------------------------------------*/ -/* gen390Code - generate code for Dallas 390 based controllers */ -/*-----------------------------------------------------------------*/ -void -gen390Code (iCode * lic) -{ - iCode *ic; - int cln = 0; - - lineHead = lineCurr = NULL; - - if (options.model == MODEL_FLAT24) { - fReturnSizeDS390 = 5; - fReturn = fReturn24; - } else { - fReturnSizeDS390 = 4; - fReturn = fReturn16; - options.stack10bit=0; - } -#if 0 - //REMOVE ME!!! - /* print the allocation information */ - if (allocInfo) - printAllocInfo (currFunc, codeOutFile); -#endif - /* if debug information required */ - if (options.debug && currFunc) - { - cdbSymbol (currFunc, cdbFile, FALSE, TRUE); - _G.debugLine = 1; - if (IS_STATIC (currFunc->etype)) - emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name); - else - emitcode ("", "G$%s$0$0 ==.", currFunc->name); - _G.debugLine = 0; - } - /* stack pointer name */ - if (options.useXstack) - spname = "_spx"; - else - spname = "sp"; - - - for (ic = lic; ic; ic = ic->next) - { - - if (cln != ic->lineno) - { - if (options.debug) - { - _G.debugLine = 1; - emitcode ("", "C$%s$%d$%d$%d ==.", - FileBaseName (ic->filename), ic->lineno, - ic->level, ic->block); - _G.debugLine = 0; - } - emitcode (";", "%s %d", ic->filename, ic->lineno); - cln = ic->lineno; - } - /* if the result is marked as - spilt and rematerializable or code for - this has already been generated then - do nothing */ - if (resultRemat (ic) || ic->generated) - continue; - - /* depending on the operation */ - switch (ic->op) - { - case '!': - genNot (ic); - break; - - case '~': - genCpl (ic); - break; - - case UNARYMINUS: - genUminus (ic); - break; - - case IPUSH: - genIpush (ic); - break; - - case IPOP: - /* IPOP happens only when trying to restore a - spilt live range, if there is an ifx statement - following this pop then the if statement might - be using some of the registers being popped which - would destory the contents of the register so - we need to check for this condition and handle it */ - if (ic->next && - ic->next->op == IFX && - regsInCommon (IC_LEFT (ic), IC_COND (ic->next))) - genIfx (ic->next, ic); - else - genIpop (ic); - break; - - case CALL: - genCall (ic); - break; - - case PCALL: - genPcall (ic); - break; - - case FUNCTION: - genFunction (ic); - break; - - case ENDFUNCTION: - genEndFunction (ic); - break; - - case RETURN: - genRet (ic); - break; - - case LABEL: - genLabel (ic); - break; - - case GOTO: - genGoto (ic); - break; - - case '+': - genPlus (ic); - break; - - case '-': - if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic))) - genMinus (ic); - break; - - case '*': - genMult (ic); - break; - - case '/': - genDiv (ic); - break; - - case '%': - genMod (ic); - break; - - case '>': - genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case '<': - genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case LE_OP: - case GE_OP: - case NE_OP: - - /* note these two are xlated by algebraic equivalence - during parsing SDCC.y */ - werror (E_INTERNAL_ERROR, __FILE__, __LINE__, - "got '>=' or '<=' shouldn't have come here"); - break; - - case EQ_OP: - genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case AND_OP: - genAndOp (ic); - break; - - case OR_OP: - genOrOp (ic); - break; - - case '^': - genXor (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case '|': - genOr (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case BITWISEAND: - genAnd (ic, ifxForOp (IC_RESULT (ic), ic)); - break; - - case INLINEASM: - genInline (ic); - break; - - case RRC: - genRRC (ic); - break; - - case RLC: - genRLC (ic); - break; - - case GETHBIT: - genGetHbit (ic); - break; - - case LEFT_OP: - genLeftShift (ic); - break; - - case RIGHT_OP: - genRightShift (ic); - break; - - case GET_VALUE_AT_ADDRESS: - genPointerGet (ic,hasInc(IC_LEFT(ic),ic)); - break; - - case '=': - if (POINTER_SET (ic)) - genPointerSet (ic,hasInc(IC_RESULT(ic),ic)); - else - genAssign (ic); - break; - - case IFX: - genIfx (ic, NULL); - break; - - case ADDRESS_OF: - genAddrOf (ic); - break; - - case JUMPTABLE: - genJumpTab (ic); - break; - - case CAST: - genCast (ic); - break; - - case RECEIVE: - genReceive (ic); - break; - - case SEND: - addSet (&_G.sendSet, ic); - break; - - case ARRAYINIT: - genArrayInit(ic); - break; - - default: - ic = ic; - } - } - - - /* now we are ready to call the - peep hole optimizer */ - if (!options.nopeep) - peepHole (&lineHead); - - /* now do the actual printing */ - printLine (lineHead, codeOutFile); - return; -} -- 2.47.2