X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic16%2Fgen.c;h=fa1d7a014660d3255e42ada3791a871ae15c8aa0;hb=5a1d5e778e85664f4e6657019348b4756b16eacb;hp=6f7eb2511fded4d7daf5bf869ca2b301747ef2f1;hpb=193aa0c8689791ae7d723d428ebd84e3d06fe7fd;p=fw%2Fsdcc diff --git a/src/pic16/gen.c b/src/pic16/gen.c index 6f7eb251..fa1d7a01 100644 --- a/src/pic16/gen.c +++ b/src/pic16/gen.c @@ -8,6 +8,8 @@ PIC16 port - Martin Dubuc m.dubuc@rogers.com (2002) - Vangelis Rokas (2003-2006) Bug Fixes - Raphael Neider (2004,2005) + Bug Fixes - Borut Razem (2007) + Bug Fixes - Mauro Giachero (2008) 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 @@ -49,40 +51,16 @@ #include "main.h" #include "glue.h" -/* Set the following to 1 to enable the slower/bigger - * but more robust generic shifting routine (which also - * operates correctly with negative shift values). */ -#define USE_GENERIC_SIGNED_SHIFT 1 - -/* Set the following to 1 to enable the new - * stripped down genCmp version. - * This version should be easier to understand, - * more reliable and (sigh) slighly slower. */ -#define USE_SIMPLE_GENCMP 1 - /* The PIC port(s) do not need to distinguish between POINTER and FPOINTER. */ #define PIC_IS_DATA_PTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x)) #define PIC_IS_FARPTR(x) (IS_DATA_PTR(x) || IS_FARPTR(x)) #define PIC_IS_TAGGED(x) (IS_GENPTR(x) || IS_CODEPTR(x)) #define IS_DIRECT(op) ((AOP_TYPE(op) == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_DIR)) -/* If you change these, you also have to update the library files - * device/lib/pic16/libsdcc/gptr{get,put}{1,2,3,4}.c */ -#define GPTR_TAG_DATA 0x80 -#define GPTR_TAG_EEPROM 0x40 -#define GPTR_TAG_CODE 0x00 /* must be 0 becaue of UPPER(sym)==0 */ - /* Wrapper to execute `code' at most once. */ #define PERFORM_ONCE(id,code) do { static char id = 0; if (!id) { id = 1; code } } while (0) void pic16_genMult8X8_n (operand *, operand *,operand *); -#if 0 -extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *); -extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *); -void pic16_genMult16X16_16(operand *, operand *, operand *); -void pic16_genMult32X32_32(operand *, operand *, operand *); -#endif -pCode *pic16_AssembleLine(char *line, int peeps); extern void pic16_printpBlock(FILE *of, pBlock *pb); static asmop *newAsmop (short type); static pCodeOp *pic16_popRegFromString(char *str, int size, int offset, operand *op); @@ -90,17 +68,8 @@ extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...); static void mov2fp(pCodeOp *dst, asmop *src, int offset); static pCodeOp *pic16_popRegFromIdx(int rIdx); -//static int aopIdx (asmop *aop, int offset); - int pic16_labelOffset=0; extern int pic16_debug_verbose; -#if !(USE_GENERIC_SIGNED_SHIFT) -static int optimized_for_speed = 0; -#endif -/* - hack hack - -*/ extern set *externs; @@ -119,9 +88,6 @@ static iCode *ifxForOp ( operand *op, iCode *ic ); void pic16_pushpCodeOp(pCodeOp *pcop); void pic16_poppCodeOp(pCodeOp *pcop); -static bool is_LitOp(operand *op); -static bool is_LitAOp(asmop *aop); - #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff) @@ -134,10 +100,8 @@ static bool is_LitAOp(asmop *aop); 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 = "sp"; /* @@ -147,28 +111,19 @@ static char *one = "#0x01"; * 24 bits -> PRODH:PRODL:WREG * 32 bits -> FSR0L:PRODH:PRODL:WREG * >32 bits -> on stack, and FSR0 points to the beginning - * */ - - -char *fReturnpic16[] = {"WREG", "PRODL", "PRODH", "FSR0L" }; -int fReturnIdx[] = {IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L }; +char *fReturnpic16[] = { "WREG", "PRODL", "PRODH", "FSR0L" }; +int fReturnIdx[] = { IDX_WREG, IDX_PRODL, IDX_PRODH, IDX_FSR0L }; unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */ static char **fReturn = fReturnpic16; static char *accUse[] = {"WREG"}; -//static short rbank = -1; - static struct { - short r0Pushed; - short r1Pushed; - short fsr0Pushed; short accInUse; short inLine; short debugLine; short nRegsSaved; - short ipushRegs; set *sendSet; set *stackRegSet; int usefastretfie; @@ -180,10 +135,7 @@ static struct { int useWreg; /* flag when WREG is used to pass function parameter */ } _G; -extern int pic16_ptrRegReq ; -extern int pic16_nRegs; extern struct dbuf_s *codeOutBuf; -//static void saverbank (int, iCode *,bool); static lineNode *lineHead = NULL; static lineNode *lineCurr = NULL; @@ -313,11 +265,17 @@ void DEBUGpic16_emitcode (char *inst,char *fmt, ...) void pic16_emitpLabel(int key) { + if(key>max_key) + max_key = key; + pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+pic16_labelOffset)); } void pic16_emitpLabelFORCE(int key) { + if(key>max_key) + max_key = key; + pic16_addpCode2pBlock(pb,pic16_newpCodeLabelFORCE(NULL,key+100+pic16_labelOffset)); } @@ -404,149 +362,6 @@ pic16_emitDebuggerSymbol (char * debugSym) _G.debugLine = 0; } - -/*-----------------------------------------------------------------*/ -/* 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; - bool fsr0iu = FALSE, fsr0ou; - bool fsr2iu = FALSE, fsr2ou; - - //fprintf(stderr, "%s:%s:%d: getting free ptr from ic = %c result: %d\n", __FILE__, __FUNCTION__, __LINE__, ic->op, result); - - - fsr2iu = bitVectBitValue(ic->rUsed, IDX_FSR2); - fsr0iu = bitVectBitValue(ic->rUsed, IDX_FSR0); - - fsr2ou = bitVectBitValue(ic->rMask, IDX_FSR2); - fsr0ou = bitVectBitValue(ic->rMask, IDX_FSR0); - - if(bitVectBitValue(ic->rUsed, IDX_WREG)) { - fprintf(stderr, "%s:%d WREG is used by this ic\n", __FILE__, __LINE__); - DEBUGpic16_emitcode("%s:%d WREG is used by this ic", __FILE__, __LINE__); - } - - if(!fsr0iu && !fsr0ou) { - ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR0); - (*aopp)->type = AOP_FSR0; - - //fprintf(stderr, "%s:%d returning plain FSR0\n", __FILE__, __LINE__); - - return ((*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR0)); - } - -#if 0 - /* no usage of FSR2 */ - if(!fsr2iu && !fsr2ou) { - ic->rUsed = bitVectSetBit(ic->rUsed, IDX_FSR2); - (*aopp)->type = AOP_FSR2; - - return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(IDX_FSR2); - } -#endif - - /* now we know they both have usage */ - /* if fsr0 not used in this instruction */ - if (!fsr0iu) { - if (!_G.fsr0Pushed) { - pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) ); - pic16_pushpCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) ); - _G.fsr0Pushed++; - } - - ic->rUsed = bitVectSetBit (ic->rUsed, IDX_FSR0); - (*aopp)->type = AOP_FSR0; - -// fprintf(stderr, "%s:%d returning FSR0 after pushing value to stack\n", __FILE__, __LINE__); - - return (*aopp)->aopu.aop_ptr = pic16_regWithIdx (IDX_FSR0); - } - - - fprintf(stderr, "%s:%d could not allocate a free pointer\n", __FILE__, __LINE__); - assert( 0 ); - - return NULL; -#if 0 - /* 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 */ - if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) && - (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) - { - 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 = pic16_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 = pic16_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) { - //pic16_emitcode ("push","%s", - // pic16_regWithIdx(R0_IDX)->dname); - _G.r0Pushed++ ; - } - - ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX); - (*aopp)->type = AOP_R0; - - return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX); - } - - /* if r1 not used then */ - - if (!r1iu) { - /* push it if not already pushed */ - if (!_G.r1Pushed) { - //pic16_emitcode ("push","%s", - // pic16_regWithIdx(R1_IDX)->dname); - _G.r1Pushed++ ; - } - - ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX); - (*aopp)->type = AOP_R1; - return pic16_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(0); -#endif -} - /*-----------------------------------------------------------------*/ /* newAsmop - creates a new asmOp */ /*-----------------------------------------------------------------*/ @@ -559,20 +374,6 @@ static asmop *newAsmop (short type) return aop; } -static void genSetDPTR(int n) -{ - if (!n) - { - pic16_emitcode(";", "Select standard DPTR"); - pic16_emitcode("mov", "dps, #0x00"); - } - else - { - pic16_emitcode(";", "Select alternate DPTR"); - pic16_emitcode("mov", "dps, #0x01"); - } -} - /*-----------------------------------------------------------------*/ /* resolveIfx - converts an iCode ifx into a form more useful for */ /* generating code */ @@ -797,44 +598,10 @@ static asmop *aopForSym (iCode *ic, operand *op, bool result) } #endif -#if 0 - if (sym->onStack && options.stack10bit) - { - /* It's on the 10 bit stack, which is located in - * far data space. - */ - - //DEBUGpic16_emitcode(";","%d",__LINE__); - - if ( _G.accInUse ) - pic16_emitcode("push","acc"); - - pic16_emitcode("mov","a,_bp"); - pic16_emitcode("add","a,#0x%02x", - ((sym->stack < 0) ? - ((char)(sym->stack - _G.nRegsSaved )) : - ((char)sym->stack)) & 0xff); - - genSetDPTR(1); - pic16_emitcode ("mov","dpx1,#0x40"); - pic16_emitcode ("mov","dph1,#0x00"); - pic16_emitcode ("mov","dpl1, a"); - genSetDPTR(0); - - if ( _G.accInUse ) - pic16_emitcode("pop","acc"); - - sym->aop = aop = newAsmop(AOP_DPTR2); - aop->size = getSize(sym->type); - return aop; - } -#endif - #if 1 /* special case for a function */ if (IS_FUNC(sym->type)) { sym->aop = aop = newAsmop(AOP_PCODE); - //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1); aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0); PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space); PCOI(aop->aopu.pcop)->index = 0; @@ -1101,14 +868,14 @@ static bool operandsEqu ( operand *op1, operand *op2) if (IS_ITEMP(op1) && !IS_ITEMP(op2) && sym1->isspilt && - (sym1->usl.spillLoc == sym2)) + (SYM_SPIL_LOC(sym1) == sym2)) return TRUE; if (IS_ITEMP(op2) && !IS_ITEMP(op1) && sym2->isspilt && sym1->level > 0 && - (sym2->usl.spillLoc == sym1)) + (SYM_SPIL_LOC(sym2) == sym1)) return TRUE ; return FALSE ; @@ -1242,8 +1009,6 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) if (sym->remat) { sym->aop = op->aop = aop = aopForRemat (op, result); -// aop->size = getSize(sym->type); -// DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd); return; } @@ -1254,7 +1019,7 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) aop->size = getSize(sym->type); for ( i = 0 ; i < 1 ; i++ ) { aop->aopu.aop_str[i] = accUse[i]; -// aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset); +// aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, SYM_SPIL_LOC(sym)->offset); } fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name); DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size); @@ -1266,7 +1031,7 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) if (sym->ruonly) { /* sym->aop = op->aop = aop = newAsmop(AOP_PCODE); - aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset); + aop->aopu.pcop = pic16_popGetImmd(SYM_SPIL_LOC(sym)->rname,0,SYM_SPIL_LOC(sym)->offset); //pic16_allocDirReg (IC_LEFT(ic)); aop->size = getSize(sym->type); */ @@ -1283,24 +1048,24 @@ void pic16_aopOp (operand *op, iCode *ic, bool result) } #endif /* else spill location */ - if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) { + if (SYM_SPIL_LOC(sym) && getSize(sym->type) != getSize(SYM_SPIL_LOC(sym)->type)) { /* force a new aop if sizes differ */ - sym->usl.spillLoc->aop = NULL; + SYM_SPIL_LOC(sym)->aop = NULL; } #if 0 DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d", __FUNCTION__,__LINE__, - sym->usl.spillLoc->rname, - sym->rname, sym->usl.spillLoc->offset); + SYM_SPIL_LOC(sym)->rname, + sym->rname, SYM_SPIL_LOC(sym)->offset); #endif - //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset); - if (sym->usl.spillLoc && sym->usl.spillLoc->rname) { + //aop->aopu.pcop = pic16_popGetImmd(SYM_SPIL_LOC(sym)->rname,0,SYM_SPIL_LOC(sym)->offset); + if (SYM_SPIL_LOC(sym) && SYM_SPIL_LOC(sym)->rname) { sym->aop = op->aop = aop = newAsmop(AOP_PCODE); - aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, + aop->aopu.pcop = pic16_popRegFromString(SYM_SPIL_LOC(sym)->rname, getSize(sym->type), - sym->usl.spillLoc->offset, op); + SYM_SPIL_LOC(sym)->offset, op); } else if (getSize(sym->type) <= 1) { //fprintf (stderr, "%s:%d called for a spillLocation -- assigning WREG instead --- CHECK (size:%u)!\n", __FUNCTION__, __LINE__, getSize(sym->type)); pic16_emitpcomment (";!!! %s:%d called for a spillLocation -- assigning WREG instead --- CHECK", __FUNCTION__, __LINE__); @@ -1361,46 +1126,8 @@ void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop) aop->freed = 1; - /* depending on the asmop type only three cases need work AOP_RO - , AOP_R1 && AOP_STK */ #if 1 switch (aop->type) { - case AOP_FSR0 : - if (_G.fsr0Pushed ) { - if (pop) { - pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0h) ); - pic16_poppCodeOp( pic16_popCopyReg(&pic16_pc_fsr0l) ); -// pic16_emitcode ("pop","ar0"); - _G.fsr0Pushed--; - } - } - bitVectUnSetBit(ic->rUsed,IDX_FSR0); - break; - - case AOP_FSR2 : - bitVectUnSetBit(ic->rUsed,IDX_FSR2); - break; - - case AOP_R0 : - if (_G.r0Pushed ) { - if (pop) { - pic16_emitcode ("pop","ar0"); - _G.r0Pushed--; - } - } - bitVectUnSetBit(ic->rUsed,R0_IDX); - break; - - case AOP_R1 : - if (_G.r1Pushed ) { - if (pop) { - pic16_emitcode ("pop","ar1"); - _G.r1Pushed--; - } - } - bitVectUnSetBit(ic->rUsed,R1_IDX); - break; - case AOP_STA: { int i; @@ -1436,7 +1163,7 @@ void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop) } } - { + if (_G.sregsAllocSet) { regs *sr; _G.sregsAllocSet = reverseSet( _G.sregsAllocSet ); @@ -1529,56 +1256,6 @@ char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname) /* depending on type */ switch (aop->type) { - - case AOP_FSR0: - case AOP_FSR2: - sprintf(s, "%s", aop->aopu.aop_ptr->name); - rs = Safe_calloc(1, strlen(s)+1); - strcpy(rs, s); - return (rs); - -#if 0 - /* 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; -#endif - - - case AOP_IMMD: - if (bit16) - sprintf (s,"%s",aop->aopu.aop_immd); - else - if (offset) - sprintf(s,"(%s >> %d)", - aop->aopu.aop_immd, - offset*8); - else - sprintf(s,"%s", - aop->aopu.aop_immd); - DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s); - rs = Safe_calloc(1,strlen(s)+1); - strcpy(rs,s); - return rs; - case AOP_DIR: if (offset) { sprintf(s,"(%s + %d)", @@ -1709,34 +1386,6 @@ pCodeOp *pic16_popGetTempReg(int lock) cfunc = currFunc; currFunc = NULL; -#if 0 - { - regs *rr; - int i; - - /* this code might seem better but it does the *same* job with - * the old code, it all depends on ralloc.c to get a free/unused - * register */ - - i=0; - while(i < pic16_nRegs) { - rr = pic16_typeRegWithIdx(i, REG_GPR, 0); - fprintf(stderr, "%s:%d checking for TempReg Idx=%d rr=%p\n", __FILE__, __LINE__, i, rr); - if((!rr || (rr && rr->isFree)) - && !bitVectBitValue(cfunc->regsUsed, i)) { - pcop = pic16_newpCodeOpReg( i ); - PCOR(pcop)->r->wasUsed = 1; - PCOR(pcop)->r->isFree = 0; - break; - } - i++; - } - - if(pcop) { - pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) ); - } - } -#else pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP); if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) { PCOR(pcop)->r->wasUsed=1; @@ -1745,7 +1394,6 @@ pCodeOp *pic16_popGetTempReg(int lock) /* push value on stack */ pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) ); } -#endif currFunc = cfunc; @@ -2059,31 +1707,6 @@ pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname) /* depending on type */ switch (aop->type) { - case AOP_R0: - case AOP_R1: - case AOP_DPTR: - case AOP_DPTR2: - DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type)); - fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type)); - assert( 0 ); - return NULL; - - case AOP_FSR0: - case AOP_FSR2: - pcop = Safe_calloc(1, sizeof(pCodeOpReg)); - PCOR(pcop)->rIdx = aop->aopu.aop_ptr->rIdx+2; /* access PLUSW register */ - PCOR(pcop)->r = pic16_regWithIdx( PCOR(pcop)->rIdx ); - PCOR(pcop)->r->wasUsed = 1; - PCOR(pcop)->r->isFree = 0; - - PCOR(pcop)->instance = offset; - pcop->type = PCOR(pcop)->r->pc_type; - return (pcop); - - case AOP_IMMD: - DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__); - return pic16_popGetImmd(aop->aopu.aop_immd,offset,0); - case AOP_STA: /* pCodeOp is already allocated from aopForSym */ DEBUGpic16_emitcode(";---", "%d getting stack + offset %d\n", __LINE__, offset); @@ -2300,81 +1923,6 @@ void pic16_aopPut (asmop *aop, char *s, int offset) } break; - case AOP_DPTR: - case AOP_DPTR2: - - if (aop->type == AOP_DPTR2) - { - genSetDPTR(1); - } - - if (aop->code) { - werror(E_INTERNAL_ERROR,__FILE__,__LINE__, - "pic16_aopPut writting to code space"); - exit(0); - } - - while (offset > aop->coff) { - aop->coff++; - pic16_emitcode ("inc","dptr"); - } - - while (offset < aop->coff) { - aop->coff-- ; - pic16_emitcode("lcall","__decdptr"); - } - - aop->coff = offset; - - /* if not in accumulater */ - MOVA(s); - - pic16_emitcode ("movx","@dptr,a"); - - if (aop->type == AOP_DPTR2) - { - genSetDPTR(0); - } - break; - - case AOP_R0: - case AOP_R1: - while (offset > aop->coff) { - aop->coff++; - pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name); - } - while (offset < aop->coff) { - aop->coff-- ; - pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name); - } - aop->coff = offset; - - if (aop->paged) { - MOVA(s); - pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name); - - } else - if (*s == '@') { - MOVA(s); - pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__); - } 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); - pic16_emitcode("mov","@%s,%s", - aop->aopu.aop_ptr->name,buffer); - } else - pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s); - - break; - case AOP_STK: if (strcmp(s,"a") == 0) pic16_emitcode("push","acc"); @@ -2443,15 +1991,32 @@ void pic16_mov2w (asmop *aop, int offset) { DEBUGpic16_emitcode ("; ***","%s %d offset=%d",__FUNCTION__,__LINE__,offset); - if(is_LitAOp(aop)) + if(pic16_isLitAop(aop)) pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset)); else pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset)); } +void pic16_mov2w_volatile (asmop *aop) +{ + int i; + + if(!pic16_isLitAop(aop)) { + // may need to protect this from the peepholer -- this is not nice but works... + pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN")); + for (i = 0; i < aop->size; i++) { + if (i > 0) { + pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - MORE")); + } // if + pic16_emitpcode(POC_MOVFW, pic16_popGet(aop, i)); + } // for + pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(";", "VOLATILE READ - END")); + } +} + void pic16_mov2f(asmop *dst, asmop *src, int offset) { - if(is_LitAOp(src)) { + if(pic16_isLitAop(src)) { pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset)); pic16_emitpcode(POC_MOVWF, pic16_popGet(dst, offset)); } else { @@ -2477,7 +2042,7 @@ static void pic16_movLit2f(pCodeOp *pc, int lit) static void mov2fp(pCodeOp *dst, asmop *src, int offset) { - if(is_LitAOp(src)) { + if(pic16_isLitAop(src)) { pic16_emitpcode(POC_MOVLW, pic16_popGet(src, offset)); pic16_emitpcode(POC_MOVWF, dst); } else { @@ -2547,7 +2112,7 @@ void pushaop(asmop *aop, int offset) if(_G.resDirect)return; - if(is_LitAOp(aop)) { + if(pic16_isLitAop(aop)) { pic16_emitpcode(POC_MOVLW, pic16_popGet(aop, offset)); pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec )); } else { @@ -2584,65 +2149,6 @@ void popaopidx(asmop *aop, int offset, int index) pic16_testStackOverflow(); } -#if !(USE_GENERIC_SIGNED_SHIFT) -/*-----------------------------------------------------------------*/ -/* reAdjustPreg - points a register back to where it should */ -/*-----------------------------------------------------------------*/ -static void reAdjustPreg (asmop *aop) -{ - int size ; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - aop->coff = 0; - if ((size = aop->size) <= 1) - return ; - size-- ; - switch (aop->type) { - case AOP_R0 : - case AOP_R1 : - while (size--) - pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name); - break; - case AOP_DPTR : - case AOP_DPTR2: - if (aop->type == AOP_DPTR2) - { - genSetDPTR(1); - } - while (size--) - { - pic16_emitcode("lcall","__decdptr"); - } - - if (aop->type == AOP_DPTR2) - { - genSetDPTR(0); - } - break; - - } - -} -#endif - -#if 0 -/*-----------------------------------------------------------------*/ -/* opIsGptr: returns non-zero if the passed operand is */ -/* a generic pointer type. */ -/*-----------------------------------------------------------------*/ -static int opIsGptr(operand *op) -{ - sym_link *type = operandType(op); - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type)) - { - return 1; - } - return 0; -} -#endif - /*-----------------------------------------------------------------*/ /* pic16_getDataSize - get the operand data size */ /*-----------------------------------------------------------------*/ @@ -2790,7 +2296,7 @@ static void genUminusFloat(operand *op,operand *result) /*-----------------------------------------------------------------*/ static void genUminus (iCode *ic) { - int size, i; + int lsize, rsize, i; sym_link *optype, *rtype; symbol *label; int needLabel=0; @@ -2825,177 +2331,77 @@ static void genUminus (iCode *ic) } /* otherwise subtract from zero by taking the 2's complement */ - size = AOP_SIZE(IC_LEFT(ic)); - assert( size == AOP_SIZE(IC_RESULT(ic)) ); + lsize = AOP_SIZE(IC_LEFT(ic)); + rsize = AOP_SIZE(IC_RESULT(ic)); label = newiTempLabel ( NULL ); if (pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) { - for (i=size-1; i > 0; i--) { - pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_LEFT(ic)), i)); + /* If the result is longer than the operand, + store sign extension (0x00 or 0xff) in W */ + if (rsize > lsize) { + pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0x00)); + pic16_emitpcode (POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(IC_LEFT(ic)), lsize-1), 7)); + pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0xFF)); + } + for (i = rsize - 1; i > 0; --i) { + if (i > lsize - 1) { + pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i)); + } else { + pic16_emitpcode (POC_COMF, pic16_popGet (AOP(IC_RESULT(ic)), i)); + } // if } // for - pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_LEFT(ic)), 0)); - for (i=1; i < size; i++) { - if (i == size - 1) { emitSKPNZ; } else { pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; } - pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_LEFT(ic)), i)); + pic16_emitpcode (POC_NEGF, pic16_popGet (AOP(IC_RESULT(ic)), 0)); + for (i = 1; i < rsize; ++i) { + if (i == rsize - 1) { + emitSKPNZ; + } else { + pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; + } + pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)), i)); } // for } else { - for (i=size-1; i >= 0; i--) { + for (i = min(rsize, lsize) - 1; i >= 0; i--) { pic16_emitpcode (POC_COMFW, pic16_popGet (AOP(IC_LEFT(ic)), i)); pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i)); } // for - if (size > 1) { - for (i=0; i < size-2; i++) { + /* Sign extend if the result is longer than the operand */ + if (rsize > lsize) { + pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0x00)); + pic16_emitpcode (POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(IC_RESULT(ic)), lsize - 1), 7)); + pic16_emitpcode (POC_MOVLW, pic16_popGetLit(0xFF)); + for (i = rsize - 1; i > lsize - 1; --i) { + pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(IC_RESULT(ic)), i)); + } // for + } // if + if (rsize > 1) { + for (i = 0; i < rsize - 2; i++) { pic16_emitpcode (POC_INCF, pic16_popGet (AOP(IC_RESULT(ic)),i)); - pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); needLabel++; + pic16_emitpcode (POC_BNZ, pic16_popGetLabel (label->key)); + needLabel++; } // for - pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), size-2)); + pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(IC_RESULT(ic)), rsize - 2)); } // if - pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), size-1)); + pic16_emitpcode (POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), rsize - 1)); } if (needLabel) pic16_emitpLabel (label->key); release: /* release the aops */ - pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1)); - pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); + pic16_freeAsmop(IC_LEFT(ic), NULL, ic, (RESULTONSTACK(ic) ? 0 : 1)); + pic16_freeAsmop(IC_RESULT(ic), NULL, ic, TRUE); } -#if 0 -/*-----------------------------------------------------------------*/ -/* saveRegisters - will look for a call and save the registers */ -/*-----------------------------------------------------------------*/ -static void saveRegisters(iCode *lic) +void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src) { - int i; - iCode *ic; - bitVect *rsave; - sym_link *dtype; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* 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_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type)) - return ; - - /* 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)) - pic16_emitcode("mov","b,r0"); - pic16_emitcode("mov","r0,%s",spname); - for (i = 0 ; i < pic16_nRegs ; i++) { - if (bitVectBitValue(rsave,i)) { - if (i == R0_IDX) - pic16_emitcode("mov","a,b"); - else - pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name); - pic16_emitcode("movx","@r0,a"); - pic16_emitcode("inc","r0"); - } - } - pic16_emitcode("mov","%s,r0",spname); - if (bitVectBitValue(rsave,R0_IDX)) - pic16_emitcode("mov","r0,b"); - }// else - //for (i = 0 ; i < pic16_nRegs ; i++) { - // if (bitVectBitValue(rsave,i)) - // pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname); - //} - - dtype = operandType(IC_LEFT(ic)); - if (currFunc && dtype && - (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) && - IFFUNC_ISISR(currFunc->type) && - !ic->bankSaved) - - saverbank(FUNC_REGBANK(dtype),ic,TRUE); - -} -/*-----------------------------------------------------------------*/ -/* unsaveRegisters - pop the pushed registers */ -/*-----------------------------------------------------------------*/ -static void unsaveRegisters (iCode *ic) -{ - int i; - bitVect *rsave; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* find the registers in use at this time - and push them away to safety */ - rsave = bitVectCplAnd(bitVectCopy(ic->rMask), - ic->rUsed); - - if (options.useXstack) { - pic16_emitcode("mov","r0,%s",spname); - for (i = pic16_nRegs ; i >= 0 ; i--) { - if (bitVectBitValue(rsave,i)) { - pic16_emitcode("dec","r0"); - pic16_emitcode("movx","a,@r0"); - if (i == R0_IDX) - pic16_emitcode("mov","b,a"); - else - pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name); - } - - } - pic16_emitcode("mov","%s,r0",spname); - if (bitVectBitValue(rsave,R0_IDX)) - pic16_emitcode("mov","r0,b"); - } //else - //for (i = pic16_nRegs ; i >= 0 ; i--) { - // if (bitVectBitValue(rsave,i)) - // pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname); - //} - -} -#endif - -#if 0 // patch 14 -/*-----------------------------------------------------------------*/ -/* pushSide - */ -/*-----------------------------------------------------------------*/ -static void pushSide(operand * oper, int size) -{ - int offset = 0; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - while (size--) { - char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE); - if (AOP_TYPE(oper) != AOP_REG && - AOP_TYPE(oper) != AOP_DIR && - strcmp(l,"a") ) { - pic16_emitcode("mov","a,%s",l); - pic16_emitcode("push","acc"); - } else - pic16_emitcode("push","%s",l); - } -} -#endif // patch 14 - -void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src) -{ - if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) { - pic16_emitpcode(POC_MOVFW, src); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset)); - } else { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p( - src, pic16_popGet(AOP(op), offset))); - } -} + if((AOP(op)->type == AOP_PCODE) && (AOP(op)->aopu.pcop->type == PO_IMMEDIATE)) { + pic16_emitpcode(POC_MOVFW, src); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset)); + } else { + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + src, pic16_popGet(AOP(op), offset))); + } +} /*-----------------------------------------------------------------*/ @@ -3173,105 +2579,6 @@ static void genIpop (iCode *ic) #endif } -#if 0 -/*-----------------------------------------------------------------*/ -/* unsaverbank - restores the resgister bank from stack */ -/*-----------------------------------------------------------------*/ -static void unsaverbank (int bank,iCode *ic,bool popPsw) -{ - DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__); -#if 0 - int i; - asmop *aop ; - regs *r = NULL; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if (popPsw) { - if (options.useXstack) { - aop = newAsmop(0); - r = getFreePtr(ic,&aop,FALSE); - - - pic16_emitcode("mov","%s,_spx",r->name); - pic16_emitcode("movx","a,@%s",r->name); - pic16_emitcode("mov","psw,a"); - pic16_emitcode("dec","%s",r->name); - - }else - pic16_emitcode ("pop","psw"); - } - - for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) { - if (options.useXstack) { - pic16_emitcode("movx","a,@%s",r->name); - //pic16_emitcode("mov","(%s+%d),a", - // regspic16[i].base,8*bank+regspic16[i].offset); - pic16_emitcode("dec","%s",r->name); - - } else - pic16_emitcode("pop",""); //"(%s+%d)", - //regspic16[i].base,8*bank); //+regspic16[i].offset); - } - - if (options.useXstack) { - - pic16_emitcode("mov","_spx,%s",r->name); - pic16_freeAsmop(NULL,aop,ic,TRUE); - - } -#endif -} - -/*-----------------------------------------------------------------*/ -/* saverbank - saves an entire register bank on the stack */ -/*-----------------------------------------------------------------*/ -static void saverbank (int bank, iCode *ic, bool pushPsw) -{ - DEBUGpic16_emitcode ("; ***","%s %d - WARNING no code generated",__FUNCTION__,__LINE__); -#if 0 - int i; - asmop *aop ; - regs *r = NULL; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if (options.useXstack) { - - aop = newAsmop(0); - r = getFreePtr(ic,&aop,FALSE); - pic16_emitcode("mov","%s,_spx",r->name); - - } - - for (i = 0 ; i < pic16_nRegs ;i++) { - if (options.useXstack) { - pic16_emitcode("inc","%s",r->name); - //pic16_emitcode("mov","a,(%s+%d)", - // regspic16[i].base,8*bank+regspic16[i].offset); - pic16_emitcode("movx","@%s,a",r->name); - } else - pic16_emitcode("push","");// "(%s+%d)", - //regspic16[i].base,8*bank+regspic16[i].offset); - } - - if (pushPsw) { - if (options.useXstack) { - pic16_emitcode("mov","a,psw"); - pic16_emitcode("movx","@%s,a",r->name); - pic16_emitcode("inc","%s",r->name); - pic16_emitcode("mov","_spx,%s",r->name); - pic16_freeAsmop (NULL,aop,ic,TRUE); - - } else - pic16_emitcode("push","psw"); - - pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff); - } - ic->bankSaved = 1; -#endif -} -#endif /* 0 */ - - static int wparamCmp(void *p1, void *p2) { return (!strcmp((char *)p1, (char *)p2)); @@ -3814,7 +3121,7 @@ static void genFunction (iCode *ic) if (sym->regsUsed) { pic16_emitpinfo(INF_LOCALREGS, pic16_newpCodeOpLocalRegs(LR_ENTRY_BEGIN)); - if(!xinst) { + if(!pic16_options.xinst) { /* save the registers used */ DEBUGpic16_emitcode("; **", "Saving used registers in stack"); for ( i = 0 ; i < sym->regsUsed->size ; i++) { @@ -4004,7 +3311,7 @@ void pic16_storeForReturn(iCode *ic, /*operand *op,*/ int offset, pCodeOp *dest) op = IC_LEFT(ic); - // this fails for is_LitOp(op) (if op is an AOP_PCODE) + // this fails for pic16_isLitOp(op) (if op is an AOP_PCODE) if(AOP_TYPE(op) == AOP_LIT) { if(!IS_FLOAT(operandType( op ))) { lit = ulFromVal (AOP(op)->aopu.aop_lit); @@ -4100,49 +3407,6 @@ static void genRet (iCode *ic) } } -#if 0 - /* old code, left here for reference -- VR */ - while (size--) { - char *l ; - - if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) { - /* #NOCHANGE */ - l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE); - pic16_emitpcomment("push %s",l); - pushed++; - } else { - DEBUGpic16_emitcode(";", "%d", __LINE__); - l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE); - DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l); - - if (strcmp(fReturn[offset],l)) { - if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) - || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) { - pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset)); - } else { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset)); - } - - if(size) { - pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr)); - } - offset++; - } - } - } - - if (pushed) { - while(pushed) { - pushed--; - if (strcmp(fReturn[pushed],"a")) - pic16_emitcode("pop",fReturn[pushed]); - else - pic16_emitcode("pop","acc"); - } - } -#endif - - pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE); jumpret: @@ -5102,104 +4366,6 @@ static void genSkipc(resolvedIfx *rifx) rifx->generated = 1; } -#if !(USE_SIMPLE_GENCMP) -/*-----------------------------------------------------------------*/ -/* genSkipz2 */ -/*-----------------------------------------------------------------*/ -static void genSkipz2(resolvedIfx *rifx, int invert_condition) -{ - DEBUGpic16_emitcode ("; ***","%s %d rifx= %p",__FUNCTION__,__LINE__, rifx); - - if(!rifx) - return; - - if( (rifx->condition ^ invert_condition) & 1) - emitSKPZ; - else - emitSKPNZ; - - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key)); - rifx->generated = 1; -} -#endif - -#if 0 -/*-----------------------------------------------------------------*/ -/* genSkipz */ -/*-----------------------------------------------------------------*/ -static void genSkipz(iCode *ifx, int condition) -{ - if(!ifx) - return; - - if(condition) - emitSKPNZ; - else - emitSKPZ; - - if ( IC_TRUE(ifx) ) - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); - else - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); - - if ( IC_TRUE(ifx) ) - pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset); - else - pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset); - -} -#endif - -#if !(USE_SIMPLE_GENCMP) -/*-----------------------------------------------------------------*/ -/* genSkipCond */ -/*-----------------------------------------------------------------*/ -static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit) -{ - if(!rifx) - return; - - if(rifx->condition) - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER)); - else - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0, PO_GPR_REGISTER)); - - - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key)); - rifx->generated = 1; -} -#endif - -#if 0 -/*-----------------------------------------------------------------*/ -/* genChkZeroes :- greater or less than comparison */ -/* For each byte in a literal that is zero, inclusive or the */ -/* the corresponding byte in the operand with W */ -/* returns true if any of the bytes are zero */ -/*-----------------------------------------------------------------*/ -static int genChkZeroes(operand *op, int lit, int size) -{ - - int i; - int flag =1; - - while(size--) { - i = (lit >> (size*8)) & 0xff; - - if(i==0) { - if(flag) - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size)); - else - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size)); - flag = 0; - } - } - - return (flag==0); -} -#endif - - /*-----------------------------------------------------------------*/ /* mov2w_regOrLit :- move to WREG either the offset's byte from */ /* aop (if it's NOT a literal) or from lit (if */ @@ -5217,8 +4383,6 @@ void mov2w_regOrLit (asmop *aop, unsigned long lit, int offset) { /* genCmp :- greater or less than comparison */ /*-----------------------------------------------------------------*/ -#if USE_SIMPLE_GENCMP /* { */ - /* genCmp performs a left < right comparison, stores * the outcome in result (if != NULL) and generates * control flow code for the ifx (if != NULL). @@ -5435,4698 +4599,2905 @@ correct_result_in_carry: } // if } -#elif 1 /* } */ - /* { */ - /* original code */ -static void genCmp (operand *left,operand *right, - operand *result, iCode *ifx, int sign) +/*-----------------------------------------------------------------*/ +/* genCmpGt :- greater than comparison */ +/*-----------------------------------------------------------------*/ +static void genCmpGt (iCode *ic, iCode *ifx) { - int size; //, offset = 0 ; - unsigned long lit = 0L,i = 0; - resolvedIfx rFalseIfx; - // resolvedIfx rTrueIfx; - symbol *truelbl; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); -/* - if(ifx) { - DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true")); - DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true")); - } -*/ - - FENTRY; + operand *left, *right, *result; + sym_link *letype , *retype; + int sign ; - resolveIfx(&rFalseIfx,ifx); - truelbl = newiTempLabel(NULL); - size = max(AOP_SIZE(left),AOP_SIZE(right)); + FENTRY; - DEBUGpic16_pic16_AopType(__LINE__,left,right,result); + left = IC_LEFT(ic); + right= IC_RIGHT(ic); + result = IC_RESULT(ic); -#define _swapp + letype = getSpec(operandType(left)); + retype =getSpec(operandType(right)); + sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype)); + /* assign the amsops */ + pic16_aopOp (left,ic,FALSE); + pic16_aopOp (right,ic,FALSE); + pic16_aopOp (result,ic,TRUE); - /* if literal is on the right then swap with left */ - if ((AOP_TYPE(right) == AOP_LIT)) { - operand *tmp = right ; - unsigned long mask = (0x100 << (8*(size-1))) - 1; - lit = ulFromVal (AOP(right)->aopu.aop_lit); -#ifdef _swapp + genCmp(right, left, result, ifx, sign); - lit = (lit - 1) & mask; - right = left; - left = tmp; - rFalseIfx.condition ^= 1; -#endif + pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(result,NULL,ic,TRUE); +} - } else if ((AOP_TYPE(left) == AOP_LIT)) { - lit = ulFromVal (AOP(left)->aopu.aop_lit); - } +/*-----------------------------------------------------------------*/ +/* genCmpLt - less than comparisons */ +/*-----------------------------------------------------------------*/ +static void genCmpLt (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + sym_link *letype , *retype; + int sign ; + FENTRY; - //if(IC_TRUE(ifx) == NULL) - /* if left & right are bit variables */ - if (AOP_TYPE(left) == AOP_CRY && - AOP_TYPE(right) == AOP_CRY ) { - assert (0 && "bit variables used in genCmp"); - pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); - pic16_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 */ + left = IC_LEFT(ic); + right= IC_RIGHT(ic); + result = IC_RESULT(ic); - symbol *lbl = newiTempLabel(NULL); + letype = getSpec(operandType(left)); + retype =getSpec(operandType(right)); + sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype)); -#if 0 - fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n", - __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+pic16_labelOffset, lbl->key+100+pic16_labelOffset); -#endif + /* assign the amsops */ + pic16_aopOp (left,ic,FALSE); + pic16_aopOp (right,ic,FALSE); + pic16_aopOp (result,ic,TRUE); -#ifndef _swapp - if(AOP_TYPE(right) == AOP_LIT) { + genCmp(left, right, result, ifx, sign); - //lit = ulFromVal (AOP(right)->aopu.aop_lit); + pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(result,NULL,ic,TRUE); +} - DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign); +/*-----------------------------------------------------------------*/ +/* pic16_isLitOp - check if operand has to be treated as literal */ +/*-----------------------------------------------------------------*/ +bool pic16_isLitOp(operand *op) +{ + return ((AOP_TYPE(op) == AOP_LIT) + || ( (AOP_TYPE(op) == AOP_PCODE) + && ( (AOP(op)->aopu.pcop->type == PO_LITERAL) + || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ))); +} - /* special cases */ +/*-----------------------------------------------------------------*/ +/* pic16_isLitAop - check if operand has to be treated as literal */ +/*-----------------------------------------------------------------*/ +bool pic16_isLitAop(asmop *aop) +{ + return ((aop->type == AOP_LIT) + || ( (aop->type == AOP_PCODE) + && ( (aop->aopu.pcop->type == PO_LITERAL) + || (aop->aopu.pcop->type == PO_IMMEDIATE) ))); +} - if(lit == 0) { - if(sign != 0) - genSkipCond(&rFalseIfx,left,size-1,7); - else - /* no need to compare to 0...*/ - /* NOTE: this is a de-generate compare that most certainly - * creates some dead code. */ - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key)); - if(ifx) ifx->generated = 1; - return; - - } - size--; - - if(size == 0) { - //i = (lit >> (size*8)) & 0xff; - DEBUGpic16_emitcode(";right lit","line = %d",__LINE__); - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size)); - - i = ((0-lit) & 0xff); - if(sign) { - if( i == 0x81) { - /* lit is 0x7f, all signed chars are less than - * this except for 0x7f itself */ - pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f)); - genSkipz2(&rFalseIfx,0); - } else { - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80)); - genSkipc(&rFalseIfx); - } +/*-----------------------------------------------------------------*/ +/* genCmpEq - generates code for equal to */ +/*-----------------------------------------------------------------*/ +static void genCmpEq (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + symbol *falselbl = newiTempLabel(NULL); + symbol *donelbl = newiTempLabel(NULL); - } else { - if(lit == 1) { - genSkipz2(&rFalseIfx,1); - } else { - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i)); - genSkipc(&rFalseIfx); - } - } + int preserve_result = 0; + int generate_result = 0; + int i=0; + unsigned long lit = -1; - if(ifx) ifx->generated = 1; - return; - } + FENTRY; - /* chars are out of the way. now do ints and longs */ + pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE); + pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE); + pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); + DEBUGpic16_pic16_AopType(__LINE__,left,right,result); - DEBUGpic16_emitcode(";right lit","line = %d",__LINE__); + if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) ) + { + werror(W_POSSBUG2, __FILE__, __LINE__); + DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__); + fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__); + goto release; + } - /* special cases */ + if (pic16_isLitOp(left) || (AOP_TYPE(right) == AOP_ACC)) + { + operand *tmp = right ; + right = left; + left = tmp; + } - if(sign) { + if (AOP_TYPE(right) == AOP_LIT) { + lit = ulFromVal (AOP(right)->aopu.aop_lit); + } - if(lit == 0) { - genSkipCond(&rFalseIfx,left,size,7); - if(ifx) ifx->generated = 1; - return; - } + if ( regsInCommon(left, result) || regsInCommon(right, result) ) + preserve_result = 1; - if(lit <0x100) { - DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit); + if(result && AOP_SIZE(result)) + generate_result = 1; - //rFalseIfx.condition ^= 1; - //genSkipCond(&rFalseIfx,left,size,7); - //rFalseIfx.condition ^= 1; + if(generate_result && !preserve_result) + { + for(i = 0; i < AOP_SIZE(result); i++) + pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i)); + } - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - if(rFalseIfx.condition) - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); + assert( AOP_SIZE(left) == AOP_SIZE(right) ); + for(i=0; i < AOP_SIZE(left); i++) + { + if(AOP_TYPE(left) != AOP_ACC) + { + if(pic16_isLitOp(left)) + pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i)); else - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit)); - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1)); - - while(size > 1) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--)); - - if(rFalseIfx.condition) { - emitSKPZ; - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - - } else { - emitSKPNZ; - } - - genSkipc(&rFalseIfx); - pic16_emitpLabel(truelbl->key); - if(ifx) ifx->generated = 1; - return; - + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i)); + } + if(pic16_isLitOp(right)) { + if (pic16_isLitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) { + pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); } + } else + pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); - if(size == 1) { + pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key)); + } - if( (lit & 0xff) == 0) { - /* lower byte is zero */ - DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit); - i = ((lit >> 8) & 0xff) ^0x80; - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i)); - genSkipc(&rFalseIfx); + // result == true + if(generate_result && preserve_result) + { + for(i = 0; i < AOP_SIZE(result); i++) + pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i)); + } - if(ifx) ifx->generated = 1; - return; + if(generate_result) + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true - } - } else { - /* Special cases for signed longs */ - if( (lit & 0xffffff) == 0) { - /* lower byte is zero */ - DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit); - i = ((lit >> 8*3) & 0xff) ^0x80; - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i)); - genSkipc(&rFalseIfx); - - - if(ifx) ifx->generated = 1; - return; + if(generate_result && preserve_result) + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key)); - } + if(ifx && IC_TRUE(ifx)) + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); - } + if(ifx && IC_FALSE(ifx)) + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key)); + pic16_emitpLabel(falselbl->key); - if(lit & (0x80 << (size*8))) { - /* lit is negative */ - DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit); + // result == false - //genSkipCond(&rFalseIfx,left,size,7); + if(ifx && IC_FALSE(ifx)) + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); + if(generate_result && preserve_result) + { + for(i = 0; i < AOP_SIZE(result); i++) + pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i)); + } - if(rFalseIfx.condition) - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - else - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); + pic16_emitpLabel(donelbl->key); + if(ifx) + ifx->generated = 1; - } else { - /* lit is positive */ - DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - if(rFalseIfx.condition) - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - else - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); +release: + pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(result,NULL,ic,TRUE); - } +} - /* - This works, but is only good for ints. - It also requires a "known zero" register. - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff)); - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_RLCFW, pic16_popCopyReg(&pic16_pc_kzero)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff))); - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1)); - genSkipc(&rFalseIfx); - - pic16_emitpLabel(truelbl->key); - if(ifx) ifx->generated = 1; - return; - **/ - /* There are no more special cases, so perform a general compare */ +#if 0 +// old version kept for reference - pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size)); +/*-----------------------------------------------------------------*/ +/* genCmpEq - generates code for equal to */ +/*-----------------------------------------------------------------*/ +static void genCmpEq (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + unsigned long lit = 0L; + int size,offset=0; + symbol *falselbl = newiTempLabel(NULL); - while(size--) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff)); - emitSKPNZ; - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size)); - } - //rFalseIfx.condition ^= 1; - genSkipc(&rFalseIfx); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_emitpLabel(truelbl->key); + if(ifx) + DEBUGpic16_emitcode ("; ifx is non-null",""); + else + DEBUGpic16_emitcode ("; ifx is null",""); - if(ifx) ifx->generated = 1; - return; + pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE); + pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE); + pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); + size = max(AOP_SIZE(left),AOP_SIZE(right)); - } + DEBUGpic16_pic16_AopType(__LINE__,left,right,result); + /* 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)) { + operand *tmp = right ; + right = left; + left = tmp; + } - /* sign is out of the way. So now do an unsigned compare */ - DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit); + if(ifx && !AOP_SIZE(result)){ + symbol *tlbl; + DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__); + /* if they are both bit variables */ + if (AOP_TYPE(left) == AOP_CRY && + ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) { + DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__); + if(AOP_TYPE(right) == AOP_LIT){ + unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit); + if(lit == 0L){ + pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + pic16_emitcode("cpl","c"); + } else if(lit == 1L) { + pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + } else { + pic16_emitcode("clr","c"); + } + /* AOP_TYPE(right) == AOP_CRY */ + } else { + symbol *lbl = newiTempLabel(NULL); + pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100)); + pic16_emitcode("cpl","c"); + pic16_emitcode("","%05d_DS_:",(lbl->key+100)); + } + /* if true label then we jump if condition + supplied is true */ + tlbl = newiTempLabel(NULL); + if ( IC_TRUE(ifx) ) { + pic16_emitcode("jnc","%05d_DS_",tlbl->key+100); + pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); + } else { + pic16_emitcode("jc","%05d_DS_",tlbl->key+100); + pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100); + } + pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset); - /* General case - compare to an unsigned literal on the right.*/ + { + /* left and right are both bit variables, result is carry */ + resolvedIfx rIfx; - i = (lit >> (size*8)) & 0xff; - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size)); - while(size--) { - i = (lit >> (size*8)) & 0xff; + resolveIfx(&rIfx,ifx); - if(i) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i)); - emitSKPNZ; - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size)); + pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0)); + pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0)); + pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0)); + genSkipz2(&rIfx,0); + } } else { - /* this byte of the lit is zero, - *if it's not the last then OR in the variable */ - if(size) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size)); - } - } - - - pic16_emitpLabel(lbl->key); -// pic16_emitpLabel(truelbl->key); - //if(emitFinalCheck) - genSkipc(&rFalseIfx); - if(sign) - pic16_emitpLabel(truelbl->key); - - if(ifx) ifx->generated = 1; - return; - - } -#endif // _swapp + DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__); - if(AOP_TYPE(left) == AOP_LIT) { - //symbol *lbl = newiTempLabel(NULL); + /* They're not both bit variables. Is the right a literal? */ + if(AOP_TYPE(right) == AOP_LIT) { + lit = ulFromVal (AOP(right)->aopu.aop_lit); - //EXPERIMENTAL lit = ulFromVal (AOP(left)->aopu.aop_lit); + switch(size) { + case 1: + switch(lit & 0xff) { + case 1: + if ( IC_TRUE(ifx) ) { + pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset)); + emitSKPNZ; + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); + } else { + pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset)); + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); + } + break; + case 0xff: + if ( IC_TRUE(ifx) ) { + pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset)); + emitSKPNZ; + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); + } else { + pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset)); + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); + } + break; + default: + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset)); + if(lit) + pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff)); + genSkip(ifx,'z'); + } // switch lit - DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign); - /* Special cases */ - if((lit == 0) && (sign == 0)){ + /* end of size == 1 */ + break; - size--; - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - while(size) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size)); + case 2: + genc16bit2lit(left,lit,offset); + genSkip(ifx,'z'); + break; + /* end of size == 2 */ - genSkipz2(&rFalseIfx,0); - if(ifx) ifx->generated = 1; - return; - } + default: + /* size is 4 */ + if(lit==0) { + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0)); + pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1)); + pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2)); + pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3)); + genSkip(ifx,'z'); + } else { + /* search for patterns that can be optimized */ - if(size==1) { - /* Special cases */ - lit &= 0xff; - if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) { - /* degenerate compare can never be true */ - if(rFalseIfx.condition == 0) - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key)); + genc16bit2lit(left,lit,0); + lit >>= 16; + if(lit) { + if(IC_TRUE(ifx)) + emitSKPZ; // if hi word unequal + else + emitSKPNZ; // if hi word equal + // fail early + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key)); + genc16bit2lit(left,lit,2); + genSkip(ifx,'z'); + } else { + pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2)); + pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3)); + genSkip(ifx,'z'); + } + } + pic16_emitpLabel(falselbl->key); + break; - if(ifx) ifx->generated = 1; - return; - } + } // switch size - if(sign) { - /* signed comparisons to a literal byte */ + ifx->generated = 1; + goto release ; - int lp1 = (lit+1) & 0xff; - DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit); - switch (lp1) { - case 0: - rFalseIfx.condition ^= 1; - genSkipCond(&rFalseIfx,right,0,7); - break; - case 0x7f: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f)); - genSkipz2(&rFalseIfx,1); - break; - default: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80)); - rFalseIfx.condition ^= 1; - genSkipc(&rFalseIfx); - break; - } - } else { - /* unsigned comparisons to a literal byte */ + } else if(AOP_TYPE(right) == AOP_CRY ) { + /* we know the left is not a bit, but that the right is */ + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset)); + pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS), + pic16_popGet(AOP(right),offset)); + pic16_emitpcode(POC_XORLW,pic16_popGetLit(1)); - switch(lit & 0xff ) { - case 0: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - genSkipz2(&rFalseIfx,0); - break; - case 0x7f: - rFalseIfx.condition ^= 1; - genSkipCond(&rFalseIfx,right,0,7); - break; + /* if the two are equal, then W will be 0 and the Z bit is set + * we could test Z now, or go ahead and check the high order bytes if + * the variable we're comparing is larger than a byte. */ - default: - pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0)); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - rFalseIfx.condition ^= 1; - if (AOP_TYPE(result) == AOP_CRY) - genSkipc(&rFalseIfx); - else { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0)); - } - break; - } - } + while(--size) + pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset)); - if(ifx) ifx->generated = 1; - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) - goto check_carry; - return; + if ( IC_TRUE(ifx) ) { + emitSKPNZ; + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); + // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset); + } else { + emitSKPZ; + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); + // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset); + } - } else { + } else { + /* They're both variables that are larger than bits */ + int s = size; - /* Size is greater than 1 */ + tlbl = newiTempLabel(NULL); - if(sign) { - int lp1 = lit+1; + while(size--) { + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset)); + pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset)); - size--; + if ( IC_TRUE(ifx) ) { + if(size) { + emitSKPZ; - if(lp1 == 0) { - /* this means lit = 0xffffffff, or -1 */ + DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ"); + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); + pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset); + } else { + emitSKPNZ; - DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__); - rFalseIfx.condition ^= 1; - genSkipCond(&rFalseIfx,right,size,7); - if(ifx) ifx->generated = 1; + DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ"); - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) - goto check_carry; - return; - } + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); + pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset); + } + } else { + emitSKPZ; - if(lit == 0) { - int s = size; + DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ"); - if(rFalseIfx.condition) { - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); + pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset); + } + offset++; } - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - while(size--) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size)); - - - emitSKPZ; - if(rFalseIfx.condition) { - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - pic16_emitpLabel(truelbl->key); - }else { - rFalseIfx.condition ^= 1; - genSkipCond(&rFalseIfx,right,s,7); + if(s>1 && IC_TRUE(ifx)) { + pic16_emitpLabel(tlbl->key); + pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset); } - - if(ifx) ifx->generated = 1; - - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) - goto check_carry; - - return; } + } + /* mark the icode as generated */ + ifx->generated = 1; + goto release ; + } - if((size == 1) && (0 == (lp1&0xff))) { - /* lower byte of signed word is zero */ - DEBUGpic16_emitcode(";left lit","line = %d 0x%x+1 low byte is zero",__LINE__,lit); - i = ((lp1 >> 8) & 0xff) ^0x80; - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i)); - - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) { - emitTOGC; - if(ifx) ifx->generated = 1; - goto check_carry; + /* if they are both bit variables */ + if (AOP_TYPE(left) == AOP_CRY && + ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) { + DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__); + if(AOP_TYPE(right) == AOP_LIT){ + unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit); + if(lit == 0L){ + pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + pic16_emitcode("cpl","c"); + } else if(lit == 1L) { + pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); } else { - rFalseIfx.condition ^= 1; - genSkipc(&rFalseIfx); - if(ifx) ifx->generated = 1; + pic16_emitcode("clr","c"); } + /* AOP_TYPE(right) == AOP_CRY */ + } else { + symbol *lbl = newiTempLabel(NULL); + pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100)); + pic16_emitcode("cpl","c"); + pic16_emitcode("","%05d_DS_:",(lbl->key+100)); + } + /* c = 1 if egal */ + if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){ + pic16_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 */ + pic16_outBitC(result); + } else { - return; - } + DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__); + gencjne(left,right,result,ifx); +/* + if(ifx) + gencjne(left,right,newiTempLabel(NULL)); + else { + if(IC_TRUE(ifx)->key) + gencjne(left,right,IC_TRUE(ifx)->key); + else + gencjne(left,right,IC_FALSE(ifx)->key); + ifx->generated = 1; + goto release ; + } + if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) { + pic16_aopPut(AOP(result),"a",0); + goto release ; + } - if(lit & (0x80 << (size*8))) { - /* Lit is less than zero */ - DEBUGpic16_emitcode(";left lit","line = %d 0x%x is less than 0",__LINE__,lit); - //rFalseIfx.condition ^= 1; - //genSkipCond(&rFalseIfx,left,size,7); - //rFalseIfx.condition ^= 1; - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - - if(rFalseIfx.condition) - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - else - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); + 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) + pic16_outAcc(result); +*/ + /* leave the result in acc */ + } +release: + pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(result,NULL,ic,TRUE); +} +#endif - } else { - /* Lit is greater than or equal to zero */ - DEBUGpic16_emitcode(";left lit","line = %d 0x%x is greater than 0",__LINE__,lit); - //rFalseIfx.condition ^= 1; - //genSkipCond(&rFalseIfx,right,size,7); - //rFalseIfx.condition ^= 1; - - //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0)); - //pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - if(rFalseIfx.condition) - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - else - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); +/*-----------------------------------------------------------------*/ +/* ifxForOp - returns the icode containing the ifx for operand */ +/*-----------------------------------------------------------------*/ +static iCode *ifxForOp ( operand *op, iCode *ic ) +{ + FENTRY2; - } + /* if true symbol then needs to be assigned */ + if (IS_TRUE_SYMOP(op)) + return NULL ; - pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size)); + /* 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 + ) { + DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__); + return ic->next; + } - while(size--) { + /* + if (ic->next && + ic->next->op == IFX && + IC_COND(ic->next)->key == op->key) { + DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__); + return ic->next; + } + */ - pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff)); - emitSKPNZ; - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size)); - } - rFalseIfx.condition ^= 1; - //rFalseIfx.condition = 1; - genSkipc(&rFalseIfx); + DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__); + if (ic->next && + ic->next->op == IFX) + DEBUGpic16_emitcode ("; ic-next"," is an IFX"); - pic16_emitpLabel(truelbl->key); + if (ic->next && + ic->next->op == IFX && + IC_COND(ic->next)->key == op->key) { + DEBUGpic16_emitcode ("; "," key is okay"); + DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d", + OP_SYMBOL(op)->liveTo, + ic->next->seq); + } - if(ifx) ifx->generated = 1; +#if 0 + /* the code below is completely untested + * it just allows ulong2fs.c compile -- VR */ + ic = ic->next; + fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n", + __FILE__, __FUNCTION__, __LINE__); - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) - goto check_carry; + /* 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; - // end of if (sign) - } else { + if (ic->next && + ic->next->op == IFX && + IC_COND(ic->next)->key == op->key) { + DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__); + return ic->next; + } - /* compare word or long to an unsigned literal on the right.*/ + fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n", + __FILE__, __FUNCTION__, __LINE__); +// return ic->next->next; /* this just might work */ /* FIXME FIXME */ +#endif - size--; - if(lit < 0xff) { - DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit); - switch (lit) { - case 0: - break; /* handled above */ -/* - case 0xff: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - while(size--) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size)); - genSkipz2(&rFalseIfx,0); - break; -*/ - default: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - while(--size) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size)); - - emitSKPZ; - if(rFalseIfx.condition) - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rFalseIfx.lbl->key)); - else - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(truelbl->key)); - + return NULL; +} +/*-----------------------------------------------------------------*/ +/* genAndOp - for && operation */ +/*-----------------------------------------------------------------*/ +static void genAndOp (iCode *ic) +{ + operand *left,*right, *result; +/* symbol *tlbl; */ - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0)); + FENTRY; - rFalseIfx.condition ^= 1; - genSkipc(&rFalseIfx); - } + /* note here that && operations that are in an + if statement are taken away by backPatchLabels + only those used in arthmetic operations remain */ + pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE); + pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE); + pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); - pic16_emitpLabel(truelbl->key); + DEBUGpic16_pic16_AopType(__LINE__,left,right,result); - if(ifx) ifx->generated = 1; + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0)); + pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0)); - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) - goto check_carry; + /* if both are bit variables */ +/* if (AOP_TYPE(left) == AOP_CRY && */ +/* AOP_TYPE(right) == AOP_CRY ) { */ +/* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */ +/* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */ +/* pic16_outBitC(result); */ +/* } else { */ +/* tlbl = newiTempLabel(NULL); */ +/* pic16_toBoolean(left); */ +/* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */ +/* pic16_toBoolean(right); */ +/* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */ +/* pic16_outBitAcc(result); */ +/* } */ - return; - } + pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(result,NULL,ic,TRUE); +} - lit++; - DEBUGpic16_emitcode ("; ***","%s %d lit =0x%x",__FUNCTION__,__LINE__,lit); - i = (lit >> (size*8)) & 0xff; +/*-----------------------------------------------------------------*/ +/* genOrOp - for || operation */ +/*-----------------------------------------------------------------*/ +/* + tsd pic port - + modified this code, but it doesn't appear to ever get called +*/ - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size)); +static void genOrOp (iCode *ic) +{ + operand *left,*right, *result; + symbol *tlbl; - while(size--) { - i = (lit >> (size*8)) & 0xff; + FENTRY; - if(i) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i)); - emitSKPNZ; - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size)); - } else { - /* this byte of the lit is zero, - * if it's not the last then OR in the variable */ - if(size) - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size)); - } - } + /* note here that || operations that are in an + if statement are taken away by backPatchLabels + only those used in arthmetic operations remain */ + pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE); + pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE); + pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); + DEBUGpic16_pic16_AopType(__LINE__,left,right,result); - pic16_emitpLabel(lbl->key); + /* if both are bit variables */ + if (AOP_TYPE(left) == AOP_CRY && + AOP_TYPE(right) == AOP_CRY ) { + pic16_emitcode("clrc",""); + pic16_emitcode("btfss","(%s >> 3), (%s & 7)", + AOP(left)->aopu.aop_dir, + AOP(left)->aopu.aop_dir); + pic16_emitcode("btfsc","(%s >> 3), (%s & 7)", + AOP(right)->aopu.aop_dir, + AOP(right)->aopu.aop_dir); + pic16_emitcode("setc",""); - rFalseIfx.condition ^= 1; + } else { + tlbl = newiTempLabel(NULL); + pic16_toBoolean(left); + emitSKPZ; + pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset); + pic16_toBoolean(right); + pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset); - genSkipc(&rFalseIfx); - } + pic16_outBitAcc(result); + } - if(sign) - pic16_emitpLabel(truelbl->key); - if(ifx) ifx->generated = 1; + pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(result,NULL,ic,TRUE); +} - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) - goto check_carry; +/*-----------------------------------------------------------------*/ +/* 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; - return; - } - } - /* Compare two variables */ + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + for(idx = 0; idx < 32; idx++) + if(lit == pw[idx]) + return idx+1; + return 0; +} - DEBUGpic16_emitcode(";sign","%d",sign); +/*-----------------------------------------------------------------*/ +/* continueIfTrue - */ +/*-----------------------------------------------------------------*/ +static void continueIfTrue (iCode *ic) +{ + FENTRY; + if(IC_TRUE(ic)) + pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100); + ic->generated = 1; +} - size--; - if(sign) { - /* Sigh. thus sucks... */ - if(size) { - pCodeOp *pctemp; - - pctemp = pic16_popGetTempReg(1); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size)); - pic16_emitpcode(POC_MOVWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr)); - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80)); - pic16_emitpcode(POC_XORWF, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr)); - pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size)); - pic16_emitpcode(POC_SUBFW, pctemp); //pic16_popRegFromIdx(pic16_Gstack_base_addr)); - pic16_popReleaseTempReg(pctemp, 1); - } else { - /* Signed char comparison */ - /* Special thanks to Nikolai Golovchenko for this snippet */ - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); /* could be any register */ - pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); +/*-----------------------------------------------------------------*/ +/* jmpIfTrue - */ +/*-----------------------------------------------------------------*/ +static void jumpIfTrue (iCode *ic) +{ + FENTRY; + if(!IC_TRUE(ic)) + pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100); + ic->generated = 1; +} - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - genSkipc(&rFalseIfx); +/*-----------------------------------------------------------------*/ +/* jmpTrueOrFalse - */ +/*-----------------------------------------------------------------*/ +static void jmpTrueOrFalse (iCode *ic, symbol *tlbl) +{ + // ugly but optimized by peephole + FENTRY; + if(IC_TRUE(ic)){ + symbol *nlbl = newiTempLabel(NULL); + pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100); + pic16_emitcode("","%05d_DS_:",tlbl->key+100); + pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100); + pic16_emitcode("","%05d_DS_:",nlbl->key+100); + } else { + pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100); + pic16_emitcode("","%05d_DS_:",tlbl->key+100); + } + ic->generated = 1; +} - if(ifx) ifx->generated = 1; +/*-----------------------------------------------------------------*/ +/* genAnd - code for and */ +/*-----------------------------------------------------------------*/ +static void genAnd (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + int size, offset = 0; + unsigned long lit = 0L; + resolvedIfx rIfx; - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) - goto check_carry; + FENTRY; - return; - } + pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE); + pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE); + pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE); - } else { + resolveIfx (&rIfx, ifx); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size)); + /* if left is a literal & right is not then exchange them */ + if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) || + AOP_NEEDSACC (left)) + { + operand *tmp = right; + right = left; + left = tmp; } + /* if result = right then exchange them */ + if (pic16_sameRegs (AOP (result), AOP (right))) + { + operand *tmp = right; + right = left; + left = tmp; + } - /* The rest of the bytes of a multi-byte compare */ - while (size) { - - emitSKPZ; - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(lbl->key)); - size--; - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size)); - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size)); + /* 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 = ulFromVal (AOP (right)->aopu.aop_lit); - } + size = AOP_SIZE (result); - pic16_emitpLabel(lbl->key); + DEBUGpic16_pic16_AopType (__LINE__, left, right, result); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || - (AOP_TYPE(result) == AOP_REG)) { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0)); + // 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 && pic16_sameRegs(AOP(result),AOP(left))) + // no change + goto release; + pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); + } else { + // bit(result) = 0; + if(size && (AOP_TYPE(result) == AOP_CRY)){ + pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir); + goto release; + } + if((AOP_TYPE(result) == AOP_CRY) && ifx){ + jumpIfTrue(ifx); + goto release; + } + pic16_emitcode("clr","c"); + } } else { - genSkipc(&rFalseIfx); + if (AOP_TYPE(right) == AOP_CRY){ + // c = bit & bit; + pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); + pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir); + } else { + // c = bit & val; + MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE)); + // c = lsb + pic16_emitcode("rrc","a"); + pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir); + } } - //genSkipc(&rFalseIfx); - if(ifx) ifx->generated = 1; - + // bit = c + // val = c + if(size) + pic16_outBitC(result); + // if(bit & ...) + else if((AOP_TYPE(result) == AOP_CRY) && ifx) + genIfxJump(ifx, "c"); + goto release ; + } - if ((AOP_TYPE(result) != AOP_CRY) && (AOP_SIZE(result))) - goto check_carry; + // 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)) + { + symbol *tlbl = newiTempLabel (NULL); + int sizel = AOP_SIZE (left); + int nonnull = 0; + char emitBra; - return; + if (size) + emitSETC; - } + /* get number of non null bytes in literal */ + while (sizel--) + { + if (lit & (0xff << (sizel * 8))) + ++nonnull; + } -check_carry: - if ((AOP_TYPE(result) != AOP_CRY) - && AOP_SIZE(result)) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + emitBra = nonnull || rIfx.condition; - if(!ifx)pic16_emitpLabel( rFalseIfx.lbl->key ); + for (sizel = AOP_SIZE (left); sizel--; ++offset, lit >>= 8) + { + unsigned char bytelit = lit; - pic16_outBitC(result); - } else { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* if the result is used in the next - ifx conditional branch then generate - code a little differently */ - if (ifx ) - genIfxJump (ifx,"c"); - else - pic16_outBitC(result); - /* leave the result in acc */ - } + if (bytelit != 0) + { + int posbit; -} + --nonnull; -#elif 0 /* VR version of genCmp() */ /* } else { */ - -/* check all condition and return appropriate instruction, POC_CPFSGT or POC_CPFFSLT */ -static int selectCompareOp(resolvedIfx *rIfx, iCode *ifx, - operand *result, int offset, int invert_op) -{ - /* add code here */ - - /* check condition, > or < ?? */ - if(rIfx->condition != 0)invert_op ^= 1; - - if(ifx && IC_FALSE(ifx))invert_op ^= 1; - - if(!ifx)invert_op ^= 1; - - DEBUGpic16_emitcode("; +++", "%s:%d %s] rIfx->condition= %d, ifx&&IC_FALSE(ifx)= %d, invert_op = %d", - __FILE__, __LINE__, __FUNCTION__, rIfx->condition, (ifx && IC_FALSE(ifx)), invert_op); - - /* do selection */ - if(!invert_op)return POC_CPFSGT; - else return POC_CPFSLT; -} - -static int compareAopfirstpass=1; - -static void compareAop(resolvedIfx *resIfx, iCode *ifx, symbol *falselbl, - operand *oper, int offset, operand *result, - int sign, int invert_op, pCodeOp *pcop, pCodeOp *pcop2, - symbol *tlbl) -{ - int op; - symbol *truelbl; - - /* invert if there is a result to be loaded, in order to fit, - * SETC/CLRC sequence */ - if(AOP_SIZE(result))invert_op ^= 1; - -// if(sign && !offset)invert_op ^= 1; - -// if(sign)invert_op ^= 1; + /* patch provided by Aaron Colwell */ + if ((posbit = isLiteralBit (bytelit)) != 0) + { + if (nonnull) + { + pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER)); + pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.condition ? rIfx.lbl->key : tlbl->key)); + } + else + { + pic16_emitpcode (rIfx.condition ? POC_BTFSC :POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet (AOP (left), offset, FALSE, FALSE), posbit - 1, 0, PO_GPR_REGISTER)); + } + } + else + { + if (bytelit == 0xff) + { + /* Aaron had a MOVF instruction here, changed to MOVFW cause + * a peephole could optimize it out -- VR */ + pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset)); + } + else + { + pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset)); + pic16_emitpcode (POC_ANDLW, pic16_popGetLit (bytelit)); + } + if (nonnull) + { + if (rIfx.condition) + { + emitSKPZ; + pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */ + } + else + { + pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */ + } + } + else + { + /* last non null byte */ + if (rIfx.condition) + emitSKPZ; + else + emitSKPNZ; + } + } + } + } - op = selectCompareOp(resIfx, ifx, result, offset, invert_op); + // bit = left & literal + if (size) + { + emitCLRC; + pic16_emitpLabel (tlbl->key); + } - if(AOP_SIZE(result) && compareAopfirstpass) { - if(!ifx) { - if(pcop2) - pic16_emitpcode(POC_SETF, pcop2); - else - emitSETC; - } else { - if(pcop2) - pic16_emitpcode(POC_CLRF, pcop2); + // if(left & literal) else - emitCLRC; + { + if (ifx) + { + if (emitBra) + pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); + ifx->generated = 1; + } + pic16_emitpLabel (tlbl->key); + goto release; + } + pic16_outBitC (result); + goto release; } - } - - compareAopfirstpass = 0; - - /* there is a bug when comparing operands with size > 1, - * because higher bytes can be equal and test should be performed - * to the next lower byte, current algorithm, considers operands - * inequal in these cases! -- VR 20041107 */ + /* if left is same as result */ + if(pic16_sameRegs(AOP(result),AOP(left))){ + int know_W = -1; + for(;size--; offset++,lit>>=8) { + if(AOP_TYPE(right) == AOP_LIT){ + switch(lit & 0xff) { + case 0x00: + /* and'ing with 0 has clears the result */ +// pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE)); + pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset)); + break; + case 0xff: + /* and'ing with 0xff is a nop when the result and left are the same */ + break; - if(pcop) - pic16_emitpcode(op, pcop); - else - pic16_emitpcode(op, pic16_popGet(AOP(oper), offset)); + default: + { + int p = pic16_my_powof2( (~lit) & 0xff ); + if(p>=0) { + /* only one bit is set in the literal, so use a bcf instruction */ +// pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p); + pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER)); + } else { + pic16_emitcode("movlw","0x%x", (lit & 0xff)); + pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE)); + if(know_W != (lit&0xff)) + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); + know_W = lit &0xff; + pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset)); + } + } + } + } else { + if (AOP_TYPE(left) == AOP_ACC) { + pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset)); + } else { + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset)); + pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset)); - if((!sign || !offset) && AOP_SIZE(result)) { - if(!ifx) { - if(pcop2) - pic16_emitpcode(POC_CLRF, pcop2); - else - emitCLRC; - } else { - if(pcop2) - pic16_emitpcode(POC_SETF, pcop2); - else - emitSETC; + } + } } - /* don't emit final branch (offset == 0) */ - if(offset) { - - if(pcop2) - pic16_emitpcode(POC_RRCF, pcop2); - - pic16_emitpcode(POC_BNC, pic16_popGetLabel(falselbl->key)); - } } else { - if((ifx && (IC_TRUE(ifx)!=NULL)) || (sign && !offset)) { - DEBUGpic16_emitcode ("; +++","%s: %d: ifx = %p, IC_TRUE(ifx) = %d, sign = %d, offset = %d", - __FUNCTION__, __LINE__, ifx, (ifx&&IC_TRUE(ifx)), sign, offset); - - truelbl = newiTempLabel( NULL ); - pic16_emitpcode(POC_BRA, pic16_popGetLabel(truelbl->key)); - if((!ifx || !IC_TRUE(ifx)) && (sign && !offset)) - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key)); - else - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key)); - pic16_emitpLabel(truelbl->key); + // 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) + pic16_emitcode("setb","c"); + while(sizer--){ + MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE)); + pic16_emitcode("anl","a,%s", + pic16_aopGet(AOP(left),offset,FALSE,FALSE)); + pic16_emitcode("jnz","%05d_DS_",tlbl->key+100); + offset++; + } + if(size){ + CLRC; + pic16_emitcode("","%05d_DS_:",tlbl->key+100); + pic16_outBitC(result); + } else if(ifx) + jmpTrueOrFalse(ifx, tlbl); } else { - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(resIfx->lbl->key)); + for(;(size--);offset++) { + // normal case + // result = left & right + if(AOP_TYPE(right) == AOP_LIT){ + int t = (lit >> (offset*8)) & 0x0FFL; + switch(t) { + case 0x00: + pic16_emitcode("clrf","%s", + pic16_aopGet(AOP(result),offset,FALSE,FALSE)); + pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset)); + break; + case 0xff: + pic16_emitcode("movf","%s,w", + pic16_aopGet(AOP(left),offset,FALSE,FALSE)); + pic16_emitcode("movwf","%s", + pic16_aopGet(AOP(result),offset,FALSE,FALSE)); + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset)); + break; + default: + pic16_emitcode("movlw","0x%x",t); + pic16_emitcode("andwf","%s,w", + pic16_aopGet(AOP(left),offset,FALSE,FALSE)); + pic16_emitcode("movwf","%s", + pic16_aopGet(AOP(result),offset,FALSE,FALSE)); + + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t)); + pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset)); + } + continue; + } + + if (AOP_TYPE(left) == AOP_ACC) { + pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); + pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset)); + } else { + pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); + pic16_emitcode("andwf","%s,w", + pic16_aopGet(AOP(left),offset,FALSE,FALSE)); + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset)); + pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset)); + } + pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset)); + } } } + +release : + pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(result,NULL,ic,TRUE); } -static void genCmp (operand *left, operand *right, - operand *result, iCode *ifx, int sign) +/*-----------------------------------------------------------------*/ +/* genOr - code for or */ +/*-----------------------------------------------------------------*/ +static void genOr (iCode *ic, iCode *ifx) { - int size, cmpop=1; - long lit = 0L; - resolvedIfx rFalseIfx; - symbol *falselbl, *tlbl; - - FENTRY; - - DEBUGpic16_pic16_AopType(__LINE__,left,right,result); + operand *left, *right, *result; + int size, offset = 0; + unsigned long lit = 0L; + resolvedIfx rIfx; - resolveIfx(&rFalseIfx, ifx); - size = max(AOP_SIZE(left), AOP_SIZE(right)); + FENTRY; - /* if left & right are bit variables */ - if(AOP_TYPE(left) == AOP_CRY - && AOP_TYPE(right) == AOP_CRY ) { + pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE); + pic16_aopOp ((right= IC_RIGHT (ic)), ic, FALSE); + pic16_aopOp ((result=IC_RESULT (ic)), ic, TRUE); - pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); - pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir); + resolveIfx (&rIfx, ifx); - werror(W_POSSBUG2, __FILE__, __LINE__); - exit(EXIT_FAILURE); + /* if left is a literal & right is not then exchange them */ + if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) || + AOP_NEEDSACC (left)) + { + operand *tmp = right; + right = left; + left = tmp; } - /* if literal is on the right then swap with left */ - if((AOP_TYPE(right) == AOP_LIT)) { - operand *tmp = right ; -// unsigned long mask = (0x100 << (8*(size-1))) - 1; - - lit = ulFromVal (AOP(right)->aopu.aop_lit); - -// lit = (lit - 1) & mask; - right = left; - left = tmp; - rFalseIfx.condition ^= 1; /* reverse compare */ - } else - if ((AOP_TYPE(left) == AOP_LIT)) { - /* float compares are handled by support functions */ - lit = ulFromVal(AOP(left)->aopu.aop_lit); + /* if result = right then exchange them */ + if (pic16_sameRegs (AOP (result), AOP (right))) + { + operand *tmp = right; + right = left; + left = tmp; } - /* actual comparing algorithm */ -// size = AOP_SIZE( right ); + /* 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; + } - falselbl = newiTempLabel( NULL ); - if(AOP_TYPE(left) == AOP_LIT) { - /* compare to literal */ - DEBUGpic16_emitcode ("; ***","%s: %d: compare to literal", __FUNCTION__, __LINE__); + DEBUGpic16_pic16_AopType (__LINE__, left, right, result); - if(sign) { - pCodeOp *pct, *pct2; - symbol *tlbl1; + if (AOP_TYPE (right) == AOP_LIT) + lit = ulFromVal (AOP (right)->aopu.aop_lit); - /* signed compare */ - DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__); + size = AOP_SIZE (result); - /* using PRODL:PRODH as a temporary register here */ - pct = pic16_popCopyReg(&pic16_pc_prodl); - pct2 = pic16_popCopyReg(&pic16_pc_prodh); - tlbl = newiTempLabel( NULL ); + // 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) + pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); + //pic16_emitcode("bsf","(%s >> 3), (%s & 7)", + // AOP(result)->aopu.aop_dir, + // AOP(result)->aopu.aop_dir); + else if(ifx) + continueIfTrue(ifx); + goto release; + } + } else { + // lit == 0 => result = left + if(size && pic16_sameRegs(AOP(result),AOP(left))) + goto release; + pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__); + } + } else { + if (AOP_TYPE(right) == AOP_CRY){ + if(pic16_sameRegs(AOP(result),AOP(left))){ + // c = bit | bit; + pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); - /* first compare signs: - * a. if both are positive, compare just like unsigned - * b. if both are negative, invert cmpop, compare just like unsigned - * c. if different signs, determine the result directly */ + } else { + if( AOP_TYPE(result) == AOP_ACC) { + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0)); + pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0)); + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1)); - size--; + } else { -#if 1 - /* { */ - tlbl1 = newiTempLabel( NULL ); -// pic16_emitpcode(POC_RLCFW, pic16_popGet( AOP(right), size)); /* move sign to carry */ + pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0)); + pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); - if(lit > 0) { + } + } + } else { + // c = bit | val; + symbol *tlbl = newiTempLabel(NULL); + pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__); - /* literal is zero or positive: - * a. if carry is zero, too, continue compare, - * b. if carry is set, then continue depending on cmpop ^ condition: - * 1. '<' return false (literal < variable), - * 2. '>' return true (literal > variable) */ -// pic16_emitpcode(POC_BNC, pic16_popGetLabel( tlbl1->key )); - pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7)); + pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0)); + if( AOP_TYPE(right) == AOP_ACC) { + pic16_emitpcode(POC_IORLW, pic16_popGetLit(0)); + emitSKPNZ; + pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0)); + pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); + } - if(cmpop ^ rFalseIfx.condition)pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key )); - else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key )); - } else - if(lit < 0) { - /* literal is negative: - * a. if carry is set, too, continue compare, - * b. if carry is zero, then continue depending on cmpop ^ condition: - * 1. '<' return true (literal < variable), - * 2. '>' return false (literal > variable) */ -// pic16_emitpcode(POC_BC, pic16_popGetLabel( tlbl1->key )); - pic16_emitpcode(POC_BTFSS, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7)); - if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key )); - else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key)); - } -#if 1 - else { - /* lit == 0 */ - pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(right), size), 7)); + if(!((AOP_TYPE(result) == AOP_CRY) && ifx)) + pic16_emitcode(";XXX setb","c"); + pic16_emitcode(";XXX jb","%s,%05d_DS_", + AOP(left)->aopu.aop_dir,tlbl->key+100); + pic16_toBoolean(right); + pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100); + if((AOP_TYPE(result) == AOP_CRY) && ifx){ + jmpTrueOrFalse(ifx, tlbl); + goto release; + } else { + CLRC; + pic16_emitcode("","%05d_DS_:",tlbl->key+100); + } + } + } + // bit = c + // val = c + if(size) + pic16_outBitC(result); + // if(bit | ...) + else if((AOP_TYPE(result) == AOP_CRY) && ifx) + genIfxJump(ifx, "c"); + goto release ; + } - if(!(cmpop ^ rFalseIfx.condition))pic16_emitpcode(POC_GOTO, pic16_popGetLabel( tlbl->key )); - else pic16_emitpcode(POC_GOTO, pic16_popGetLabel( rFalseIfx.lbl->key)); + // 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 (IS_OP_VOLATILE(left)) { + pic16_mov2w_volatile(AOP(left)); + } // if + if (lit) + { + if (rIfx.condition) + pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */ + ifx->generated = 1; } -#endif - - - pic16_emitpLabel( tlbl1->key ); -#endif /* } */ - - compareAopfirstpass=1; -// pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80)); -// pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size)); -// pic16_emitpcode(POC_MOVWF, pct); - -// pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80)); - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size))); -// compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl); - compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl); + else + wassert (0); - /* generic case */ - while( size-- ) { -// pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80)); -// pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0)); -// pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right), size)); -// pic16_emitpcode(POC_MOVWF, pct); + goto release; + } -// pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x80)); - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size) + 0x0)); - compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, pct2, tlbl); -// compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl); -// compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl); + /* if left is same as result */ + if(pic16_sameRegs(AOP(result),AOP(left))){ + int know_W = -1; + for(;size--; offset++,lit>>=8) { + if(AOP_TYPE(right) == AOP_LIT){ + if(((lit & 0xff) == 0) && !IS_OP_VOLATILE(left)) { + /* or'ing with 0 has no effect */ + continue; + } else { + int p = pic16_my_powof2(lit & 0xff); + if(p>=0) { + /* only one bit is set in the literal, so use a bsf instruction */ + pic16_emitpcode(POC_BSF, + pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER)); + } else { + if(know_W != (lit & 0xff)) + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); + know_W = lit & 0xff; + pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset)); } - if(ifx)ifx->generated = 1; - - if(AOP_SIZE(result)) { - pic16_emitpLabel(tlbl->key); - pic16_emitpLabel(falselbl->key); - pic16_outBitOp( result, pct2 ); - } else { - pic16_emitpLabel(tlbl->key); } } else { + if (AOP_TYPE(left) == AOP_ACC) { + pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset)); + } else { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset)); + pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset)); + } + } + } + } 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)); + pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__); - /* unsigned compare */ - DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__); - - compareAopfirstpass=1; - while(size--) { - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(BYTEofLONG(lit, size))); - compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL); + if(size) + pic16_emitcode(";XXX setb","c"); + while(sizer--){ + MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE)); + pic16_emitcode(";XXX orl","a,%s", + pic16_aopGet(AOP(left),offset,FALSE,FALSE)); + pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100); + offset++; + } + if(size){ + CLRC; + pic16_emitcode("","%05d_DS_:",tlbl->key+100); + pic16_outBitC(result); + } else if(ifx) + jmpTrueOrFalse(ifx, tlbl); + } else for(;(size--);offset++){ + // normal case + // result = left & right + if(AOP_TYPE(right) == AOP_LIT){ + int t = (lit >> (offset*8)) & 0x0FFL; + switch(t) { + case 0x00: + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); + break; + default: + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t)); + pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); + } + continue; } - if(ifx)ifx->generated = 1; - if(AOP_SIZE(result)) { - pic16_emitpLabel(falselbl->key); - pic16_outBitC( result ); + // faster than result <- left, anl result,right + // and better if result is SFR + if (AOP_TYPE(left) == AOP_ACC) { + pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset)); + } else { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset)); + pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset)); } - + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); } - } else { - /* compare registers */ - DEBUGpic16_emitcode ("; ***","%s: %d: compare registers", __FUNCTION__, __LINE__); + } +release : + pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(result,NULL,ic,TRUE); +} - if(sign) { - pCodeOp *pct, *pct2; +/*-----------------------------------------------------------------*/ +/* genXor - code for xclusive or */ +/*-----------------------------------------------------------------*/ +static void genXor (iCode *ic, iCode *ifx) +{ + operand *left, *right, *result; + int size, offset = 0; + unsigned long lit = 0L; + resolvedIfx rIfx; - /* signed compare */ - DEBUGpic16_emitcode ("; ***","%s: %d: signed compare", __FUNCTION__, __LINE__); + FENTRY; - pct = pic16_popCopyReg(&pic16_pc_prodl); /* first temporary register */ - pct2 = pic16_popCopyReg(&pic16_pc_prodh); /* second temporary register */ - tlbl = newiTempLabel( NULL ); + pic16_aopOp ((left = IC_LEFT (ic)), ic, FALSE); + pic16_aopOp ((right = IC_RIGHT (ic)), ic, FALSE); + pic16_aopOp ((result = IC_RESULT (ic)), ic, TRUE); - compareAopfirstpass=1; + resolveIfx (&rIfx,ifx); - size--; - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size)); -// pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0)); - pic16_emitpcode(POC_MOVWF, pct); + /* 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) || + (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))) + { + operand *tmp = right; + right = left; + left = tmp; + } - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size)); -// pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0)); + /* if result = right then exchange them */ + if (pic16_sameRegs (AOP (result), AOP (right))) + { + operand *tmp = right ; + right = left; + left = tmp; + } - /* WREG already holds left + 0x80 */ - compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl); + /* 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; + } - while( size-- ) { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), size)); -// pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0)); - pic16_emitpcode(POC_MOVWF, pct); + if (AOP_TYPE (right) == AOP_LIT) + lit = ulFromVal (AOP (right)->aopu.aop_lit); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size)); -// pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x0)); + size = AOP_SIZE (result); - /* WREG already holds left + 0x80 */ - compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, pct, pct2, tlbl); -// compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 0, pct, pct2, tlbl); + // 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) + { + pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result), offset)); + } + else if (ifx) + continueIfTrue(ifx); + goto release; + } + pic16_emitcode("setb", "c"); + } + else + { + // lit == (0 or 1) + if (lit == 0) + { + // lit == 0, result = left + if (size && pic16_sameRegs(AOP(result), AOP(left))) + goto release; + pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir); + } + else + { + // lit == 1, result = not(left) + if (size && pic16_sameRegs(AOP(result), AOP(left))) + { + pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result), offset)); + pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result), offset)); + pic16_emitcode("cpl", "%s", AOP(result)->aopu.aop_dir); + goto release; + } + else + { + pic16_emitcode("mov", "c,%s", AOP(left)->aopu.aop_dir); + pic16_emitcode("cpl", "c"); + } + } + } + } + else + { + // right != literal + symbol *tlbl = newiTempLabel(NULL); + if (AOP_TYPE(right) == AOP_CRY) + { + // c = bit ^ bit; + pic16_emitcode("mov", "c,%s", AOP(right)->aopu.aop_dir); + } + else + { + int sizer = AOP_SIZE(right); + // c = bit ^ val + // if val>>1 != 0, result = 1 + pic16_emitcode("setb", "c"); + while (sizer) + { + MOVA(pic16_aopGet(AOP(right), sizer - 1, FALSE, FALSE)); + if (sizer == 1) + // test the msb of the lsb + pic16_emitcode("anl", "a,#0xfe"); + pic16_emitcode("jnz", "%05d_DS_", tlbl->key+100); + sizer--; + } + // val = (0,1) + pic16_emitcode("rrc", "a"); + } + pic16_emitcode("jnb", "%s,%05d_DS_", AOP(left)->aopu.aop_dir, (tlbl->key + 100)); + pic16_emitcode("cpl", "c"); + pic16_emitcode("", "%05d_DS_:", (tlbl->key + 100)); } + // bit = c + // val = c + if (size) + pic16_outBitC(result); + // if(bit | ...) + else if ((AOP_TYPE(result) == AOP_CRY) && ifx) + genIfxJump(ifx, "c"); + goto release; + } - if(ifx)ifx->generated = 1; + // 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)) + { + symbol *tlbl = newiTempLabel (NULL); + int sizel; - if(AOP_SIZE(result)) { - pic16_emitpLabel(tlbl->key); - pic16_emitpLabel(falselbl->key); - pic16_outBitOp( result, pct2 ); - } else { - pic16_emitpLabel(tlbl->key); - } + if (size) + emitSETC; - } else { - /* unsigned compare */ - DEBUGpic16_emitcode ("; ***","%s: %d: unsigned compare", __FUNCTION__, __LINE__); + for (sizel = AOP_SIZE(left); sizel--; ++offset, lit >>= 8) + { + unsigned char bytelit = lit; - compareAopfirstpass=1; - while(size--) { + switch (bytelit) + { + case 0xff: + pic16_emitpcode (POC_COMFW, pic16_popGet (AOP (left), offset)); + break; - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), size)); - compareAop(&rFalseIfx, ifx, falselbl, right, size, result, sign, 1, NULL, NULL, NULL); + case 0x00: + pic16_emitpcode (POC_MOVFW, pic16_popGet (AOP (left), offset)); + break; + default: + pic16_emitpcode (POC_MOVLW, pic16_popGetLit (bytelit)); + pic16_emitpcode (POC_XORFW, pic16_popGet (AOP (left), offset)); + break; + } + if (sizel) + { + if (rIfx.condition) + { + /* rIfx.lbl might be far away... */ + emitSKPZ; + pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); /* to false */ + } + else + { + pic16_emitpcode (POC_BNZ, pic16_popGetLabel (tlbl->key)); /* to true */ + } + } + else + { + /* last non null byte */ + if (rIfx.condition) + emitSKPZ; + else + emitSKPNZ; + } } - if(ifx)ifx->generated = 1; - if(AOP_SIZE(result)) { - - pic16_emitpLabel(falselbl->key); - pic16_outBitC( result ); + // bit = left ^ literal + if (size) + { + emitCLRC; + pic16_emitpLabel (tlbl->key); + } + // if (left ^ literal) + else + { + if (ifx) + { + pic16_emitpcode (POC_GOTO, pic16_popGetLabel (rIfx.lbl->key)); + ifx->generated = 1; + } + pic16_emitpLabel (tlbl->key); + goto release; } - } - } -} + pic16_outBitC (result); + goto release; + } -#endif /* } */ + if (pic16_sameRegs(AOP(result), AOP(left))) + { + /* if left is same as result */ + for (; size--; offset++) + { + if (AOP_TYPE(right) == AOP_LIT) + { + int t = (lit >> (offset * 8)) & 0x0FFL; + if (t == 0x00L) + continue; + else + { + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t)); + pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset)); + } + } + else + { + if (AOP_TYPE(left) == AOP_ACC) + pic16_emitcode("xrl", "a,%s", pic16_aopGet(AOP(right), offset, FALSE, FALSE)); + else + { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset)); + pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(left), offset)); + } + } + } + } + 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) + pic16_emitcode("setb", "c"); + while (sizer--) + { + if ((AOP_TYPE(right) == AOP_LIT) && + (((lit >> (offset*8)) & 0x0FFL) == 0x00L)) + { + MOVA(pic16_aopGet(AOP(left), offset, FALSE, FALSE)); + } + else + { + MOVA(pic16_aopGet(AOP(right), offset, FALSE, FALSE)); + pic16_emitcode("xrl", "a,%s", + pic16_aopGet(AOP(left), offset, FALSE, FALSE)); + } + pic16_emitcode("jnz", "%05d_DS_", tlbl->key + 100); + offset++; + } + if (size) + { + CLRC; + pic16_emitcode("", "%05d_DS_:", tlbl->key + 100); + pic16_outBitC(result); + } + else if (ifx) + jmpTrueOrFalse(ifx, tlbl); + } + else + { + for (; (size--); offset++) + { + // normal case + // result = left ^ right + if (AOP_TYPE(right) == AOP_LIT) + { + int t = (lit >> (offset * 8)) & 0x0FFL; + switch(t) + { + case 0x00: + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); + break; + + case 0xff: + pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(left), offset)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); + break; + + default: + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t)); + pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); + } + continue; + } + // faster than result <- left, anl result,right + // and better if result is SFR + if (AOP_TYPE(left) == AOP_ACC) + { + pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), offset)); + } + else + { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset)); + pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left), offset)); + } + if ( AOP_TYPE(result) != AOP_ACC) + { + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); + } + } + } + } +release : + pic16_freeAsmop(left, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(right, NULL, ic, (RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(result, NULL, ic, TRUE); +} /*-----------------------------------------------------------------*/ -/* genCmpGt :- greater than comparison */ +/* genInline - write the inline code out */ /*-----------------------------------------------------------------*/ -static void genCmpGt (iCode *ic, iCode *ifx) +static void genInline (iCode *ic) { - operand *left, *right, *result; - sym_link *letype , *retype; - int sign ; + char *buffer, *bp, *bp1; + bool inComment = FALSE; - FENTRY; + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - left = IC_LEFT(ic); - right= IC_RIGHT(ic); - result = IC_RESULT(ic); + _G.inLine += (!options.asmpeep); - letype = getSpec(operandType(left)); - retype =getSpec(operandType(right)); - sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype)); - /* assign the amsops */ - pic16_aopOp (left,ic,FALSE); - pic16_aopOp (right,ic,FALSE); - pic16_aopOp (result,ic,TRUE); + buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic)); - genCmp(right, left, result, ifx, sign); + while((bp1=strstr(bp, "\\n"))) { + *bp1++ = '\n'; + *bp1++ = ' '; + bp = bp1; + } + bp = bp1 = buffer; - pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(result,NULL,ic,TRUE); -} +#if 0 + /* This is an experimental code for #pragma inline + and is temporarily disabled for 2.5.0 release */ + if(asmInlineMap) + { + symbol *sym; + char *s; + char *cbuf; + int cblen; -/*-----------------------------------------------------------------*/ -/* genCmpLt - less than comparisons */ -/*-----------------------------------------------------------------*/ -static void genCmpLt (iCode *ic, iCode *ifx) -{ - operand *left, *right, *result; - sym_link *letype , *retype; - int sign ; + cbuf = Safe_strdup(buffer); + cblen = strlen(buffer)+1; + memset(cbuf, 0, cblen); - FENTRY; + bp = buffer; + bp1 = cbuf; + while(*bp) { + if(*bp != '%')*bp1++ = *bp++; + else { + int i; - left = IC_LEFT(ic); - right= IC_RIGHT(ic); - result = IC_RESULT(ic); + bp++; + i = *bp - '0'; + if(i>elementsInSet(asmInlineMap))break; - letype = getSpec(operandType(left)); - retype =getSpec(operandType(right)); - sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype)); + bp++; + s = indexSet(asmInlineMap, i); + DEBUGpc("searching symbol s = `%s'", s); + sym = findSym(SymbolTab, NULL, s); - /* assign the amsops */ - pic16_aopOp (left,ic,FALSE); - pic16_aopOp (right,ic,FALSE); - pic16_aopOp (result,ic,TRUE); + if(sym->reqv) { + strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name); + } else { + strcat(bp1, sym->rname); + } - genCmp(left, right, result, ifx, sign); + while(*bp1)bp1++; + } - pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(result,NULL,ic,TRUE); -} + if(strlen(bp1) > cblen - 16) { + int i = strlen(cbuf); + cblen += 50; + cbuf = realloc(cbuf, cblen); + memset(cbuf+i, 0, 50); + bp1 = cbuf + i; + } + } -#if 0 -// not needed ATM -// FIXME reenable literal optimisation when the pic16 port is stable + free(buffer); + buffer = Safe_strdup( cbuf ); + free(cbuf); -/*-----------------------------------------------------------------*/ -/* genc16bit2lit - compare a 16 bit value to a literal */ -/*-----------------------------------------------------------------*/ -static void genc16bit2lit(operand *op, int lit, int offset) -{ - int i; + bp = bp1 = buffer; + } +#endif /* 0 */ - DEBUGpic16_emitcode ("; ***","%s %d, lit = %d",__FUNCTION__,__LINE__,lit); - if( (lit&0xff) == 0) - i=1; - else - i=0; + /* emit each line as a code */ + while (*bp) + { + switch (*bp) + { + case ';': + inComment = TRUE; + ++bp; + break; - switch( BYTEofLONG(lit,i)) { - case 0: - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i)); - break; - case 1: - pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i)); - break; - case 0xff: - pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i)); - break; - default: - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i)); - pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i))); - } + case '\n': + inComment = FALSE; + *bp++ = '\0'; + if (*bp1) + pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process + bp1 = bp; + break; - i ^= 1; + default: + /* Add \n for labels, not dirs such as c:\mydir */ + if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1]))) + { + ++bp; + *bp = '\0'; + ++bp; + /* print label, use this special format with NULL directive + * to denote that the argument should not be indented with tab */ + pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process + bp1 = bp; + } + else + ++bp; + break; + } + } - switch( BYTEofLONG(lit,i)) { - case 0: - pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i)); - break; - case 1: - emitSKPNZ; - pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i)); - break; - case 0xff: - emitSKPNZ; - pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i)); - break; - default: - pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i))); - emitSKPNZ; - pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i)); + if ((bp1 != bp) && *bp1) + pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process - } + Safe_free (buffer); + _G.inLine -= (!options.asmpeep); } -#endif -#if 0 -// not needed ATM /*-----------------------------------------------------------------*/ -/* gencjneshort - compare and jump if not equal */ +/* genRRC - rotate right with carry */ /*-----------------------------------------------------------------*/ -static void gencjne(operand *left, operand *right, operand *result, iCode *ifx) +static void genRRC (iCode *ic) { - int size = max(AOP_SIZE(left),AOP_SIZE(right)); - int offset = 0; - int res_offset = 0; /* the result may be a different size then left or right */ - int res_size = AOP_SIZE(result); - resolvedIfx rIfx; - symbol *lbl, *lbl_done; - - unsigned long lit = 0L; - int preserve_result = 0; /* don't touch result before we are done, if left/right == result */ + operand *left , *result ; + int size, same; DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - DEBUGpic16_pic16_AopType(__LINE__,left,right,result); - if(result) - DEBUGpic16_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__); - resolveIfx(&rIfx,ifx); - lbl = newiTempLabel(NULL); - lbl_done = newiTempLabel(NULL); - - - /* 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 = ulFromVal (AOP(right)->aopu.aop_lit); - if ( regsInCommon(left, result) || regsInCommon(right, result) ) - preserve_result = 1; - - if(result && !preserve_result) - { - int i; - for(i = 0; i < AOP_SIZE(result); i++) - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i)); - } + /* rotate right with carry */ + left = IC_LEFT(ic); + result=IC_RESULT(ic); + pic16_aopOp (left,ic,FALSE); + pic16_aopOp (result,ic,TRUE); + DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); - /* if the right side is a literal then anything goes */ - if (AOP_TYPE(right) == AOP_LIT && - AOP_TYPE(left) != AOP_DIR ) { - switch(size) { - case 2: - genc16bit2lit(left, lit, 0); - emitSKPZ; - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); - break; - default: - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - while (size--) { - if(lit & 0xff) { - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff)); - } else { - pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset)); - } + same = pic16_sameRegs(AOP(result),AOP(left)); - emitSKPZ; - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); - offset++; - if(res_offset < res_size-1) - res_offset++; - lit >>= 8; - } - break; - } - } + size = AOP_SIZE(result); - /* 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))) { - //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key; - int lbl_key = lbl->key; - - if(result) { - // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset)); - //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset)); - }else { - DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__); - fprintf(stderr, "%s %d error - expecting result to be non_null\n", - __FUNCTION__,__LINE__); - return; - } + DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same); -/* switch(size) { */ -/* case 2: */ -/* genc16bit2lit(left, lit, 0); */ -/* emitSKPNZ; */ -/* pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */ -/* break; */ -/* default: */ - while (size--) { - int emit_skip=1; - if((AOP_TYPE(left) == AOP_DIR) && - ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) { + /* get the lsb and put it into the carry */ + pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset)); + while(size--) { - } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){ + if(same) { + pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),size)); + } else { + pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),size)); + } + } - switch (lit & 0xff) { - case 0: - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset)); - break; - case 1: - pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset)); - //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset)); - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); - emit_skip=0; - break; - case 0xff: - pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset)); - //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset)); - //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key)); - emit_skip=0; - break; - default: - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff)); - } - lit >>= 8; + pic16_freeAsmop(left,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); +} - } else { - pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset)); - } - if(emit_skip) { - if(AOP_TYPE(result) == AOP_CRY) { - pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__); - if(rIfx.condition) - emitSKPNZ; - else - emitSKPZ; - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key)); - } else { - /* fix me. probably need to check result size too */ - //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0)); - if(rIfx.condition) - emitSKPZ; - else - emitSKPNZ; - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key)); - //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset)); - } - if(ifx) - ifx->generated=1; - } - emit_skip++; - offset++; - if(res_offset < res_size-1) - res_offset++; - } -/* break; */ -/* } */ - } else if(AOP_TYPE(right) == AOP_REG && - AOP_TYPE(left) != AOP_DIR){ +/*-----------------------------------------------------------------*/ +/* genRLC - generate code for rotate left with carry */ +/*-----------------------------------------------------------------*/ +static void genRLC (iCode *ic) +{ + operand *left , *result ; + int size, offset = 0; + int same; - while(size--) { - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset)); - pic16_emitcode(";***","%s %d",__FUNCTION__,__LINE__); - if(rIfx.condition) - emitSKPNZ; - else - emitSKPZ; - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key)); - offset++; - if(res_offset < res_size-1) - res_offset++; - } + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + /* rotate right with carry */ + left = IC_LEFT(ic); + result=IC_RESULT(ic); + pic16_aopOp (left,ic,FALSE); + pic16_aopOp (result,ic,TRUE); - }else{ - /* right is a pointer reg need both a & b */ - while(size--) { - char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE); - if(strcmp(l,"b")) - pic16_emitcode("mov","b,%s",l); - MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100); - offset++; - } - } + DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); - if(result && preserve_result) - { - int i; - for(i = 0; i < AOP_SIZE(result); i++) - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i)); - } + same = pic16_sameRegs(AOP(result),AOP(left)); - pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); + /* move it to the result */ + size = AOP_SIZE(result); - if(result && preserve_result) - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key)); + /* get the msb and put it into the carry */ + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1)); - if(!rIfx.condition) - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key)); + offset = 0 ; - pic16_emitpLabel(lbl->key); + while(size--) { - if(result && preserve_result) - { - int i; - for(i = 0; i < AOP_SIZE(result); i++) - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i)); + if(same) { + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset)); + } else { + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); + } - pic16_emitpLabel(lbl_done->key); - } + offset++; + } - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if(ifx) - ifx->generated = 1; + pic16_freeAsmop(left,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); } -#endif -#if 0 + +/* gpasm can get the highest order bit with HIGH/UPPER + * so the following probably is not needed -- VR */ + /*-----------------------------------------------------------------*/ -/* gencjne - compare and jump if not equal */ +/* genGetHbit - generates code get highest order bit */ /*-----------------------------------------------------------------*/ -static void gencjne(operand *left, operand *right, iCode *ifx) +static void genGetHbit (iCode *ic) { - symbol *tlbl = newiTempLabel(NULL); + operand *left, *result; + left = IC_LEFT(ic); + result=IC_RESULT(ic); + pic16_aopOp (left,ic,FALSE); + pic16_aopOp (result,ic,FALSE); DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - gencjneshort(left, right, lbl); - - pic16_emitcode("mov","a,%s",one); - pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100); - pic16_emitcode("","%05d_DS_:",lbl->key+100); - pic16_emitcode("clr","a"); - pic16_emitcode("","%05d_DS_:",tlbl->key+100); + /* get the highest order byte into a */ + MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE)); + if(AOP_TYPE(result) == AOP_CRY){ + pic16_emitcode("rlc","a"); + pic16_outBitC(result); + } + else{ + pic16_emitcode("rl","a"); + pic16_emitcode("anl","a,#0x01"); + pic16_outAcc(result); + } - pic16_emitpLabel(lbl->key); - pic16_emitpLabel(tlbl->key); + pic16_freeAsmop(left,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); } -#endif - +#if 0 /*-----------------------------------------------------------------*/ -/* is_LitOp - check if operand has to be treated as literal */ +/* AccRol - rotate left accumulator by known count */ /*-----------------------------------------------------------------*/ -static bool is_LitOp(operand *op) +static void AccRol (int shCount) { - return ((AOP_TYPE(op) == AOP_LIT) - || ( (AOP_TYPE(op) == AOP_PCODE) - && ( (AOP(op)->aopu.pcop->type == PO_LITERAL) - || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ))); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + shCount &= 0x0007; // shCount : 0..7 + switch(shCount){ + case 0 : + break; + case 1 : + pic16_emitcode("rl","a"); + break; + case 2 : + pic16_emitcode("rl","a"); + pic16_emitcode("rl","a"); + break; + case 3 : + pic16_emitcode("swap","a"); + pic16_emitcode("rr","a"); + break; + case 4 : + pic16_emitcode("swap","a"); + break; + case 5 : + pic16_emitcode("swap","a"); + pic16_emitcode("rl","a"); + break; + case 6 : + pic16_emitcode("rr","a"); + pic16_emitcode("rr","a"); + break; + case 7 : + pic16_emitcode("rr","a"); + break; + } } +#endif /*-----------------------------------------------------------------*/ -/* is_LitAOp - check if operand has to be treated as literal */ +/* AccLsh - left shift accumulator by known count */ /*-----------------------------------------------------------------*/ -static bool is_LitAOp(asmop *aop) +static void AccLsh (int shCount, int doMask) { - return ((aop->type == AOP_LIT) - || ( (aop->type == AOP_PCODE) - && ( (aop->aopu.pcop->type == PO_LITERAL) - || (aop->aopu.pcop->type == PO_IMMEDIATE) ))); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + switch(shCount){ + case 0 : + return; + break; + case 1 : + pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + break; + case 2 : + pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + break; + case 3 : + pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + break; + case 4 : + pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg)); + break; + case 5 : + pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + break; + case 6 : + pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + break; + case 7 : + pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + break; + } + if (doMask) { + /* no masking is required in genPackBits */ + pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount])); + } } - - /*-----------------------------------------------------------------*/ -/* genCmpEq - generates code for equal to */ +/* AccRsh - right shift accumulator by known count */ /*-----------------------------------------------------------------*/ -static void genCmpEq (iCode *ic, iCode *ifx) +static void AccRsh (int shCount, int andmask) { - operand *left, *right, *result; - symbol *falselbl = newiTempLabel(NULL); - symbol *donelbl = newiTempLabel(NULL); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + assert ((shCount >= 0) && (shCount <= 8)); + switch (shCount) { + case 0 : + return; break; + case 1 : + pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + break; + case 2 : + pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + break; + case 3 : + pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + break; + case 4 : + pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg)); + break; + case 5 : + pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + break; + case 6 : + pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + break; + case 7 : + pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); + break; + default: + // Rotating by 8 is a NOP. + break; + } - int preserve_result = 0; - int generate_result = 0; - int i=0; - unsigned long lit = -1; + if (andmask) + pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount])); + else + DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__); +} - FENTRY; +/*-----------------------------------------------------------------*/ +/* shiftR1Left2Result - shift right one byte from left to result */ +/*-----------------------------------------------------------------*/ +static void shiftR1Left2ResultSigned (operand *left, int offl, + operand *result, int offr, + int shCount) +{ + int same; - pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE); - pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE); - pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + assert ((shCount >= 0) && (shCount <= 8)); - DEBUGpic16_pic16_AopType(__LINE__,left,right,result); + same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr); - if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) ) - { - werror(W_POSSBUG2, __FILE__, __LINE__); - DEBUGpic16_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__); - fprintf(stderr, "%s %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__); - goto release; + /* Do NOT use result for intermediate results, it might be an SFR!. */ + switch (shCount) { + case 0: + if (!same) { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); } + break; - if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC)) - { - operand *tmp = right ; - right = left; - left = tmp; + case 1: + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), offl)); + if (same) + pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr)); + else { + pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); } + break; - if (AOP_TYPE(right) == AOP_LIT) { - lit = ulFromVal (AOP(right)->aopu.aop_lit); - } + case 2: + pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f)); // keep sign bit in W<5> + pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 5)); + pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xc0)); // sign-extend + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - if ( regsInCommon(left, result) || regsInCommon(right, result) ) - preserve_result = 1; + case 3: + pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); // keep sign in W<4> + pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 4)); + pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); // sign-extend + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - if(result && AOP_SIZE(result)) - generate_result = 1; + case 4: + pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); // keep sign in W<3> + pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 3)); + pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); // sign-extend + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - if(generate_result && !preserve_result) - { - for(i = 0; i < AOP_SIZE(result); i++) - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i)); - } + case 5: + pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); // keep sign in W<2> + pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 2)); + pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); // sign-extend + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - assert( AOP_SIZE(left) == AOP_SIZE(right) ); - for(i=0; i < AOP_SIZE(left); i++) - { - if(AOP_TYPE(left) != AOP_ACC) - { - if(is_LitOp(left)) - pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i)); - else - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i)); - } - if(is_LitOp(right)) { - if (is_LitOp(left) || (0 != ((lit >> (8*i))&0x00FF))) { - pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); - } - } else - pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); + case 6: + pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03)); // keep sign bit in W<1> + pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(PCOP(&pic16_pc_wreg), 1)); + pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xfc)); // sign-extend + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key)); - } + case 7: + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00)); + pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), offl), 7)); + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - // result == true + default: + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr)); + break; + } +} - if(generate_result && preserve_result) - { - for(i = 0; i < AOP_SIZE(result); i++) - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i)); - } +/*-----------------------------------------------------------------*/ +/* shiftR1Left2Result - shift right one byte from left to result */ +/*-----------------------------------------------------------------*/ +static void shiftR1Left2Result (operand *left, int offl, + operand *result, int offr, + int shCount, int sign) +{ + int same; - if(generate_result) - pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + assert ((shCount >= 0) && (shCount <= 8)); - if(generate_result && preserve_result) - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key)); + same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr); - if(ifx && IC_TRUE(ifx)) - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); + /* Copy the msb into the carry if signed. */ + if (sign) { + shiftR1Left2ResultSigned(left, offl, result, offr, shCount); + return; + } - if(ifx && IC_FALSE(ifx)) - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key)); + /* Do NOT use result for intermediate results, it might be an SFR!. */ + switch (shCount) { + case 0: + if (!same) { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + } + break; - pic16_emitpLabel(falselbl->key); + case 1: + if (same) { + emitCLRC; + pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result), offr)); + } else { + pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x7f)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + } + break; - // result == false + case 2: + pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x3f)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - if(ifx && IC_FALSE(ifx)) - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); + case 3: + pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - if(generate_result && preserve_result) - { - for(i = 0; i < AOP_SIZE(result); i++) - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i)); - } + case 4: + pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - pic16_emitpLabel(donelbl->key); + case 5: + pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - if(ifx) - ifx->generated = 1; - -release: - pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(result,NULL,ic,TRUE); - -} - - -#if 0 -// old version kept for reference - -/*-----------------------------------------------------------------*/ -/* genCmpEq - generates code for equal to */ -/*-----------------------------------------------------------------*/ -static void genCmpEq (iCode *ic, iCode *ifx) -{ - operand *left, *right, *result; - unsigned long lit = 0L; - int size,offset=0; - symbol *falselbl = newiTempLabel(NULL); - - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - if(ifx) - DEBUGpic16_emitcode ("; ifx is non-null",""); - else - DEBUGpic16_emitcode ("; ifx is null",""); - - pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE); - pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE); - pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); - - size = max(AOP_SIZE(left),AOP_SIZE(right)); - - DEBUGpic16_pic16_AopType(__LINE__,left,right,result); - - /* 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 *tmp = right ; - right = left; - left = tmp; - } - - - if(ifx && !AOP_SIZE(result)){ - symbol *tlbl; - DEBUGpic16_emitcode ("; ***","%s %d CASE 1",__FUNCTION__,__LINE__); - /* if they are both bit variables */ - if (AOP_TYPE(left) == AOP_CRY && - ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) { - DEBUGpic16_emitcode ("; ***","%s %d CASE 11",__FUNCTION__,__LINE__); - if(AOP_TYPE(right) == AOP_LIT){ - unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit); - if(lit == 0L){ - pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); - pic16_emitcode("cpl","c"); - } else if(lit == 1L) { - pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); - } else { - pic16_emitcode("clr","c"); - } - /* AOP_TYPE(right) == AOP_CRY */ - } else { - symbol *lbl = newiTempLabel(NULL); - pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); - pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100)); - pic16_emitcode("cpl","c"); - pic16_emitcode("","%05d_DS_:",(lbl->key+100)); - } - /* if true label then we jump if condition - supplied is true */ - tlbl = newiTempLabel(NULL); - if ( IC_TRUE(ifx) ) { - pic16_emitcode("jnc","%05d_DS_",tlbl->key+100); - pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); - } else { - pic16_emitcode("jc","%05d_DS_",tlbl->key+100); - pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100); - } - pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset); - - { - /* left and right are both bit variables, result is carry */ - resolvedIfx rIfx; - - resolveIfx(&rIfx,ifx); - - pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0)); - genSkipz2(&rIfx,0); - } - } else { - - DEBUGpic16_emitcode ("; ***","%s %d CASE 12",__FUNCTION__,__LINE__); - - /* They're not both bit variables. Is the right a literal? */ - if(AOP_TYPE(right) == AOP_LIT) { - lit = ulFromVal (AOP(right)->aopu.aop_lit); - - switch(size) { - - case 1: - switch(lit & 0xff) { - case 1: - if ( IC_TRUE(ifx) ) { - pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset)); - emitSKPNZ; - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); - } else { - pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); - } - break; - case 0xff: - if ( IC_TRUE(ifx) ) { - pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset)); - emitSKPNZ; - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); - } else { - pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); - } - break; - default: - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset)); - if(lit) - pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff)); - genSkip(ifx,'z'); - } // switch lit - - - /* end of size == 1 */ - break; - - case 2: - genc16bit2lit(left,lit,offset); - genSkip(ifx,'z'); - break; - /* end of size == 2 */ - - default: - /* size is 4 */ - if(lit==0) { - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1)); - pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2)); - pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3)); - genSkip(ifx,'z'); - } else { - /* search for patterns that can be optimized */ - - genc16bit2lit(left,lit,0); - lit >>= 16; - if(lit) { - if(IC_TRUE(ifx)) - emitSKPZ; // if hi word unequal - else - emitSKPNZ; // if hi word equal - // fail early - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key)); - genc16bit2lit(left,lit,2); - genSkip(ifx,'z'); - } else { - pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2)); - pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3)); - genSkip(ifx,'z'); - } - } - pic16_emitpLabel(falselbl->key); - break; - - } // switch size - - ifx->generated = 1; - goto release ; - - - } else if(AOP_TYPE(right) == AOP_CRY ) { - /* we know the left is not a bit, but that the right is */ - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS), - pic16_popGet(AOP(right),offset)); - pic16_emitpcode(POC_XORLW,pic16_popGetLit(1)); - - /* if the two are equal, then W will be 0 and the Z bit is set - * we could test Z now, or go ahead and check the high order bytes if - * the variable we're comparing is larger than a byte. */ - - while(--size) - pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset)); - - if ( IC_TRUE(ifx) ) { - emitSKPNZ; - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); - // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset); - } else { - emitSKPZ; - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); - // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset); - } - - } else { - /* They're both variables that are larger than bits */ - int s = size; - - tlbl = newiTempLabel(NULL); - - while(size--) { - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset)); - - if ( IC_TRUE(ifx) ) { - if(size) { - emitSKPZ; - - DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ"); - - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); - pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+pic16_labelOffset); - } else { - emitSKPNZ; - - DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ"); - - - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); - pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+pic16_labelOffset); - } - } else { - emitSKPZ; - - DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ"); - - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key)); - pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+pic16_labelOffset); - } - offset++; - } - if(s>1 && IC_TRUE(ifx)) { - pic16_emitpLabel(tlbl->key); - pic16_emitcode("","_%05d_DS_:",tlbl->key+100+pic16_labelOffset); - } - } - } - /* mark the icode as generated */ - ifx->generated = 1; - goto release ; - } - - /* if they are both bit variables */ - if (AOP_TYPE(left) == AOP_CRY && - ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) { - DEBUGpic16_emitcode ("; ***","%s %d CASE 2",__FUNCTION__,__LINE__); - if(AOP_TYPE(right) == AOP_LIT){ - unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit); - if(lit == 0L){ - pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); - pic16_emitcode("cpl","c"); - } else if(lit == 1L) { - pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); - } else { - pic16_emitcode("clr","c"); - } - /* AOP_TYPE(right) == AOP_CRY */ - } else { - symbol *lbl = newiTempLabel(NULL); - pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); - pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100)); - pic16_emitcode("cpl","c"); - pic16_emitcode("","%05d_DS_:",(lbl->key+100)); - } - /* c = 1 if egal */ - if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){ - pic16_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 */ - pic16_outBitC(result); - } else { - - DEBUGpic16_emitcode ("; ***","%s %d CASE 3",__FUNCTION__,__LINE__); - gencjne(left,right,result,ifx); -/* - if(ifx) - gencjne(left,right,newiTempLabel(NULL)); - else { - if(IC_TRUE(ifx)->key) - gencjne(left,right,IC_TRUE(ifx)->key); - else - gencjne(left,right,IC_FALSE(ifx)->key); - ifx->generated = 1; - goto release ; - } - if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) { - pic16_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) - pic16_outAcc(result); -*/ - /* leave the result in acc */ - } - -release: - pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(result,NULL,ic,TRUE); -} -#endif - -/*-----------------------------------------------------------------*/ -/* ifxForOp - returns the icode containing the ifx for operand */ -/*-----------------------------------------------------------------*/ -static iCode *ifxForOp ( operand *op, iCode *ic ) -{ - FENTRY2; - - /* 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 - ) { - DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__); - return ic->next; - } - - /* - if (ic->next && - ic->next->op == IFX && - IC_COND(ic->next)->key == op->key) { - DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__); - return ic->next; - } - */ - - DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__); - if (ic->next && - ic->next->op == IFX) - DEBUGpic16_emitcode ("; ic-next"," is an IFX"); - - if (ic->next && - ic->next->op == IFX && - IC_COND(ic->next)->key == op->key) { - DEBUGpic16_emitcode ("; "," key is okay"); - DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d", - OP_SYMBOL(op)->liveTo, - ic->next->seq); - } - -#if 0 - /* the code below is completely untested - * it just allows ulong2fs.c compile -- VR */ - - ic = ic->next; - fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n", - __FILE__, __FUNCTION__, __LINE__); - - /* 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; - - if (ic->next && - ic->next->op == IFX && - IC_COND(ic->next)->key == op->key) { - DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__); - return ic->next; - } - - fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n", - __FILE__, __FUNCTION__, __LINE__); - -// return ic->next->next; /* this just might work */ /* FIXME FIXME */ -#endif - - return NULL; -} -/*-----------------------------------------------------------------*/ -/* genAndOp - for && operation */ -/*-----------------------------------------------------------------*/ -static void genAndOp (iCode *ic) -{ - operand *left,*right, *result; -/* symbol *tlbl; */ - - FENTRY; - - /* note here that && operations that are in an - if statement are taken away by backPatchLabels - only those used in arthmetic operations remain */ - pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE); - pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE); - pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); - - DEBUGpic16_pic16_AopType(__LINE__,left,right,result); - - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0)); - - /* if both are bit variables */ -/* if (AOP_TYPE(left) == AOP_CRY && */ -/* AOP_TYPE(right) == AOP_CRY ) { */ -/* pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */ -/* pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */ -/* pic16_outBitC(result); */ -/* } else { */ -/* tlbl = newiTempLabel(NULL); */ -/* pic16_toBoolean(left); */ -/* pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */ -/* pic16_toBoolean(right); */ -/* pic16_emitcode("","%05d_DS_:",tlbl->key+100); */ -/* pic16_outBitAcc(result); */ -/* } */ - - pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(result,NULL,ic,TRUE); -} - - -/*-----------------------------------------------------------------*/ -/* genOrOp - for || operation */ -/*-----------------------------------------------------------------*/ -/* - tsd pic port - - modified this code, but it doesn't appear to ever get called -*/ - -static void genOrOp (iCode *ic) -{ - operand *left,*right, *result; - symbol *tlbl; - - FENTRY; - - /* note here that || operations that are in an - if statement are taken away by backPatchLabels - only those used in arthmetic operations remain */ - pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE); - pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE); - pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); - - DEBUGpic16_pic16_AopType(__LINE__,left,right,result); - - /* if both are bit variables */ - if (AOP_TYPE(left) == AOP_CRY && - AOP_TYPE(right) == AOP_CRY ) { - pic16_emitcode("clrc",""); - pic16_emitcode("btfss","(%s >> 3), (%s & 7)", - AOP(left)->aopu.aop_dir, - AOP(left)->aopu.aop_dir); - pic16_emitcode("btfsc","(%s >> 3), (%s & 7)", - AOP(right)->aopu.aop_dir, - AOP(right)->aopu.aop_dir); - pic16_emitcode("setc",""); - - } else { - tlbl = newiTempLabel(NULL); - pic16_toBoolean(left); - emitSKPZ; - pic16_emitcode("goto","%05d_DS_",tlbl->key+100+pic16_labelOffset); - pic16_toBoolean(right); - pic16_emitcode("","%05d_DS_:",tlbl->key+100+pic16_labelOffset); - - pic16_outBitAcc(result); - } - - pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_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; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - for(idx = 0; idx < 32; idx++) - if(lit == pw[idx]) - return idx+1; - return 0; -} - -/*-----------------------------------------------------------------*/ -/* continueIfTrue - */ -/*-----------------------------------------------------------------*/ -static void continueIfTrue (iCode *ic) -{ - FENTRY; - if(IC_TRUE(ic)) - pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100); - ic->generated = 1; -} - -/*-----------------------------------------------------------------*/ -/* jmpIfTrue - */ -/*-----------------------------------------------------------------*/ -static void jumpIfTrue (iCode *ic) -{ - FENTRY; - if(!IC_TRUE(ic)) - pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100); - ic->generated = 1; -} - -/*-----------------------------------------------------------------*/ -/* jmpTrueOrFalse - */ -/*-----------------------------------------------------------------*/ -static void jmpTrueOrFalse (iCode *ic, symbol *tlbl) -{ - // ugly but optimized by peephole - FENTRY; - if(IC_TRUE(ic)){ - symbol *nlbl = newiTempLabel(NULL); - pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100); - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100); - pic16_emitcode("","%05d_DS_:",nlbl->key+100); - } else { - pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100); - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - } - ic->generated = 1; -} - -/*-----------------------------------------------------------------*/ -/* 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; - resolvedIfx rIfx; - - FENTRY; - - pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE); - pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE); - pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); - - resolveIfx(&rIfx,ifx); - - /* if left is a literal & right is not then exchange them */ - if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) || - AOP_NEEDSACC(left)) { - operand *tmp = right ; - right = left; - left = tmp; - } - - /* if result = right then exchange them */ - if(pic16_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 = ulFromVal (AOP(right)->aopu.aop_lit); - - size = AOP_SIZE(result); - - DEBUGpic16_pic16_AopType(__LINE__,left,right,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 && pic16_sameRegs(AOP(result),AOP(left))) - // no change - goto release; - pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); - } else { - // bit(result) = 0; - if(size && (AOP_TYPE(result) == AOP_CRY)){ - pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir); - goto release; - } - if((AOP_TYPE(result) == AOP_CRY) && ifx){ - jumpIfTrue(ifx); - goto release; - } - pic16_emitcode("clr","c"); - } - } else { - if (AOP_TYPE(right) == AOP_CRY){ - // c = bit & bit; - pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); - pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir); - } else { - // c = bit & val; - MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE)); - // c = lsb - pic16_emitcode("rrc","a"); - pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir); - } - } - // bit = c - // val = c - if(size) - pic16_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(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE)); - // bit = left & 2^n - if(size) - pic16_emitcode("mov","c,acc.%d",posbit&0x07); - // if(left & 2^n) - else{ - if(ifx){ -/* - if(IC_TRUE(ifx)) { - pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0)); - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key)); - } else { - pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0)); - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key)); - } -*/ - DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__); - size = AOP_SIZE(left); - - { - int bp = posbit, ofs=0; - - while(bp > 7) { - bp -= 8; - ofs++; - } - - pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS), - pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0, PO_GPR_REGISTER)); - - } -/* - pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS), - pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0)); -*/ - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key)); - - ifx->generated = 1; - } - goto release; - } - } else { - symbol *tlbl = newiTempLabel(NULL); - int sizel = AOP_SIZE(left); - - if(size) - emitSETC; - - while(sizel--) { - if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L) { - - /* patch provided by Aaron Colwell */ - if((posbit = isLiteralBit(bytelit)) != 0) { - pic16_emitpcode(((rIfx.condition) ? POC_BTFSS : POC_BTFSC ), - pic16_newpCodeOpBit(pic16_aopGet(AOP(left), offset,FALSE,FALSE), - (posbit-1),0, PO_GPR_REGISTER)); - - pic16_emitpcode(POC_BRA, pic16_popGetLabel(tlbl->key)); -// pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key)); - } else { - if (bytelit == 0xff) { - /* Aaron had a MOVF instruction here, changed to MOVFW cause - * a peephole could optimize it out -- VR */ - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset)); - } else { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offset)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(bytelit)); - } - - pic16_emitpcode(((rIfx.condition) ? POC_BZ : POC_BNZ), - pic16_popGetLabel(tlbl->key)); - } - -#if 0 - /* old code, left here for reference -- VR 09/2004 */ - MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - // byte == 2^n ? - if((posbit = isLiteralBit(bytelit)) != 0) - pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100); - else{ - if(bytelit != 0x0FFL) - pic16_emitcode("anl","a,%s", - pic16_aopGet(AOP(right),offset,FALSE,TRUE)); - pic16_emitcode("jnz","%05d_DS_",tlbl->key+100); - } -#endif - } - offset++; - } - // bit = left & literal - if(size) { - emitCLRC; - pic16_emitpLabel(tlbl->key); - } - // if(left & literal) - else { - if(ifx) { - pic16_emitpcode(POC_BRA, pic16_popGetLabel(rIfx.lbl->key)); - ifx->generated = 1; - } - pic16_emitpLabel(tlbl->key); - goto release; - } - } - - pic16_outBitC(result); - goto release ; - } - - /* if left is same as result */ - if(pic16_sameRegs(AOP(result),AOP(left))){ - int know_W = -1; - for(;size--; offset++,lit>>=8) { - if(AOP_TYPE(right) == AOP_LIT){ - switch(lit & 0xff) { - case 0x00: - /* and'ing with 0 has clears the result */ -// pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE)); - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset)); - break; - case 0xff: - /* and'ing with 0xff is a nop when the result and left are the same */ - break; - - default: - { - int p = pic16_my_powof2( (~lit) & 0xff ); - if(p>=0) { - /* only one bit is set in the literal, so use a bcf instruction */ -// pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p); - pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER)); - - } else { - pic16_emitcode("movlw","0x%x", (lit & 0xff)); - pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE)); - if(know_W != (lit&0xff)) - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); - know_W = lit &0xff; - pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset)); - } - } - } - } else { - if (AOP_TYPE(left) == AOP_ACC) { - pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset)); - } else { - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset)); - pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset)); - - } - } - } - - } 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) - pic16_emitcode("setb","c"); - while(sizer--){ - MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - pic16_emitcode("anl","a,%s", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - pic16_emitcode("jnz","%05d_DS_",tlbl->key+100); - offset++; - } - if(size){ - CLRC; - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - pic16_outBitC(result); - } else if(ifx) - jmpTrueOrFalse(ifx, tlbl); - } else { - for(;(size--);offset++) { - // normal case - // result = left & right - if(AOP_TYPE(right) == AOP_LIT){ - int t = (lit >> (offset*8)) & 0x0FFL; - switch(t) { - case 0x00: - pic16_emitcode("clrf","%s", - pic16_aopGet(AOP(result),offset,FALSE,FALSE)); - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset)); - break; - case 0xff: - pic16_emitcode("movf","%s,w", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - pic16_emitcode("movwf","%s", - pic16_aopGet(AOP(result),offset,FALSE,FALSE)); - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset)); - break; - default: - pic16_emitcode("movlw","0x%x",t); - pic16_emitcode("andwf","%s,w", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - pic16_emitcode("movwf","%s", - pic16_aopGet(AOP(result),offset,FALSE,FALSE)); - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t)); - pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset)); - } - continue; - } - - if (AOP_TYPE(left) == AOP_ACC) { - pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset)); - } else { - pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - pic16_emitcode("andwf","%s,w", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset)); - pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset)); - } - pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset)); - } - } - } - - release : - pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_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; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - FENTRY; - - pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE); - pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE); - pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); - - DEBUGpic16_pic16_AopType(__LINE__,left,right,result); - - /* if left is a literal & right is not then exchange them */ - if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) || - AOP_NEEDSACC(left)) { - operand *tmp = right ; - right = left; - left = tmp; - } - - /* if result = right then exchange them */ - if(pic16_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; - } - - DEBUGpic16_pic16_AopType(__LINE__,left,right,result); - - if(AOP_TYPE(right) == AOP_LIT) - lit = ulFromVal (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) - pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); - //pic16_emitcode("bsf","(%s >> 3), (%s & 7)", - // AOP(result)->aopu.aop_dir, - // AOP(result)->aopu.aop_dir); - else if(ifx) - continueIfTrue(ifx); - goto release; - } - } else { - // lit == 0 => result = left - if(size && pic16_sameRegs(AOP(result),AOP(left))) - goto release; - pic16_emitcode(";XXX mov","c,%s %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__); - } - } else { - if (AOP_TYPE(right) == AOP_CRY){ - if(pic16_sameRegs(AOP(result),AOP(left))){ - // c = bit | bit; - pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); - - pic16_emitcode("bcf","(%s >> 3), (%s & 7)", - AOP(result)->aopu.aop_dir, - AOP(result)->aopu.aop_dir); - pic16_emitcode("btfsc","(%s >> 3), (%s & 7)", - AOP(right)->aopu.aop_dir, - AOP(right)->aopu.aop_dir); - pic16_emitcode("bsf","(%s >> 3), (%s & 7)", - AOP(result)->aopu.aop_dir, - AOP(result)->aopu.aop_dir); - } else { - if( AOP_TYPE(result) == AOP_ACC) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0)); - pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1)); - - } else { - - pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); - - pic16_emitcode("bcf","(%s >> 3), (%s & 7)", - AOP(result)->aopu.aop_dir, - AOP(result)->aopu.aop_dir); - pic16_emitcode("btfss","(%s >> 3), (%s & 7)", - AOP(right)->aopu.aop_dir, - AOP(right)->aopu.aop_dir); - pic16_emitcode("btfsc","(%s >> 3), (%s & 7)", - AOP(left)->aopu.aop_dir, - AOP(left)->aopu.aop_dir); - pic16_emitcode("bsf","(%s >> 3), (%s & 7)", - AOP(result)->aopu.aop_dir, - AOP(result)->aopu.aop_dir); - } - } - } else { - // c = bit | val; - symbol *tlbl = newiTempLabel(NULL); - pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__); - - - pic16_emitpcode(POC_BCF, pic16_popGet(AOP(result),0)); - if( AOP_TYPE(right) == AOP_ACC) { - pic16_emitpcode(POC_IORLW, pic16_popGetLit(0)); - emitSKPNZ; - pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0)); - } - - - - if(!((AOP_TYPE(result) == AOP_CRY) && ifx)) - pic16_emitcode(";XXX setb","c"); - pic16_emitcode(";XXX jb","%s,%05d_DS_", - AOP(left)->aopu.aop_dir,tlbl->key+100); - pic16_toBoolean(right); - pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100); - if((AOP_TYPE(result) == AOP_CRY) && ifx){ - jmpTrueOrFalse(ifx, tlbl); - goto release; - } else { - CLRC; - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - } - } - } - // bit = c - // val = c - if(size) - pic16_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){ - pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__); - // result = 1 - if(size) - pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir); - else - continueIfTrue(ifx); - goto release; - } else { - pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__); - // lit = 0, result = boolean(left) - if(size) - pic16_emitcode(";XXX setb","c"); - pic16_toBoolean(right); - if(size){ - symbol *tlbl = newiTempLabel(NULL); - pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100); - CLRC; - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - } else { - genIfxJump (ifx,"a"); - goto release; - } - } - pic16_outBitC(result); - goto release ; - } - - /* if left is same as result */ - if(pic16_sameRegs(AOP(result),AOP(left))){ - int know_W = -1; - for(;size--; offset++,lit>>=8) { - if(AOP_TYPE(right) == AOP_LIT){ - if((lit & 0xff) == 0) - /* or'ing with 0 has no effect */ - continue; - else { - int p = pic16_my_powof2(lit & 0xff); - if(p>=0) { - /* only one bit is set in the literal, so use a bsf instruction */ - pic16_emitpcode(POC_BSF, - pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0, PO_GPR_REGISTER)); - } else { - if(know_W != (lit & 0xff)) - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); - know_W = lit & 0xff; - pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset)); - } - - } - } else { - if (AOP_TYPE(left) == AOP_ACC) { - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),offset)); -// pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - } else { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset)); - pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset)); - -// pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); -// pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,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)); - pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__); - - - if(size) - pic16_emitcode(";XXX setb","c"); - while(sizer--){ - MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - pic16_emitcode(";XXX orl","a,%s", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100); - offset++; - } - if(size){ - CLRC; - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - pic16_outBitC(result); - } else if(ifx) - jmpTrueOrFalse(ifx, tlbl); - } else for(;(size--);offset++){ - // normal case - // result = left & right - if(AOP_TYPE(right) == AOP_LIT){ - int t = (lit >> (offset*8)) & 0x0FFL; - switch(t) { - case 0x00: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - -// pic16_emitcode("movf","%s,w", -// pic16_aopGet(AOP(left),offset,FALSE,FALSE)); -// pic16_emitcode("movwf","%s", -// pic16_aopGet(AOP(result),offset,FALSE,FALSE)); - break; - default: - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t)); - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - -// pic16_emitcode("movlw","0x%x",t); -// pic16_emitcode("iorwf","%s,w", -// pic16_aopGet(AOP(left),offset,FALSE,FALSE)); -// pic16_emitcode("movwf","%s", -// pic16_aopGet(AOP(result),offset,FALSE,FALSE)); - - } - continue; - } - - // faster than result <- left, anl result,right - // and better if result is SFR - if (AOP_TYPE(left) == AOP_ACC) { - pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(right),offset)); -// pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - } else { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset)); - pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),offset)); - -// pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); -// pic16_emitcode("iorwf","%s,w", -// pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - } - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); -// pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE)); - } - } - -release : - pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_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; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - FENTRY; - - pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE); - pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE); - pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE); - - /* 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) || - (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) { - operand *tmp = right ; - right = left; - left = tmp; - } - - /* if result = right then exchange them */ - if(pic16_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 = ulFromVal (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) - {pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),offset)); - pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);} - else if(ifx) - continueIfTrue(ifx); - goto release; - } - pic16_emitcode("setb","c"); - } else{ - // lit == (0 or 1) - if(lit == 0){ - // lit == 0, result = left - if(size && pic16_sameRegs(AOP(result),AOP(left))) - goto release; - pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); - } else{ - // lit == 1, result = not(left) - if(size && pic16_sameRegs(AOP(result),AOP(left))){ - pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),offset)); - pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offset)); - pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir); - goto release; - } else { - pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); - pic16_emitcode("cpl","c"); - } - } - } - - } else { - // right != literal - symbol *tlbl = newiTempLabel(NULL); - if (AOP_TYPE(right) == AOP_CRY){ - // c = bit ^ bit; - pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir); - } - else{ - int sizer = AOP_SIZE(right); - // c = bit ^ val - // if val>>1 != 0, result = 1 - pic16_emitcode("setb","c"); - while(sizer){ - MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE)); - if(sizer == 1) - // test the msb of the lsb - pic16_emitcode("anl","a,#0xfe"); - pic16_emitcode("jnz","%05d_DS_",tlbl->key+100); - sizer--; - } - // val = (0,1) - pic16_emitcode("rrc","a"); - } - pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100)); - pic16_emitcode("cpl","c"); - pic16_emitcode("","%05d_DS_:",(tlbl->key+100)); - } - // bit = c - // val = c - if(size) - pic16_outBitC(result); - // if(bit | ...) - else if((AOP_TYPE(result) == AOP_CRY) && ifx) - genIfxJump(ifx, "c"); - goto release ; - } - - if(pic16_sameRegs(AOP(result),AOP(left))){ - /* if left is same as result */ - for(;size--; offset++) { - if(AOP_TYPE(right) == AOP_LIT){ - int t = (lit >> (offset*8)) & 0x0FFL; - if(t == 0x00L) - continue; - else - if (IS_AOP_PREG(left)) { - MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE)); - pic16_aopPut(AOP(result),"a",offset); - } else { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t)); - pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset)); - pic16_emitcode("xrl","%s,%s", - pic16_aopGet(AOP(left),offset,FALSE,TRUE), - pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - } - } else { - if (AOP_TYPE(left) == AOP_ACC) - pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - else { - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset)); - pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset)); -/* - if (IS_AOP_PREG(left)) { - pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE)); - pic16_aopPut(AOP(result),"a",offset); - } else - pic16_emitcode("xrl","%s,a", - pic16_aopGet(AOP(left),offset,FALSE,TRUE)); -*/ - } - } - } - } 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) - pic16_emitcode("setb","c"); - while(sizer--){ - if((AOP_TYPE(right) == AOP_LIT) && - (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){ - MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - } else { - MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - pic16_emitcode("xrl","a,%s", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - } - pic16_emitcode("jnz","%05d_DS_",tlbl->key+100); - offset++; - } - if(size){ - CLRC; - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - pic16_outBitC(result); - } else if(ifx) - jmpTrueOrFalse(ifx, tlbl); - } else for(;(size--);offset++){ - // normal case - // result = left & right - if(AOP_TYPE(right) == AOP_LIT){ - int t = (lit >> (offset*8)) & 0x0FFL; - switch(t) { - case 0x00: - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset)); - pic16_emitcode("movf","%s,w", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - pic16_emitcode("movwf","%s", - pic16_aopGet(AOP(result),offset,FALSE,FALSE)); - break; - case 0xff: - pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset)); - pic16_emitcode("comf","%s,w", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - pic16_emitcode("movwf","%s", - pic16_aopGet(AOP(result),offset,FALSE,FALSE)); - break; - default: - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t)); - pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset)); - pic16_emitcode("movlw","0x%x",t); - pic16_emitcode("xorwf","%s,w", - pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - pic16_emitcode("movwf","%s", - pic16_aopGet(AOP(result),offset,FALSE,FALSE)); - - } - continue; - } - - // faster than result <- left, anl result,right - // and better if result is SFR - if (AOP_TYPE(left) == AOP_ACC) { - pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset)); - pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - } else { - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset)); - pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset)); - pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - } - if ( AOP_TYPE(result) != AOP_ACC){ - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset)); - pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE)); - } - } - } - - release : - pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(result,NULL,ic,TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genInline - write the inline code out */ -/*-----------------------------------------------------------------*/ -static void genInline (iCode *ic) -{ - char *buffer, *bp, *bp1; - bool inComment = FALSE; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - _G.inLine += (!options.asmpeep); - - buffer = bp = bp1 = Safe_strdup (IC_INLINE (ic)); - - while((bp1=strstr(bp, "\\n"))) { - *bp1++ = '\n'; - *bp1++ = ' '; - bp = bp1; - } - bp = bp1 = buffer; - -#if 0 - /* This is an experimental code for #pragma inline - and is temporarily disabled for 2.5.0 release */ - if(asmInlineMap) - { - symbol *sym; - char *s; - char *cbuf; - int cblen; - - cbuf = Safe_strdup(buffer); - cblen = strlen(buffer)+1; - memset(cbuf, 0, cblen); - - bp = buffer; - bp1 = cbuf; - while(*bp) { - if(*bp != '%')*bp1++ = *bp++; - else { - int i; - - bp++; - i = *bp - '0'; - if(i>elementsInSet(asmInlineMap))break; - - bp++; - s = indexSet(asmInlineMap, i); - DEBUGpc("searching symbol s = `%s'", s); - sym = findSym(SymbolTab, NULL, s); - - if(sym->reqv) { - strcat(bp1, sym->reqv->operand.symOperand->regs[0]->name); - } else { - strcat(bp1, sym->rname); - } - - while(*bp1)bp1++; - } - - if(strlen(bp1) > cblen - 16) { - int i = strlen(cbuf); - cblen += 50; - cbuf = realloc(cbuf, cblen); - memset(cbuf+i, 0, 50); - bp1 = cbuf + i; - } - } - - free(buffer); - buffer = Safe_strdup( cbuf ); - free(cbuf); - - bp = bp1 = buffer; - } -#endif /* 0 */ - - /* emit each line as a code */ - while (*bp) - { - switch (*bp) - { - case ';': - inComment = TRUE; - ++bp; - break; - - case '\n': - inComment = FALSE; - *bp++ = '\0'; - if (*bp1) - pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process - bp1 = bp; - break; - - default: - /* Add \n for labels, not dirs such as c:\mydir */ - if (!inComment && (*bp == ':') && (isspace((unsigned char)bp[1]))) - { - ++bp; - *bp = '\0'; - ++bp; - /* print label, use this special format with NULL directive - * to denote that the argument should not be indented with tab */ - pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process - bp1 = bp; - } - else - ++bp; - break; - } - } - - if ((bp1 != bp) && *bp1) - pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process - - Safe_free (buffer); - - _G.inLine -= (!options.asmpeep); -} - -/*-----------------------------------------------------------------*/ -/* genRRC - rotate right with carry */ -/*-----------------------------------------------------------------*/ -static void genRRC (iCode *ic) -{ - operand *left , *result ; - int size, offset = 0, same; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - /* rotate right with carry */ - left = IC_LEFT(ic); - result=IC_RESULT(ic); - pic16_aopOp (left,ic,FALSE); - pic16_aopOp (result,ic,TRUE); - - DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); - - same = pic16_sameRegs(AOP(result),AOP(left)); - - size = AOP_SIZE(result); - - DEBUGpic16_emitcode ("; ***","%s %d size:%d same:%d",__FUNCTION__,__LINE__,size,same); - - /* get the lsb and put it into the carry */ - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1)); - - offset = 0 ; - - while(size--) { - - if(same) { - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset)); - } else { - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - } - - offset++; - } - - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_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; - int same; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* rotate right with carry */ - left = IC_LEFT(ic); - result=IC_RESULT(ic); - pic16_aopOp (left,ic,FALSE); - pic16_aopOp (result,ic,TRUE); - - DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); - - same = pic16_sameRegs(AOP(result),AOP(left)); - - /* move it to the result */ - size = AOP_SIZE(result); - - /* get the msb and put it into the carry */ - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1)); - - offset = 0 ; - - while(size--) { - - if(same) { - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset)); - } else { - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - } - - offset++; - } - - - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_freeAsmop(result,NULL,ic,TRUE); -} - - -/* gpasm can get the highest order bit with HIGH/UPPER - * so the following probably is not needed -- VR */ - -/*-----------------------------------------------------------------*/ -/* genGetHbit - generates code get highest order bit */ -/*-----------------------------------------------------------------*/ -static void genGetHbit (iCode *ic) -{ - operand *left, *result; - left = IC_LEFT(ic); - result=IC_RESULT(ic); - pic16_aopOp (left,ic,FALSE); - pic16_aopOp (result,ic,FALSE); - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - /* get the highest order byte into a */ - MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE)); - if(AOP_TYPE(result) == AOP_CRY){ - pic16_emitcode("rlc","a"); - pic16_outBitC(result); - } - else{ - pic16_emitcode("rl","a"); - pic16_emitcode("anl","a,#0x01"); - pic16_outAcc(result); - } - - - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_freeAsmop(result,NULL,ic,TRUE); -} - -#if 0 -/*-----------------------------------------------------------------*/ -/* AccRol - rotate left accumulator by known count */ -/*-----------------------------------------------------------------*/ -static void AccRol (int shCount) -{ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - shCount &= 0x0007; // shCount : 0..7 - switch(shCount){ - case 0 : - break; - case 1 : - pic16_emitcode("rl","a"); - break; - case 2 : - pic16_emitcode("rl","a"); - pic16_emitcode("rl","a"); - break; - case 3 : - pic16_emitcode("swap","a"); - pic16_emitcode("rr","a"); - break; - case 4 : - pic16_emitcode("swap","a"); - break; - case 5 : - pic16_emitcode("swap","a"); - pic16_emitcode("rl","a"); - break; - case 6 : - pic16_emitcode("rr","a"); - pic16_emitcode("rr","a"); - break; - case 7 : - pic16_emitcode("rr","a"); - break; - } -} -#endif - -/*-----------------------------------------------------------------*/ -/* AccLsh - left shift accumulator by known count */ -/*-----------------------------------------------------------------*/ -static void AccLsh (int shCount, int doMask) -{ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - switch(shCount){ - case 0 : - return; - break; - case 1 : - pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - break; - case 2 : - pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - break; - case 3 : - pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg)); - pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - break; - case 4 : - pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg)); - break; - case 5 : - pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg)); - pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - break; - case 6 : - pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - break; - case 7 : - pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - break; - } - if (doMask) { - /* no masking is required in genPackBits */ - pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount])); - } -} - -/*-----------------------------------------------------------------*/ -/* AccRsh - right shift accumulator by known count */ -/*-----------------------------------------------------------------*/ -static void AccRsh (int shCount, int andmask) -{ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - switch(shCount){ - case 0 : - return; break; - case 1 : - pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - break; - case 2 : - pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - break; - case 3 : - pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg)); - pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - break; - case 4 : - pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg)); - break; - case 5 : - pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg)); - pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - break; - case 6 : - pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - break; - case 7 : - pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg)); - break; - } - - if(andmask) - pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount])); - else - DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__); -} - -#if 0 -/*-----------------------------------------------------------------*/ -/* AccSRsh - signed right shift accumulator by known count */ -/*-----------------------------------------------------------------*/ -static void AccSRsh (int shCount) -{ - symbol *tlbl ; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if(shCount != 0){ - if(shCount == 1){ - pic16_emitcode("mov","c,acc.7"); - pic16_emitcode("rrc","a"); - } else if(shCount == 2){ - pic16_emitcode("mov","c,acc.7"); - pic16_emitcode("rrc","a"); - pic16_emitcode("mov","c,acc.7"); - pic16_emitcode("rrc","a"); - } else { - tlbl = newiTempLabel(NULL); - /* rotate right accumulator */ - AccRol(8 - shCount); - /* and kill the higher order bits */ - pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]); - pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100); - pic16_emitcode("orl","a,#0x%02x", - (unsigned char)~SRMask[shCount]); - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - } - } -} -#endif - -/*-----------------------------------------------------------------*/ -/* shiftR1Left2Result - shift right one byte from left to result */ -/*-----------------------------------------------------------------*/ -static void shiftR1Left2ResultSigned (operand *left, int offl, - operand *result, int offr, - int shCount) -{ - int same; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr); - - switch(shCount) { - case 1: - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl)); - if(same) - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); - else { - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - } - - break; - case 2: - - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl)); - if(same) - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); - else { - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - } - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); - - break; - - case 3: - if(same) - pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr)); - else { - pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - } - - pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr)); - //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); - - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0)); - - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - break; - - case 4: - pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf0)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - break; - case 5: - if(same) { - pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr)); - } else { - pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - } - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xf8)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - break; - - case 6: - if(same) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - } else { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_BCF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER)); - } - break; - - case 7: - if(same) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - } else { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offr)); - } - - default: - break; - } -} - -/*-----------------------------------------------------------------*/ -/* shiftR1Left2Result - shift right one byte from left to result */ -/*-----------------------------------------------------------------*/ -static void shiftR1Left2Result (operand *left, int offl, - operand *result, int offr, - int shCount, int sign) -{ - int same; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr); - - /* Copy the msb into the carry if signed. */ - if(sign) { - shiftR1Left2ResultSigned(left,offl,result,offr,shCount); - return; - } - - - - switch(shCount) { - case 1: - emitCLRC; - if(same) - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); - else { - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - } - break; - case 2: - emitCLRC; - if(same) { - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); - } else { - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - } - emitCLRC; - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); - - break; - case 3: - if(same) - pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr)); - else { - pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - } - - pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(result),offr)); - //pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - break; - - case 4: - pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - break; - - case 5: - pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0e)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - //emitCLRC; - pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr)); - - break; - case 6: - - pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x81)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(result),offr)); - break; - - case 7: - - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); - - break; - - default: - break; - } -} - -/*-----------------------------------------------------------------*/ -/* shiftL1Left2Result - shift left one byte from left to result */ -/*-----------------------------------------------------------------*/ -static void shiftL1Left2Result (operand *left, int offl, - operand *result, int offr, int shCount) -{ - int same; - - // char *l; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr); - DEBUGpic16_emitcode ("; ***","same = %d",same); - // l = pic16_aopGet(AOP(left),offl,FALSE,FALSE); - // MOVA(l); - /* shift left accumulator */ - //AccLsh(shCount, 1); // don't comment out just yet... - // pic16_aopPut(AOP(result),"a",offr); - - switch(shCount) { - case 1: - /* Shift left 1 bit position */ - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl)); - if(same) { - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl)); - } else { - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - } - break; - case 2: - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr)); - break; - case 3: - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); - break; - case 4: - pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr)); - break; - case 5: - pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr)); - break; - case 6: - pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); - break; - case 7: - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); - break; - - default: - DEBUGpic16_emitcode ("; ***","%s %d, shift count is %d",__FUNCTION__,__LINE__,shCount); - } - -} - -/*-----------------------------------------------------------------*/ -/* movLeft2Result - move byte from left to result */ -/*-----------------------------------------------------------------*/ -static void movLeft2Result (operand *left, int offl, - operand *result, int offr) -{ - char *l; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){ - l = pic16_aopGet(AOP(left),offl,FALSE,FALSE); - - if (*l == '@' && (IS_AOP_PREG(result))) { - pic16_emitcode("mov","a,%s",l); - pic16_aopPut(AOP(result),"a",offr); - } else { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - } - } -} - -/*-----------------------------------------------------------------*/ -/* shiftL2Left2Result - shift left two bytes from left to result */ -/*-----------------------------------------------------------------*/ -static void shiftL2Left2Result (operand *left, int offl, - operand *result, int offr, int shCount) -{ - int same = pic16_sameRegs(AOP(result), AOP(left)); - int i; - - DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr); - - if (same && (offl != offr)) { // shift bytes - if (offr > offl) { - for(i=1;i>-1;i--) { - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i)); - } - } else { // just treat as different later on - same = 0; - } - } - - if(same) { - switch(shCount) { - case 0: - break; - case 1: - case 2: - case 3: - - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); - - while(--shCount) { - emitCLRC; - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); - } - - break; - case 4: - case 5: - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f)); - pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16)); - if(shCount >=5) { - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); - } - break; - case 6: - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0)); - pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); - break; - case 7: - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); - } - - } else { - switch(shCount) { - case 0: - break; - case 1: - case 2: - case 3: - /* note, use a mov/add for the shift since the mov has a - chance of getting optimized out */ - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16)); - - while(--shCount) { - emitCLRC; - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); - } - break; - - case 4: - case 5: - pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F)); - pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16)); - - - if(shCount == 5) { - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); - } - break; - case 6: - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0)); - pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); - break; - case 7: - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16)); - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); - } - } - -} -/*-----------------------------------------------------------------*/ -/* shiftR2Left2Result - shift right two bytes from left to result */ -/*-----------------------------------------------------------------*/ -static void shiftR2Left2Result (operand *left, int offl, - operand *result, int offr, - int shCount, int sign) -{ - int same = pic16_sameRegs(AOP(result), AOP(left)); - int i; - DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign); - - if (same && (offl != offr)) { // shift right bytes - if (offr < offl) { - for(i=0;i<2;i++) { - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i)); - } - } else { // just treat as different later on - same = 0; - } - } - - switch(shCount) { - case 0: - break; - case 1: - case 2: - case 3: - /* obtain sign from left operand */ - if(sign) - pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16)); - else - emitCLRC; - - if(same) { - pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr)); - } else { - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr)); - } - - while(--shCount) { - if(sign) - /* now get sign from already assigned result (avoid BANKSEL) */ - pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16)); - else - emitCLRC; - pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr)); - } - break; - case 4: - case 5: - if(same) { - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0)); - pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr)); - - pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr)); - } else { - pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); - - pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0)); - pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr)); - } - - if(shCount >=5) { - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); - } - - if(sign) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 )); - pic16_emitpcode(POC_BTFSC, - pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16)); - } - - break; - - case 6: - if(same) { - - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); - - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03)); - if(sign) { - pic16_emitpcode(POC_BTFSC, - pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc)); - } - pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr)); - } else { - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03)); - if(sign) { - pic16_emitpcode(POC_BTFSC, - pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc)); - } - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); - //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); - - - } - - break; - case 7: - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl)); - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16)); - if(sign) { - emitSKPNC; - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16)); - } else - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); - } -} - - -/*-----------------------------------------------------------------*/ -/* shiftLLeftOrResult - shift left one byte from left, or to result*/ -/*-----------------------------------------------------------------*/ -static void shiftLLeftOrResult (operand *left, int offl, - operand *result, int offr, int shCount) -{ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl)); - /* shift left accumulator */ - AccLsh(shCount, 1); - /* or with result */ - /* back to result */ - pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr)); -} - -/*-----------------------------------------------------------------*/ -/* shiftRLeftOrResult - shift right one byte from left,or to result*/ -/*-----------------------------------------------------------------*/ -static void shiftRLeftOrResult (operand *left, int offl, - operand *result, int offr, int shCount) -{ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl)); - /* shift right accumulator */ - AccRsh(shCount, 1); - /* or with result */ - /* back to result */ - pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr)); -} - -/*-----------------------------------------------------------------*/ -/* genlshOne - left shift a one byte quantity by known count */ -/*-----------------------------------------------------------------*/ -static void genlshOne (operand *result, operand *left, int shCount) -{ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - shiftL1Left2Result(left, LSB, result, LSB, shCount); -} - -/*-----------------------------------------------------------------*/ -/* genlshTwo - left shift two bytes by known amount != 0 */ -/*-----------------------------------------------------------------*/ -static void genlshTwo (operand *result,operand *left, int shCount) -{ - int size; - - DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount); - size = pic16_getDataSize(result); - - /* if shCount >= 8 */ - if (shCount >= 8) { - shCount -= 8 ; - - if (size > 1){ - if (shCount) - shiftL1Left2Result(left, LSB, result, MSB16, shCount); - else - movLeft2Result(left, LSB, result, MSB16); - } - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB)); - } - - /* 1 <= shCount <= 7 */ - else { - if(size == 1) - shiftL1Left2Result(left, LSB, result, LSB, shCount); - else - shiftL2Left2Result(left, LSB, result, LSB, shCount); - } -} - -/*-----------------------------------------------------------------*/ -/* shiftLLong - shift left one long from left to result */ -/* offr = LSB or MSB16 */ -/*-----------------------------------------------------------------*/ -static void shiftLLong (operand *left, operand *result, int offr ) -{ - int size = AOP_SIZE(result); - int same = pic16_sameRegs(AOP(left),AOP(result)); - int i; - - DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size); - - if (same && (offr == MSB16)) { //shift one byte - for(i=size-1;i>=MSB16;i--) { - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i)); - } - } else { - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr)); - } - - if (size > LSB+offr ){ - if (same) { - pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr)); - } else { - pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr)); - } - } - - if(size > MSB16+offr){ - if (same) { - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr)); - } else { - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr)); - } - } - - if(size > MSB24+offr){ - if (same) { - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr)); - } else { - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr)); - } - } + case 6: + pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x03)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - if(size > MSB32+offr){ - if (same) { - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr)); - } else { - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr)); - } - } - if(offr != LSB) - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB)); + case 7: + pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x01)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; + default: + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr)); + break; + } } /*-----------------------------------------------------------------*/ -/* genlshFour - shift four byte by a known amount != 0 */ +/* shiftL1Left2Result - shift left one byte from left to result */ /*-----------------------------------------------------------------*/ -static void genlshFour (operand *result, operand *left, int shCount) +static void shiftL1Left2Result (operand *left, int offl, + operand *result, int offr, int shCount) { - int size; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - 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); - - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB)); - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16)); - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24)); - - return; - } + int same; - /* 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); - movLeft2Result(left, LSB, result, MSB24); - } - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB)); - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16)); - return; - } + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + assert ((shCount >= 0) && (shCount <= 8)); - /* 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); - } - else{ /* size = 4 */ - if(shCount == 0){ - movLeft2Result(left, MSB24, result, MSB32); - movLeft2Result(left, MSB16, result, MSB24); - movLeft2Result(left, LSB, result, MSB16); - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),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); - pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB)); - } - } - } + same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr); - /* 1 <= shCount <= 7 */ - else if(shCount <= 3) - { - shiftLLong(left, result, LSB); - while(--shCount >= 1) - 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); + /* Do NOT use result for intermediate results, it might be an SFR!. */ + switch (shCount) { + case 0: + if (!same) { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); } -} - -/*-----------------------------------------------------------------*/ -/* genLeftShiftLiteral - left shifting by known count */ -/*-----------------------------------------------------------------*/ -void pic16_genLeftShiftLiteral (operand *left, - operand *right, - operand *result, - iCode *ic) -{ - int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit)); - int size; - - FENTRY; - DEBUGpic16_emitcode ("; ***","shCount:%d", shCount); - pic16_freeAsmop(right,NULL,ic,TRUE); - - pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,TRUE); - - size = getSize(operandType(result)); - -#if VIEW_SIZE - pic16_emitcode("; shift left ","result %d, left %d",size, - AOP_SIZE(left)); -#endif + break; - /* I suppose that the left size >= result size */ - if(shCount == 0){ - while(size--){ - movLeft2Result(left, size, result, size); - } + case 1: + if (same) { + emitCLRC; + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left), offl)); + } else { + pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); } + break; - else if(shCount >= (size * 8)) - while(size--) - pic16_aopPut(AOP(result),zero,size); - else{ - switch (size) { - case 1: - genlshOne (result,left,shCount); - break; - - case 2: - case 3: - genlshTwo (result,left,shCount); - break; - - case 4: - genlshFour (result,left,shCount); - break; - } - } - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_freeAsmop(result,NULL,ic,TRUE); -} + case 2: + pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfc)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; -/*-----------------------------------------------------------------* - * genMultiAsm - repeat assembly instruction for size of register. - * if endian == 1, then the high byte (i.e base address + size of - * register) is used first else the low byte is used first; - *-----------------------------------------------------------------*/ -static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian) -{ + case 3: + pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf8)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - int offset = 0; + case 4: + pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + case 5: + pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_RLNCFW, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - if(!reg) - return; + case 6: + pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_RRNCFW, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - if(!endian) { - endian = 1; - } else { - endian = -1; - offset = size-1; - } + case 7: + pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left), offl)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offr)); + break; - while(size--) { - pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset)); - offset += endian; + default: + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), offr)); + break; } - } -#if !(USE_GENERIC_SIGNED_SHIFT) /*-----------------------------------------------------------------*/ -/* genLeftShift - generates code for left shifting */ +/* movLeft2Result - move byte from left to result */ /*-----------------------------------------------------------------*/ -static void genLeftShift (iCode *ic) +static void movLeft2Result (operand *left, int offl, + operand *result, int offr) { - operand *left,*right, *result; - int size, offset; -// char *l; - symbol *tlbl , *tlbl1; - pCodeOp *pctemp; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - right = IC_RIGHT(ic); - left = IC_LEFT(ic); - result = IC_RESULT(ic); - - pic16_aopOp(right,ic,FALSE); - - /* if the shift count is known then do it - as efficiently as possible */ - if (AOP_TYPE(right) == AOP_LIT) { - pic16_genLeftShiftLiteral (left,right,result,ic); - return ; + if (!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)) { + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); } +} - /* shift count is unknown then we have to form - * a loop. Get the loop count in WREG : Note: we take - * only the lower order byte since shifting - * more than 32 bits make no sense anyway, ( the - * largest size of an object can be only 32 bits ) */ +/*-----------------------------------------------------------------*/ +/* shiftL2Left2Result - shift left two bytes from left to result */ +/*-----------------------------------------------------------------*/ +static void shiftL2Left2Result (operand *left, int offl, + operand *result, int offr, int shCount) +{ + int same = pic16_sameRegs(AOP(result), AOP(left)); + int i; - pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,FALSE); + DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr); - /* now move the left to the result if they are not the - * same, and if size > 1, - * and if right is not same to result (!!!) -- VR */ - if (!pic16_sameRegs(AOP(left),AOP(result)) - && (AOP_SIZE(result) > 1)) { + if (same && (offl != offr)) { // shift bytes + if (offr > offl) { + for(i=1;i>-1;i--) { + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i)); + } + } else { // just treat as different later on + same = 0; + } + } - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + if(same) { + switch(shCount) { + case 0: + break; + case 1: + case 2: + case 3: - size = AOP_SIZE(result); - offset=0; - while (size--) { + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); -#if 0 - l = pic16_aopGet(AOP(left),offset,FALSE,TRUE); - if (*l == '@' && (IS_AOP_PREG(result))) { + while(--shCount) { + emitCLRC; + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); + } - pic16_emitcode("mov","a,%s",l); - pic16_aopPut(AOP(result),"a",offset); - } else -#endif - { - /* we don't know if left is a literal or a register, take care -- VR */ - pic16_mov2f(AOP(result), AOP(left), offset); + break; + case 4: + case 5: + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f)); + pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16)); + if(shCount >=5) { + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); } - offset++; + break; + case 6: + pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0)); + pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); + break; + case 7: + pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); } - } - size = AOP_SIZE(result); + } else { + switch(shCount) { + case 0: + break; + case 1: + case 2: + case 3: + /* note, use a mov/add for the shift since the mov has a + chance of getting optimized out */ + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16)); - /* if it is only one byte then */ - if (size == 1) { - if(optimized_for_speed) { - pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0)); - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe)); - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0)); - } else { + while(--shCount) { + emitCLRC; + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); + } + break; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + case 4: + case 5: + pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0F)); + pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16)); - tlbl = newiTempLabel(NULL); -#if 1 - /* this is already done, why change it? */ - if (!pic16_sameRegs(AOP(left),AOP(result))) { - pic16_mov2f(AOP(result), AOP(left), 0); + if(shCount == 5) { + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); } -#endif - - pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0)); - pic16_emitpLabel(tlbl->key); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1)); - emitSKPC; - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); + break; + case 6: + pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left),offl)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RRNCFW, pic16_popGet(AOP(left),offl+MSB16)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_RRNCF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xc0)); + pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr)); + break; + case 7: + pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16)); + pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); } - goto release ; } - if (pic16_sameRegs(AOP(left),AOP(result))) { - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); +} +/*-----------------------------------------------------------------*/ +/* shiftR2Left2Result - shift right two bytes from left to result */ +/*-----------------------------------------------------------------*/ +static void shiftR2Left2Result (operand *left, int offl, + operand *result, int offr, + int shCount, int sign) +{ + int same = pic16_sameRegs(AOP(result), AOP(left)); + int i; + DEBUGpic16_emitcode ("; ***","%s %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign); - tlbl = newiTempLabel(NULL); - pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0)); - genMultiAsm(POC_RRCF, result, size,1); - pic16_emitpLabel(tlbl->key); - genMultiAsm(POC_RLCF, result, size,0); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1)); - emitSKPC; - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); - goto release; + if (same && (offl != offr)) { // shift right bytes + if (offr < offl) { + for(i=0;i<2;i++) { + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i)); + } + } else { // just treat as different later on + same = 0; + } } - //tlbl = newiTempLabel(NULL); - //offset = 0 ; - //tlbl1 = newiTempLabel(NULL); + switch(shCount) { + case 0: + break; + case 1: + case 2: + case 3: + /* obtain sign from left operand */ + if(sign) + pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),offr+MSB16)); + else + emitCLRC; + + if(same) { + pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr)); + } else { + pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr)); + } - //reAdjustPreg(AOP(result)); + while(--shCount) { + if(sign) + /* now get sign from already assigned result (avoid BANKSEL) */ + pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16)); + else + emitCLRC; + pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr)); + } + break; + case 4: + case 5: + if(same) { - //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); - //pic16_emitcode("","%05d_DS_:",tlbl->key+100); - //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE); - //MOVA(l); - //pic16_emitcode("add","a,acc"); - //pic16_aopPut(AOP(result),"a",offset++); - //while (--size) { - // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE); - // MOVA(l); - // pic16_emitcode("rlc","a"); - // pic16_aopPut(AOP(result),"a",offset++); - //} - //reAdjustPreg(AOP(result)); + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0)); + pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr)); - //pic16_emitcode("","%05d_DS_:",tlbl1->key+100); - //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100); + pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr)); + } else { + pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0)); + pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr)); + } - tlbl = newiTempLabel(NULL); - tlbl1= newiTempLabel(NULL); + if(shCount >=5) { + pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr)); + } - size = AOP_SIZE(result); - offset = 1; + if(sign) { + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 )); + pic16_emitpcode(POC_BTFSC, + pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0, PO_GPR_REGISTER)); + pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16)); + } - pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */ + break; - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); + case 6: + if(same) { - /* offset should be 0, 1 or 3 */ + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1)); - emitSKPNZ; - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key)); + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03)); + if(sign) { + pic16_emitpcode(POC_BTFSC, + pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0, PO_GPR_REGISTER)); + pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc)); + } + pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr)); + } else { + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16)); + pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03)); + if(sign) { + pic16_emitpcode(POC_BTFSC, + pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0, PO_GPR_REGISTER)); + pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc)); + } + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16)); + //pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr)); - pic16_emitpcode(POC_MOVWF, pctemp); + } - pic16_emitpLabel(tlbl->key); + break; + case 7: + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl)); + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr)); + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16)); + if(sign) { + emitSKPNC; + pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16)); + } else + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16)); + } +} - emitCLRC; - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0)); - while(--size) - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++)); - pic16_emitpcode(POC_DECFSZ, pctemp); - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); - pic16_emitpLabel(tlbl1->key); +/*-----------------------------------------------------------------*/ +/* shiftLLeftOrResult - shift left one byte from left, or to result*/ +/*-----------------------------------------------------------------*/ +static void shiftLLeftOrResult (operand *left, int offl, + operand *result, int offr, int shCount) +{ + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_popReleaseTempReg(pctemp,1); + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl)); + /* shift left accumulator */ + AccLsh(shCount, 1); + /* or with result */ + /* back to result */ + pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr)); +} +/*-----------------------------------------------------------------*/ +/* shiftRLeftOrResult - shift right one byte from left,or to result*/ +/*-----------------------------------------------------------------*/ +static void shiftRLeftOrResult (operand *left, int offl, + operand *result, int offr, int shCount) +{ + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - release: - pic16_freeAsmop (right,NULL,ic,TRUE); - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_freeAsmop(result,NULL,ic,TRUE); + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl)); + /* shift right accumulator */ + AccRsh(shCount, 1); + /* or with result */ + /* back to result */ + pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr)); } -#endif - -#if 0 -#error old code (left here for reference) /*-----------------------------------------------------------------*/ -/* genLeftShift - generates code for left shifting */ +/* genlshOne - left shift a one byte quantity by known count */ /*-----------------------------------------------------------------*/ -static void genLeftShift (iCode *ic) +static void genlshOne (operand *result, operand *left, int shCount) { - operand *left,*right, *result; - int size, offset; - char *l; - symbol *tlbl , *tlbl1; - pCodeOp *pctemp; + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + shiftL1Left2Result(left, LSB, result, LSB, shCount); +} - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); +/*-----------------------------------------------------------------*/ +/* genlshTwo - left shift two bytes by known amount != 0 */ +/*-----------------------------------------------------------------*/ +static void genlshTwo (operand *result,operand *left, int shCount) +{ + int size; - right = IC_RIGHT(ic); - left = IC_LEFT(ic); - result = IC_RESULT(ic); + DEBUGpic16_emitcode ("; ***","%s %d shCount:%d",__FUNCTION__,__LINE__,shCount); + size = pic16_getDataSize(result); - pic16_aopOp(right,ic,FALSE); + /* if shCount >= 8 */ + if (shCount >= 8) { + shCount -= 8 ; - /* if the shift count is known then do it - as efficiently as possible */ - if (AOP_TYPE(right) == AOP_LIT) { - pic16_genLeftShiftLiteral (left,right,result,ic); - return ; - } + if (size > 1){ + if (shCount) + shiftL1Left2Result(left, LSB, result, MSB16, shCount); + else + movLeft2Result(left, LSB, result, MSB16); + } + pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB)); + } - /* 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 ) */ + /* 1 <= shCount <= 7 */ + else { + if(size == 1) + shiftL1Left2Result(left, LSB, result, LSB, shCount); + else + shiftL2Left2Result(left, LSB, result, LSB, shCount); + } +} +/*-----------------------------------------------------------------*/ +/* shiftLLong - shift left one long from left to result */ +/* offr = LSB or MSB16 */ +/*-----------------------------------------------------------------*/ +static void shiftLLong (operand *left, operand *result, int offr ) +{ + int size = AOP_SIZE(result); + int same = pic16_sameRegs(AOP(left),AOP(result)); + int i; - pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,FALSE); + DEBUGpic16_emitcode ("; ***","%s %d offr:%d size:%d",__FUNCTION__,__LINE__,offr,size); - /* now move the left to the result if they are not the - same */ - if (!pic16_sameRegs(AOP(left),AOP(result)) && - AOP_SIZE(result) > 1) { + if (same && (offr == MSB16)) { //shift one byte + for(i=size-1;i>=MSB16;i--) { + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i)); + } + } else { + pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB)); + } - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + if (size > LSB+offr ){ + if (same) { + pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr)); + } else { + pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr)); + } + } - size = AOP_SIZE(result); - offset=0; - while (size--) { - l = pic16_aopGet(AOP(left),offset,FALSE,TRUE); - if (*l == '@' && (IS_AOP_PREG(result))) { + if(size > MSB16+offr){ + if (same) { + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr)); + } else { + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr)); + } + } - pic16_emitcode("mov","a,%s",l); - pic16_aopPut(AOP(result),"a",offset); - } else { + if(size > MSB24+offr){ + if (same) { + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr)); + } else { + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr)); + } + } - /* we don't know if left is a literal or a register, take care -- VR */ - pic16_mov2f(AOP(result), AOP(left), offset); - } - offset++; + if(size > MSB32+offr){ + if (same) { + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr)); + } else { + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32)); + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr)); + } } - } + if(offr != LSB) + pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB)); - size = AOP_SIZE(result); +} - /* if it is only one byte then */ - if (size == 1) { - if(optimized_for_speed) { - pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0)); - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xfe)); - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0)); - } else { +/*-----------------------------------------------------------------*/ +/* genlshFour - shift four byte by a known amount != 0 */ +/*-----------------------------------------------------------------*/ +static void genlshFour (operand *result, operand *left, int shCount) +{ + int size; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + size = AOP_SIZE(result); - tlbl = newiTempLabel(NULL); - if (!pic16_sameRegs(AOP(left),AOP(result))) { - pic16_mov2f(AOP(result), AOP(left), 0); + /* 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); -// pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); -// pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); - } + pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB)); + pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16)); + pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24)); - pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0)); - pic16_emitpLabel(tlbl->key); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1)); - emitSKPC; - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); + return; } - goto release ; - } - if (pic16_sameRegs(AOP(left),AOP(result))) { - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - tlbl = newiTempLabel(NULL); - pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0)); - genMultiAsm(POC_RRCF, result, size,1); - pic16_emitpLabel(tlbl->key); - genMultiAsm(POC_RLCF, result, size,0); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1)); - emitSKPC; - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); - goto release; - } - - //tlbl = newiTempLabel(NULL); - //offset = 0 ; - //tlbl1 = newiTempLabel(NULL); + /* 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); + movLeft2Result(left, LSB, result, MSB24); + } + pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB)); + pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16)); + return; + } - //reAdjustPreg(AOP(result)); + /* 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); + } + else{ /* size = 4 */ + if(shCount == 0){ + movLeft2Result(left, MSB24, result, MSB32); + movLeft2Result(left, MSB16, result, MSB24); + movLeft2Result(left, LSB, result, MSB16); + pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),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); + pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB)); + } + } + } - //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); - //pic16_emitcode("","%05d_DS_:",tlbl->key+100); - //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE); - //MOVA(l); - //pic16_emitcode("add","a,acc"); - //pic16_aopPut(AOP(result),"a",offset++); - //while (--size) { - // l = pic16_aopGet(AOP(result),offset,FALSE,FALSE); - // MOVA(l); - // pic16_emitcode("rlc","a"); - // pic16_aopPut(AOP(result),"a",offset++); - //} - //reAdjustPreg(AOP(result)); + /* 1 <= shCount <= 7 */ + else if(shCount <= 3) + { + shiftLLong(left, result, LSB); + while(--shCount >= 1) + 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); + } +} - //pic16_emitcode("","%05d_DS_:",tlbl1->key+100); - //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100); +/*-----------------------------------------------------------------*/ +/* genLeftShiftLiteral - left shifting by known count */ +/*-----------------------------------------------------------------*/ +void pic16_genLeftShiftLiteral (operand *left, + operand *right, + operand *result, + iCode *ic) +{ + int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit)); + int size; + FENTRY; + DEBUGpic16_emitcode ("; ***","shCount:%d", shCount); + pic16_freeAsmop(right,NULL,ic,TRUE); - tlbl = newiTempLabel(NULL); - tlbl1= newiTempLabel(NULL); + pic16_aopOp(left,ic,FALSE); + pic16_aopOp(result,ic,TRUE); - size = AOP_SIZE(result); - offset = 1; + size = getSize(operandType(result)); - pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */ +#if VIEW_SIZE + pic16_emitcode("; shift left ","result %d, left %d",size, + AOP_SIZE(left)); +#endif - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); + /* I suppose that the left size >= result size */ + if(shCount == 0){ + while(size--){ + movLeft2Result(left, size, result, size); + } + } - /* offset should be 0, 1 or 3 */ + else if(shCount >= (size * 8)) + while(size--) + pic16_aopPut(AOP(result),zero,size); + else{ + switch (size) { + case 1: + genlshOne (result,left,shCount); + break; - pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1)); - emitSKPNZ; - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key)); + case 2: + case 3: + genlshTwo (result,left,shCount); + break; - pic16_emitpcode(POC_MOVWF, pctemp); + case 4: + genlshFour (result,left,shCount); + break; + } + } + pic16_freeAsmop(left,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); +} +/*-----------------------------------------------------------------* + * genMultiAsm - repeat assembly instruction for size of register. + * if endian == 1, then the high byte (i.e base address + size of + * register) is used first else the low byte is used first; + *-----------------------------------------------------------------*/ +static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian) +{ - pic16_emitpLabel(tlbl->key); + int offset = 0; - emitCLRC; - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0)); - while(--size) - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset++)); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_emitpcode(POC_DECFSZ, pctemp); - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); - pic16_emitpLabel(tlbl1->key); + if(!reg) + return; - pic16_popReleaseTempReg(pctemp,1); + if(!endian) { + endian = 1; + } else { + endian = -1; + offset = size-1; + } + while(size--) { + pic16_emitpcode(poc, pic16_popGet(AOP(reg),offset)); + offset += endian; + } - release: - pic16_freeAsmop (right,NULL,ic,TRUE); - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_freeAsmop(result,NULL,ic,TRUE); } -#endif /*-----------------------------------------------------------------*/ /* genrshOne - right shift a one byte quantity by known count */ @@ -10274,365 +7645,95 @@ static void genrshFour (operand *result, operand *left, 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); - } - } -} - -/*-----------------------------------------------------------------*/ -/* genRightShiftLiteral - right shifting by known count */ -/*-----------------------------------------------------------------*/ -static void genRightShiftLiteral (operand *left, - operand *right, - operand *result, - iCode *ic, - int sign) -{ - int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit)); - int lsize,res_size; - - pic16_freeAsmop(right,NULL,ic,TRUE); - - pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,TRUE); - - DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left)); - -#if VIEW_SIZE - pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result), - AOP_SIZE(left)); -#endif - - lsize = pic16_getDataSize(left); - res_size = pic16_getDataSize(result); - /* test the LEFT size !!! */ - - /* I suppose that the left size >= result size */ - if(shCount == 0){ - assert (res_size <= lsize); - while (res_size--) { - pic16_mov2f (AOP(result), AOP(left), res_size); - } // for - } - - else if(shCount >= (lsize * 8)){ - - if(res_size == 1) { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB)); - if(sign) { - pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),LSB)); - } - } else { - - if(sign) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff)); - while(res_size--) - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size)); - - } else { - - while(res_size--) - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size)); - } - } - } else { - - switch (res_size) { - case 1: - genrshOne (result,left,shCount,sign); - break; - - case 2: - genrshTwo (result,left,shCount,sign); - break; - - case 4: - genrshFour (result,left,shCount,sign); - break; - default : - break; - } - - } - - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_freeAsmop(result,NULL,ic,TRUE); -} - -#if !(USE_GENERIC_SIGNED_SHIFT) -/*-----------------------------------------------------------------*/ -/* genSignedRightShift - right shift of signed number */ -/*-----------------------------------------------------------------*/ -static void genSignedRightShift (iCode *ic) -{ - operand *right, *left, *result; - int size, offset; - // char *l; - symbol *tlbl, *tlbl1 ; - pCodeOp *pctemp; - - //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr); - - /* we do it the hard way put the shift count in b - and loop thru preserving the sign */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - right = IC_RIGHT(ic); - left = IC_LEFT(ic); - result = IC_RESULT(ic); - - pic16_aopOp(right,ic,FALSE); - pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,FALSE); - - - if ( AOP_TYPE(right) == AOP_LIT) { - genRightShiftLiteral (left,right,result,ic,1); - return ; - } - /* 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 ) */ - - //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE)); - //pic16_emitcode("inc","b"); - //pic16_freeAsmop (right,NULL,ic,TRUE); - //pic16_aopOp(left,ic,FALSE); - //pic16_aopOp(result,ic,FALSE); - - /* now move the left to the result if they are not the - same */ - if (!pic16_sameRegs(AOP(left),AOP(result)) && - AOP_SIZE(result) > 1) { - - size = AOP_SIZE(result); - offset=0; - while (size--) { - /* - l = pic16_aopGet(AOP(left),offset,FALSE,TRUE); - if (*l == '@' && IS_AOP_PREG(result)) { - - pic16_emitcode("mov","a,%s",l); - pic16_aopPut(AOP(result),"a",offset); - } else - pic16_aopPut(AOP(result),l,offset); - */ - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - - offset++; - } - } - - /* mov the highest order bit to OVR */ - tlbl = newiTempLabel(NULL); - tlbl1= newiTempLabel(NULL); - - size = AOP_SIZE(result); - offset = size - 1; - - pctemp = pic16_popGetTempReg(1); /* grab a temporary working register. */ - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - - /* offset should be 0, 1 or 3 */ - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3))); - emitSKPNZ; - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl1->key)); - - pic16_emitpcode(POC_MOVWF, pctemp); - - - pic16_emitpLabel(tlbl->key); - - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offset)); - - while(--size) { - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),--offset)); - } - - pic16_emitpcode(POC_DECFSZ, pctemp); - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); - pic16_emitpLabel(tlbl1->key); - - pic16_popReleaseTempReg(pctemp,1); -#if 0 - size = AOP_SIZE(result); - offset = size - 1; - pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE)); - pic16_emitcode("rlc","a"); - pic16_emitcode("mov","ov,c"); - /* if it is only one byte then */ - if (size == 1) { - l = pic16_aopGet(AOP(left),0,FALSE,FALSE); - MOVA(l); - pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - pic16_emitcode("mov","c,ov"); - pic16_emitcode("rrc","a"); - pic16_emitcode("","%05d_DS_:",tlbl1->key+100); - pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100); - pic16_aopPut(AOP(result),"a",0); - goto release ; - } - - reAdjustPreg(AOP(result)); - pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - pic16_emitcode("mov","c,ov"); - while (size--) { - l = pic16_aopGet(AOP(result),offset,FALSE,FALSE); - MOVA(l); - pic16_emitcode("rrc","a"); - pic16_aopPut(AOP(result),"a",offset--); - } - reAdjustPreg(AOP(result)); - pic16_emitcode("","%05d_DS_:",tlbl1->key+100); - pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100); - - release: -#endif - - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_freeAsmop(result,NULL,ic,TRUE); - pic16_freeAsmop(right,NULL,ic,TRUE); -} -#endif - -#if !(USE_GENERIC_SIGNED_SHIFT) -#warning This implementation of genRightShift() is incomplete! -/*-----------------------------------------------------------------*/ -/* genRightShift - generate code for right shifting */ -/*-----------------------------------------------------------------*/ -static void genRightShift (iCode *ic) -{ - operand *right, *left, *result; - sym_link *letype ; - int size, offset; - char *l; - symbol *tlbl, *tlbl1 ; - - /* if signed then we do it the hard way preserve the - sign bit moving it inwards */ - letype = getSpec(operandType(IC_LEFT(ic))); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - if (!SPEC_USIGN(letype)) { - 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); - - pic16_aopOp(right,ic,FALSE); - - /* if the shift count is known then do it - as efficiently as possible */ - if (AOP_TYPE(right) == AOP_LIT) { - genRightShiftLiteral (left,right,result,ic, 0); - return ; - } - - /* 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 ) */ + else{ + shiftR2Left2Result(left, LSB, result, LSB, shCount, 0); + shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount); + shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign); + } + } +} - pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE)); - pic16_emitcode("inc","b"); - pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,FALSE); +/*-----------------------------------------------------------------*/ +/* genRightShiftLiteral - right shifting by known count */ +/*-----------------------------------------------------------------*/ +static void genRightShiftLiteral (operand *left, + operand *right, + operand *result, + iCode *ic, + int sign) +{ + int shCount = abs((int) ulFromVal (AOP(right)->aopu.aop_lit)); + int lsize,res_size; - /* now move the left to the result if they are not the - same */ - if (!pic16_sameRegs(AOP(left),AOP(result)) && - AOP_SIZE(result) > 1) { + pic16_freeAsmop(right,NULL,ic,TRUE); - size = AOP_SIZE(result); - offset=0; - while (size--) { - l = pic16_aopGet(AOP(left),offset,FALSE,TRUE); - if (*l == '@' && IS_AOP_PREG(result)) { + pic16_aopOp(left,ic,FALSE); + pic16_aopOp(result,ic,TRUE); - pic16_emitcode("mov","a,%s",l); - pic16_aopPut(AOP(result),"a",offset); - } else - pic16_aopPut(AOP(result),l,offset); - offset++; - } - } + DEBUGpic16_emitcode ("; ***","%s %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left)); - tlbl = newiTempLabel(NULL); - tlbl1= newiTempLabel(NULL); - size = AOP_SIZE(result); - offset = size - 1; +#if VIEW_SIZE + pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result), + AOP_SIZE(left)); +#endif - /* if it is only one byte then */ - if (size == 1) { + lsize = pic16_getDataSize(left); + res_size = pic16_getDataSize(result); + /* test the LEFT size !!! */ - tlbl = newiTempLabel(NULL); - if (!pic16_sameRegs(AOP(left),AOP(result))) { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); + /* I suppose that the left size >= result size */ + if (shCount == 0) { + assert (res_size <= lsize); + while (res_size--) { + pic16_mov2f (AOP(result), AOP(left), res_size); + } // for + } else if (shCount >= (lsize * 8)) { + if (sign) { + /* + * Do NOT use + * CLRF result + * BTFSC left, 7 + * SETF result + * even for 8-bit operands; result might be an SFR. + */ + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00)); + pic16_emitpcode(POC_BTFSC, pic16_popCopyGPR2Bit(pic16_popGet(AOP(left), lsize-1), 7)); + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff)); + while (res_size--) { + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), res_size)); + } + } else { // unsigned + while (res_size--) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), res_size)); } - - pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0)); - pic16_emitpLabel(tlbl->key); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_ADDLW, pic16_popGetLit(1)); - emitSKPC; - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key)); - - goto release ; } + } else { // 0 < shCount < 8*lsize + switch (res_size) { + case 1: + genrshOne (result,left,shCount,sign); + break; - reAdjustPreg(AOP(result)); - pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); - pic16_emitcode("","%05d_DS_:",tlbl->key+100); - CLRC; - while (size--) { - l = pic16_aopGet(AOP(result),offset,FALSE,FALSE); - MOVA(l); - pic16_emitcode("rrc","a"); - pic16_aopPut(AOP(result),"a",offset--); - } - reAdjustPreg(AOP(result)); + case 2: + genrshTwo (result,left,shCount,sign); + break; - pic16_emitcode("","%05d_DS_:",tlbl1->key+100); - pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100); + case 4: + genrshFour (result,left,shCount,sign); + break; + default : + break; + } + } -release: - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_freeAsmop (right,NULL,ic,TRUE); - pic16_freeAsmop(result,NULL,ic,TRUE); + pic16_freeAsmop(left,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); } -#endif -#if (USE_GENERIC_SIGNED_SHIFT) /*-----------------------------------------------------------------*/ /* genGenericShift - generates code for left or right shifting */ /*-----------------------------------------------------------------*/ -static void genGenericShift (iCode *ic, int isShiftLeft) { +static void genGenericShift (iCode *ic, int isShiftLeft) +{ operand *left,*right, *result; int offset; int sign, signedCount; @@ -10782,13 +7883,12 @@ static void genLeftShift (iCode *ic) { static void genRightShift (iCode *ic) { genGenericShift (ic, 0); } -#endif -/* load FSR0 with address of/from op according to is_LitOp() or if lit is 1 */ +/* load FSR0 with address of/from op according to pic16_isLitOp() or if lit is 1 */ void pic16_loadFSR0(operand *op, int lit) { - if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || is_LitOp( op )) { + if((IS_SYMOP(op) && OP_SYMBOL(op)->remat) || pic16_isLitOp( op )) { if (AOP_TYPE(op) == AOP_LIT) { /* handle 12 bit integers correctly */ unsigned int val = (unsigned int) ulFromVal (AOP(op)->aopu.aop_lit); @@ -10828,8 +7928,10 @@ static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_set p_type = DCL_TYPE(operandType(ptr)); switch (p_type) { - case FPOINTER: case POINTER: + case FPOINTER: + case IPOINTER: + case PPOINTER: if (!fsr0_setup || !*fsr0_setup) { pic16_loadFSR0( ptr, 0 ); @@ -10863,6 +7965,29 @@ static void pic16_derefPtr (operand *ptr, int p_type, int doWrite, int *fsr0_set } break; + case CPOINTER: + /* XXX: Writing to CPOINTERs not (yet) implemented. */ + assert ( !doWrite && "Cannot write into __code space!" ); + if( (AOP_TYPE(ptr) == AOP_PCODE) + && ((AOP(ptr)->aopu.pcop->type == PO_IMMEDIATE) + || (AOP(ptr)->aopu.pcop->type == PO_DIR))) + { + pic16_emitpcode(POC_MOVLW, pic16_popGet (AOP (ptr), 0)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptrl)); + pic16_emitpcode(POC_MOVLW, pic16_popGet (AOP (ptr), 1)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptrh)); + pic16_emitpcode(POC_MOVLW, pic16_popGet (AOP (ptr), 2)); + pic16_emitpcode(POC_MOVWF, pic16_popCopyReg (&pic16_pc_tblptru)); + } else { + mov2fp(pic16_popCopyReg(&pic16_pc_tblptrl), AOP(ptr), 0); + mov2fp(pic16_popCopyReg(&pic16_pc_tblptrh), AOP(ptr), 1); + mov2fp(pic16_popCopyReg(&pic16_pc_tblptru), AOP(ptr), 2); + } // if + + pic16_emitpcodeNULLop (POC_TBLRD_POSTINC); + pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (&pic16_pc_tablat)); + break; + default: assert (0 && "invalid pointer type specified"); break; @@ -11010,7 +8135,7 @@ static void genDataPointerGet(operand *left, operand *result, iCode *ic) DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset); // pic16_DumpOp("(result)",result); - if(is_LitAOp(AOP(result))) { + if(pic16_isLitAop(AOP(result))) { pic16_mov2w(AOP(left), offset); // patch 8 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset)); } else { @@ -11118,308 +8243,52 @@ static void genNearPointerGet (operand *left, genUnpackBits (result, left, NULL, POINTER); else { /* we have can just get the values */ - int size = AOP_SIZE(result); - int offset = 0; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - pic16_loadFSR0( left, 0 ); - - while(size--) { - if(size) { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), - pic16_popGet(AOP(result), offset++))); - } else { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), - pic16_popGet(AOP(result), offset++))); - } - } - } - -#if 0 - /* now some housekeeping stuff */ - if (aop) { - /* we had to allocate for this iCode */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_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 */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if (AOP_SIZE(result) > 1 - && !OP_SYMBOL(left)->remat - && ( OP_SYMBOL(left)->liveTo > ic->seq - || ic->depth )) { -// int size = AOP_SIZE(result) - 1; -// while (size--) -// pic16_emitcode("dec","%s",rname); - } - } -#endif - - /* done */ - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_freeAsmop(result,NULL,ic,TRUE); -} - -/*-----------------------------------------------------------------*/ -/* genPagedPointerGet - pic16_emitcode for paged pointer fetch */ -/*-----------------------------------------------------------------*/ -static void genPagedPointerGet (operand *left, - operand *result, - iCode *ic) -{ - asmop *aop = NULL; - regs *preg = NULL ; - char *rname ; - sym_link *rtype, *retype; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - rtype = operandType(result); - retype= getSpec(rtype); - - pic16_aopOp(left,ic,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); - pic16_emitcode("mov","%s,%s", - preg->name, - pic16_aopGet(AOP(left),0,FALSE,TRUE)); - rname = preg->name ; - } else - rname = pic16_aopGet(AOP(left),0,FALSE,FALSE); - - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_aopOp (result,ic,TRUE); - - /* if bitfield then unpack the bits */ - if (IS_BITFIELD(retype)) - genUnpackBits (result,left,rname,PPOINTER); - else { - /* we have can just get the values */ - int size = AOP_SIZE(result); - int offset = 0 ; - - while (size--) { - - pic16_emitcode("movx","a,@%s",rname); - pic16_aopPut(AOP(result),"a",offset); - - offset++ ; - - if (size) - pic16_emitcode("inc","%s",rname); - } - } - - /* now some housekeeping stuff */ - if (aop) { - /* we had to allocate for this iCode */ - pic16_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 )) { - int size = AOP_SIZE(result) - 1; - while (size--) - pic16_emitcode("dec","%s",rname); - } - } - - /* done */ - pic16_freeAsmop(result,NULL,ic,TRUE); - - -} - -#if 0 -/* This code is not adjusted to PIC16 and fails utterly. - * On the other hand: PIC16 does not support xdata (the only mem FPOINTERs are used for) anyway... */ - -/*-----------------------------------------------------------------*/ -/* genFarPointerGet - gget value from far space */ -/*-----------------------------------------------------------------*/ -static void genFarPointerGet (operand *left, - operand *result, iCode *ic) -{ - int size, offset ; - sym_link *retype = getSpec(operandType(result)); - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - pic16_aopOp(left,ic,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) - pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE)); - else { /* we need to get it byte by byte */ - pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE)); - pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE)); - if (options.model == MODEL_FLAT24) - { - pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE)); - } - } - } - /* so dptr know contains the address */ - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_aopOp(result,ic,TRUE); - - /* if bit then unpack */ - if (IS_BITFIELD(retype)) - genUnpackBits(result,left,"dptr",FPOINTER); - else { - size = AOP_SIZE(result); - offset = 0 ; - - while (size--) { - pic16_emitcode("movx","a,@dptr"); - pic16_aopPut(AOP(result),"a",offset++); - if (size) - pic16_emitcode("inc","dptr"); - } - } - - pic16_freeAsmop(result,NULL,ic,TRUE); -} -#endif - -#if 0 -/*-----------------------------------------------------------------*/ -/* genCodePointerGet - get value from code space */ -/*-----------------------------------------------------------------*/ -static void genCodePointerGet (operand *left, - operand *result, iCode *ic) -{ - int size, offset ; - sym_link *retype = getSpec(operandType(result)); - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - pic16_aopOp(left,ic,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) - pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE)); - else { /* we need to get it byte by byte */ - pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE)); - pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE)); - if (options.model == MODEL_FLAT24) - { - pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE)); - } - } - } - /* so dptr know contains the address */ - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_aopOp(result,ic,FALSE); - - /* if bit then unpack */ - if (IS_BITFIELD(retype)) - genUnpackBits(result,left,"dptr",CPOINTER); - else { - size = AOP_SIZE(result); - offset = 0 ; - - while (size--) { - pic16_emitcode("clr","a"); - pic16_emitcode("movc","a,@a+dptr"); - pic16_aopPut(AOP(result),"a",offset++); - if (size) - pic16_emitcode("inc","dptr"); - } - } - - pic16_freeAsmop(result,NULL,ic,TRUE); -} -#endif - -#if 0 -/*-----------------------------------------------------------------*/ -/* genGenPointerGet - gget value from generic pointer space */ -/*-----------------------------------------------------------------*/ -static void genGenPointerGet (operand *left, - operand *result, iCode *ic) -{ - int size, offset, lit; - sym_link *retype = getSpec(operandType(result)); - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,FALSE); - size = AOP_SIZE(result); - - DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); - - if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!) - - lit = (unsigned) ulFromVal (AOP(left)->aopu.aop_lit); - // load FSR0 from immediate - pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit))); + int size = AOP_SIZE(result); + int offset = 0; -// pic16_loadFSR0( left ); + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - offset = 0; - while(size--) { - if(size) { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset))); - } else { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset))); - } - offset++; - } - goto release; + pic16_loadFSR0( left, 0 ); + while(size--) { + if(size) { + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), + pic16_popGet(AOP(result), offset++))); + } else { + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), + pic16_popGet(AOP(result), offset++))); } - else { /* we need to get it byte by byte */ - // set up FSR0 with address from left - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); - - offset = 0 ; + } + } - while(size--) { - if(size) { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset))); - } else { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset))); - } - offset++; - } - goto release; +#if 0 + /* now some housekeeping stuff */ + if (aop) { + /* we had to allocate for this iCode */ + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + pic16_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 */ + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + if (AOP_SIZE(result) > 1 + && !OP_SYMBOL(left)->remat + && ( OP_SYMBOL(left)->liveTo > ic->seq + || ic->depth )) { +// int size = AOP_SIZE(result) - 1; +// while (size--) +// pic16_emitcode("dec","%s",rname); } - - /* if bit then unpack */ - if (IS_BITFIELD(retype)) - genUnpackBits(result,left,"BAD",GPOINTER); - - release: - pic16_freeAsmop(left,NULL,ic,TRUE); - pic16_freeAsmop(result,NULL,ic,TRUE); - -} + } #endif + /* done */ + pic16_freeAsmop(left,NULL,ic,TRUE); + pic16_freeAsmop(result,NULL,ic,TRUE); +} /*-----------------------------------------------------------------*/ /* genGenPointerGet - gget value from generic pointer space */ @@ -11427,54 +8296,29 @@ static void genGenPointerGet (operand *left, static void genGenPointerGet (operand *left, operand *result, iCode *ic) { - int size, offset, lit; + int size; sym_link *letype = getSpec(operandType(left)); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_aopOp(left,ic,FALSE); - pic16_aopOp(result,ic,TRUE); - size = AOP_SIZE(result); - - DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); - - /* if bit then unpack */ - if (IS_BITFIELD(letype)) { - genUnpackBits(result,left,"BAD",GPOINTER); - goto release; - } - - if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!) - - lit = (unsigned) ulFromVal (AOP(left)->aopu.aop_lit); - // load FSR0 from immediate - pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit))); - - werror(W_POSSBUG2, __FILE__, __LINE__); - - offset = 0; - while(size--) { - if(size) { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset))); - } else { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset))); - } - offset++; - } - - goto release; + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + pic16_aopOp(left,ic,FALSE); + pic16_aopOp(result,ic,TRUE); + size = AOP_SIZE(result); - } else { /* we need to get it byte by byte */ + DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); - /* set up WREG:PRODL:FSR0L with address from left */ - mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0); - mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1); - pic16_mov2w(AOP(left), 2); - pic16_callGenericPointerRW(0, size); + /* if bit then unpack */ + if (IS_BITFIELD(letype)) { + genUnpackBits(result,left,"BAD",GPOINTER); + goto release; + } - assignResultValue(result, size, 1); + /* set up WREG:PRODL:FSR0L with address from left */ + mov2fp(pic16_popCopyReg(&pic16_pc_fsr0l), AOP(left), 0); + mov2fp(pic16_popCopyReg(&pic16_pc_prodl), AOP(left), 1); + pic16_mov2w(AOP(left), 2); + pic16_callGenericPointerRW(0, size); - goto release; - } + assignResultValue(result, size, 1); release: pic16_freeAsmop(left,NULL,ic,TRUE); @@ -11499,6 +8343,12 @@ static void genConstPointerGet (operand *left, pic16_aopOp(result,ic,TRUE); size = AOP_SIZE(result); + /* if bit then unpack */ + if (IS_BITFIELD(getSpec (operandType (left)))) { + genUnpackBits(result,left,"BAD",GPOINTER); + goto release; + } // if + DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result); DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__); @@ -11526,6 +8376,7 @@ static void genConstPointerGet (operand *left, offset++; } +release: pic16_freeAsmop(left,NULL,ic,TRUE); pic16_freeAsmop(result,NULL,ic,TRUE); } @@ -11593,20 +8444,9 @@ static void genPointerGet (iCode *ic) case POINTER: case FPOINTER: case IPOINTER: - genNearPointerGet (left,result,ic); - break; - case PPOINTER: - genPagedPointerGet(left,result,ic); - break; - -#if 0 - /* PICs do not support FAR pointers... */ - /* MUST move them somewhere; handle FPOINTERs like POINTERS or like GPOINTERs?!? */ - case FPOINTER: - genFarPointerGet (left,result,ic); + genNearPointerGet (left,result,ic); break; -#endif case CPOINTER: genConstPointerGet (left,result,ic); @@ -11951,7 +8791,6 @@ static void genNearPointerSet (operand *right, /* and result is not a bit variable */ if (AOP_TYPE(result) == AOP_PCODE -// && AOP_TYPE(result) == AOP_IMMD && DCL_TYPE(ptype) == POINTER && !IS_BITFIELD(retype) && !IS_BITFIELD(resetype)) { @@ -11977,7 +8816,7 @@ static void genNearPointerSet (operand *right, DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); while (size--) { - if (is_LitOp(right)) { + if (pic16_isLitOp(right)) { pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset)); if (size) { pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0)); @@ -12032,269 +8871,9 @@ static void genNearPointerSet (operand *right, pic16_freeAsmop(result,NULL,ic,TRUE); } -/*-----------------------------------------------------------------*/ -/* genPagedPointerSet - pic16_emitcode for Paged pointer put */ -/*-----------------------------------------------------------------*/ -static void genPagedPointerSet (operand *right, - operand *result, - iCode *ic) -{ - asmop *aop = NULL; - regs *preg = NULL ; - char *rname , *l; - sym_link *retype; - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - retype= getSpec(operandType(right)); - - pic16_aopOp(result,ic,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); - pic16_emitcode("mov","%s,%s", - preg->name, - pic16_aopGet(AOP(result),0,FALSE,TRUE)); - rname = preg->name ; - } else - rname = pic16_aopGet(AOP(result),0,FALSE,FALSE); - - pic16_freeAsmop(result,NULL,ic,TRUE); - pic16_aopOp (right,ic,FALSE); - - /* if bitfield then unpack the bits */ - if (IS_BITFIELD(retype)) - genPackBits (retype,result,right,rname,PPOINTER); - else { - /* we have can just get the values */ - int size = AOP_SIZE(right); - int offset = 0 ; - - while (size--) { - l = pic16_aopGet(AOP(right),offset,FALSE,TRUE); - - MOVA(l); - pic16_emitcode("movx","@%s,a",rname); - - if (size) - pic16_emitcode("inc","%s",rname); - - offset++; - } - } - - /* now some housekeeping stuff */ - if (aop) { - /* we had to allocate for this iCode */ - pic16_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 )) { - int size = AOP_SIZE(right) - 1; - while (size--) - pic16_emitcode("dec","%s",rname); - } - } - - /* done */ - pic16_freeAsmop(right,NULL,ic,TRUE); - - -} - -#if 0 -/* This code is not adjusted to PIC16 and fails utterly... - * On the other hand: PIC16 has no xdata anyway (the only memory FPOINTERs are use for) */ - -/*-----------------------------------------------------------------*/ -/* genFarPointerSet - set value from far space */ -/*-----------------------------------------------------------------*/ -static void genFarPointerSet (operand *right, - operand *result, iCode *ic) -{ - int size, offset ; - sym_link *retype = getSpec(operandType(right)); - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - pic16_aopOp(result,ic,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) - pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE)); - else { /* we need to get it byte by byte */ - pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE)); - pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE)); - if (options.model == MODEL_FLAT24) - { - pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE)); - } - } - } - /* so dptr know contains the address */ - pic16_freeAsmop(result,NULL,ic,TRUE); - pic16_aopOp(right,ic,FALSE); - - /* if bit then unpack */ - if (IS_BITFIELD(retype)) - genPackBits(retype,result,right,"dptr",FPOINTER); - else { - size = AOP_SIZE(right); - offset = 0 ; - - while (size--) { - char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE); - MOVA(l); - pic16_emitcode("movx","@dptr,a"); - if (size) - pic16_emitcode("inc","dptr"); - } - } - - pic16_freeAsmop(right,NULL,ic,TRUE); -} -#endif - /*-----------------------------------------------------------------*/ /* genGenPointerSet - set value from generic pointer space */ /*-----------------------------------------------------------------*/ -#if 0 -static void genGenPointerSet (operand *right, - operand *result, iCode *ic) -{ - int i, size, offset, lit; - sym_link *retype = getSpec(operandType(right)); - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - pic16_aopOp(result,ic,FALSE); - pic16_aopOp(right,ic,FALSE); - size = AOP_SIZE(right); - offset = 0; - - DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result); - - /* 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 */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - // WARNING: anythig until "else" is untested! - if (AOP_TYPE(result) == AOP_IMMD) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - lit = (unsigned) ulFromVal (AOP(result)->aopu.aop_lit); - // load FSR0 from immediate - pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit))); - offset = 0; - while(size--) { - if(size) { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0))); - } else { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0))); - } - offset++; - } - goto release; - } - else { /* we need to get it byte by byte */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE); - - // set up FSR0 with address of result - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); - - /* hack hack! see if this the FSR. If so don't load W */ - if(AOP_TYPE(right) != AOP_ACC) { - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - if(AOP_TYPE(right) == AOP_LIT) - { - // copy literal - // note: pic16_popGet handles sign extension - for(i=0;iname, OP_SYMBOL(right)->name); + //fprintf(stderr, "%s:%d symbol %s = [ %s ] is in code space\n", __FILE__, __LINE__, OP_SYMBOL(result)->name, OP_SYMBOL(right)->name); // set up table pointer - if(is_LitOp(right)) { + if(pic16_isLitOp(right)) { // fprintf(stderr, "%s:%d inside block 1\n", __FILE__, __LINE__); pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(right),0)); pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl)); @@ -12826,8 +9366,8 @@ static void genAssign (iCode *ic) pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right))); release: - pic16_freeAsmop (right,NULL,ic,FALSE); pic16_freeAsmop (result,NULL,ic,TRUE); + pic16_freeAsmop (right,NULL,ic,FALSE); } /*-----------------------------------------------------------------*/ @@ -13234,38 +9774,6 @@ static void genCast (iCode *ic) #endif DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__); -#if 0 - if(AOP_TYPE(right) == AOP_IMMD) { - pCodeOp *pcop0, *pcop1, *pcop2; - symbol *sym = OP_SYMBOL( right ); - - size = AOP_SIZE(result); - /* low */ - pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype)))); - /* high */ - pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype)))); - /* upper */ - pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype)))); - - if (size == 3) { - pic16_emitpcode(POC_MOVLW, pcop0); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); - pic16_emitpcode(POC_MOVLW, pcop1); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1)); - pic16_emitpcode(POC_MOVLW, pcop2); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2)); - } else - if (size == 2) { - pic16_emitpcode(POC_MOVLW, pcop0); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_MOVLW, pcop1); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1)); - } else { - pic16_emitpcode(POC_MOVLW, pcop0); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); - } - } else -#endif if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) { pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); @@ -13299,7 +9807,6 @@ static void genCast (iCode *ic) /* pointer to generic pointer */ if (IS_GENPTR(ctype)) { - char *l = zero; if (IS_PTR(type)) p_type = DCL_TYPE(type); @@ -13348,9 +9855,10 @@ static void genCast (iCode *ic) } /* the last byte depending on type */ switch (p_type) { - case IPOINTER: case POINTER: case FPOINTER: + case IPOINTER: + case PPOINTER: pic16_movLit2f(pic16_popGet(AOP(result), GPTRSIZE-1), GPTR_TAG_DATA); break; @@ -13358,11 +9866,6 @@ static void genCast (iCode *ic) pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), GPTRSIZE-1)); break; - case PPOINTER: - pic16_emitcode(";BUG!? ","%d",__LINE__); - l = "#0x03"; - break; - case GPOINTER: if (GPTRSIZE > AOP_SIZE(right)) { // assume __data pointer... THIS MIGHT BE WRONG! @@ -13489,21 +9992,8 @@ static int genDjnz (iCode *ic, iCode *ifx) pic16_aopOp(IC_RESULT(ic),ic,FALSE); - if (IS_AOP_PREG(IC_RESULT(ic))) { - pic16_emitcode("dec","%s", - pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); - pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); - pic16_emitcode("jnz","%05d_DS_",lbl->key+100); - } else { - - - pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0)); - pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); - - pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); - pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + pic16_labelOffset); - - } + pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0)); + pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key)); pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); ifx->generated = 1; @@ -13572,7 +10062,6 @@ static void genDummyRead (iCode * ic) { operand *op; - int i; op = IC_RIGHT(ic); if (op && IS_SYMOP(op)) { @@ -13581,12 +10070,7 @@ genDummyRead (iCode * ic) return; } pic16_aopOp (op, ic, FALSE); - for (i=0; i < AOP_SIZE(op); i++) { - // may need to protect this from the peepholer -- this is not nice but works... - pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - BEGIN")); - pic16_mov2w (AOP(op),i); - pic16_addpCode2pBlock(pb,pic16_newpCodeAsmDir(";", "VOLATILE READ - END")); - } // for i + pic16_mov2w_volatile(AOP(op)); pic16_freeAsmop (op, NULL, ic, TRUE); } else if (op) { fprintf (stderr, "%s: not implemented for non-symbols (volatile operand might not be read)\n", __FUNCTION__); @@ -13863,4 +10347,3 @@ void genpic16Code (iCode *lic) return; } -