X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic16%2Fgenarith.c;h=1664b0cf493ff6f1edd8cc2c344f133ff98f7171;hb=b607b5d8114974999bc6260698998e98ac04de86;hp=2015eb59ceccf527ff61af8d749146a7a3d2512e;hpb=282ac6dc581f9490727d70a1a25b94d18a14010d;p=fw%2Fsdcc diff --git a/src/pic16/genarith.c b/src/pic16/genarith.c index 2015eb59..1664b0cf 100644 --- a/src/pic16/genarith.c +++ b/src/pic16/genarith.c @@ -59,109 +59,101 @@ pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst); const char *pic16_AopType(short type) { switch(type) { - case AOP_LIT: - return "AOP_LIT"; - break; - case AOP_REG: - return "AOP_REG"; - break; - case AOP_DIR: - return "AOP_DIR"; - break; - case AOP_DPTR: - return "AOP_DPTR"; - break; - case AOP_DPTR2: - return "AOP_DPTR2"; - break; - case AOP_R0: - return "AOP_R0"; - break; - case AOP_R1: - return "AOP_R1"; - break; - case AOP_STK: - return "AOP_STK"; - break; - case AOP_IMMD: - return "AOP_IMMD"; - break; - case AOP_STR: - return "AOP_STR"; - break; - case AOP_CRY: - return "AOP_CRY"; - break; - case AOP_ACC: - return "AOP_ACC"; - break; - case AOP_PCODE: - return "AOP_PCODE"; - break; + case AOP_LIT: return "AOP_LIT"; + case AOP_REG: return "AOP_REG"; + case AOP_DIR: return "AOP_DIR"; + case AOP_DPTR: return "AOP_DPTR"; + case AOP_DPTR2: return "AOP_DPTR2"; + case AOP_FSR0: return "AOP_FSR0"; + case AOP_FSR2: return "AOP_FSR2"; + case AOP_R0: return "AOP_R0"; + case AOP_R1: return "AOP_R1"; + case AOP_STK: return "AOP_STK"; + case AOP_IMMD: return "AOP_IMMD"; + case AOP_STR: return "AOP_STR"; + case AOP_CRY: return "AOP_CRY"; + case AOP_ACC: return "AOP_ACC"; + case AOP_PCODE: return "AOP_PCODE"; + case AOP_STA: return "AOP_STA"; } return "BAD TYPE"; } -const char *pic16_pCodeOpType( pCodeOp *pcop) +const char *pic16_pCodeOpType(pCodeOp *pcop) { if(pcop) { switch(pcop->type) { - case PO_NONE: - return "PO_NONE"; - case PO_W: - return "PO_W"; - case PO_WREG: - return "PO_WREG"; - case PO_STATUS: - return "PO_STATUS"; - case PO_BSR: - return "PO_BSR"; - case PO_FSR0: - return "PO_FSR0"; - case PO_INDF0: - return "PO_INDF0"; - case PO_INTCON: - return "PO_INTCON"; - case PO_GPR_REGISTER: - return "PO_GPR_REGISTER"; - case PO_GPR_BIT: - return "PO_GPR_BIT"; - case PO_GPR_TEMP: - return "PO_GPR_TEMP"; - case PO_SFR_REGISTER: - return "PO_SFR_REGISTER"; - case PO_PCL: - return "PO_PCL"; - case PO_PCLATH: - return "PO_PCLATH"; - case PO_PCLATU: - return "PO_PCLATU"; - case PO_PRODL: - return "PO_PRODL"; - case PO_PRODH: - return "PO_PRODH"; - case PO_LITERAL: - return "PO_LITERAL"; - case PO_REL_ADDR: - return "PO_REL_ADDR"; - case PO_IMMEDIATE: - return "PO_IMMEDIATE"; - case PO_DIR: - return "PO_DIR"; - case PO_CRY: - return "PO_CRY"; - case PO_BIT: - return "PO_BIT"; - case PO_STR: - return "PO_STR"; - case PO_LABEL: - return "PO_LABEL"; - case PO_WILD: - return "PO_WILD"; + case PO_NONE: return "PO_NONE"; + case PO_W: return "PO_W"; + case PO_WREG: return "PO_WREG"; + case PO_STATUS: return "PO_STATUS"; + case PO_BSR: return "PO_BSR"; + case PO_FSR0: return "PO_FSR0"; + case PO_INDF0: return "PO_INDF0"; + case PO_INTCON: return "PO_INTCON"; + case PO_GPR_REGISTER: return "PO_GPR_REGISTER"; + case PO_GPR_BIT: return "PO_GPR_BIT"; + case PO_GPR_TEMP: return "PO_GPR_TEMP"; + case PO_SFR_REGISTER: return "PO_SFR_REGISTER"; + case PO_PCL: return "PO_PCL"; + case PO_PCLATH: return "PO_PCLATH"; + case PO_PCLATU: return "PO_PCLATU"; + case PO_PRODL: return "PO_PRODL"; + case PO_PRODH: return "PO_PRODH"; + case PO_LITERAL: return "PO_LITERAL"; + case PO_REL_ADDR: return "PO_REL_ADDR"; + case PO_IMMEDIATE: return "PO_IMMEDIATE"; + case PO_DIR: return "PO_DIR"; + case PO_CRY: return "PO_CRY"; + case PO_BIT: return "PO_BIT"; + case PO_STR: return "PO_STR"; + case PO_LABEL: return "PO_LABEL"; + case PO_WILD: return "PO_WILD"; + case PO_TWO_OPS: return "PO_TWO_OPS"; + } + } + + return "BAD PO_TYPE"; +} + +const char *pic16_pCodeOpSubType(pCodeOp *pcop) +{ + + if(pcop && (pcop->type == PO_GPR_BIT)) { + + switch(PCORB(pcop)->subtype) { + + case PO_NONE: return "PO_NONE"; + case PO_W: return "PO_W"; + case PO_WREG: return "PO_WREG"; + case PO_STATUS: return "PO_STATUS"; + case PO_BSR: return "PO_BSR"; + case PO_FSR0: return "PO_FSR0"; + case PO_INDF0: return "PO_INDF0"; + case PO_INTCON: return "PO_INTCON"; + case PO_GPR_REGISTER: return "PO_GPR_REGISTER"; + case PO_GPR_BIT: return "PO_GPR_BIT"; + case PO_GPR_TEMP: return "PO_GPR_TEMP"; + case PO_SFR_REGISTER: return "PO_SFR_REGISTER"; + case PO_PCL: return "PO_PCL"; + case PO_PCLATH: return "PO_PCLATH"; + case PO_PCLATU: return "PO_PCLATU"; + case PO_PRODL: return "PO_PRODL"; + case PO_PRODH: return "PO_PRODH"; + case PO_LITERAL: return "PO_LITERAL"; + case PO_REL_ADDR: return "PO_REL_ADDR"; + case PO_IMMEDIATE: return "PO_IMMEDIATE"; + case PO_DIR: return "PO_DIR"; + case PO_CRY: return "PO_CRY"; + case PO_BIT: return "PO_BIT"; + case PO_STR: return "PO_STR"; + case PO_LABEL: return "PO_LABEL"; + case PO_WILD: return "PO_WILD"; + case PO_TWO_OPS: return "PO_TWO_OPS"; } } @@ -173,10 +165,11 @@ const char *pic16_pCodeOpType( pCodeOp *pcop) /*-----------------------------------------------------------------*/ bool pic16_genPlusIncr (iCode *ic) { - unsigned int icount ; - unsigned int size = pic16_getDataSize(IC_RESULT(ic)); + unsigned int icount ; + unsigned int size = pic16_getDataSize(IC_RESULT(ic)); + + FENTRY; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); DEBUGpic16_emitcode ("; ","result %s, left %s, right %s", pic16_AopType(AOP_TYPE(IC_RESULT(ic))), pic16_AopType(AOP_TYPE(IC_LEFT(ic))), @@ -204,7 +197,7 @@ bool pic16_genPlusIncr (iCode *ic) //pic16_emitcode("incf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)); while(--size) { - emitSKPNZ; + emitSKPNC; pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),offset++)); //pic16_emitcode(" incf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE)); } @@ -212,7 +205,7 @@ bool pic16_genPlusIncr (iCode *ic) return TRUE; } - DEBUGpic16_emitcode ("; ","%s %d",__FUNCTION__,__LINE__); +// DEBUGpic16_emitcode ("; ","%s %d",__FUNCTION__,__LINE__); /* if left is in accumulator - probably a bit operation*/ // VR - why this is a bit operation?! if( (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) && (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) { @@ -268,6 +261,8 @@ void pic16_outBitAcc(operand *result) /* if the result is a bit */ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + assert(0); // not implemented for PIC16? + if (AOP_TYPE(result) == AOP_CRY){ pic16_aopPut(AOP(result),"a",0); } @@ -284,8 +279,7 @@ void pic16_outBitAcc(operand *result) /*-----------------------------------------------------------------*/ void pic16_genPlusBits (iCode *ic) { - - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; DEBUGpic16_emitcode ("; ","result %s, left %s, right %s", pic16_AopType(AOP_TYPE(IC_RESULT(ic))), @@ -424,12 +418,14 @@ static void adjustArithmeticResult(iCode *ic) } #endif +#if 1 /*-----------------------------------------------------------------*/ /* genAddlit - generates code for addition */ /*-----------------------------------------------------------------*/ static void genAddLit2byte (operand *result, int offr, int lit) { - + FENTRY; + switch(lit & 0xff) { case 0: break; @@ -445,6 +441,7 @@ static void genAddLit2byte (operand *result, int offr, int lit) } } +#endif static void emitMOVWF(operand *reg, int offset) { @@ -460,6 +457,9 @@ static void emitMOVWF(operand *reg, int offset) } + +#if 1 + static void genAddLit (iCode *ic, int lit) { @@ -469,7 +469,7 @@ static void genAddLit (iCode *ic, int lit) operand *result; operand *left; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; left = IC_LEFT(ic); @@ -534,6 +534,13 @@ static void genAddLit (iCode *ic, int lit) pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0)); pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); + break; + default: /* 0x01LL */ + pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); + pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0)); + emitSKPNC; + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); } break; @@ -573,10 +580,9 @@ static void genAddLit (iCode *ic, int lit) genAddLit2byte (result, MSB16, hi); break; case 1: /* 0xHH01 */ - pic16_emitpcode(POC_MOVLW,pic16_popGetLit((hi+1)&0xff)); - pic16_emitpcode(POC_INCFSZ, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0)); pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi)); - pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),MSB16)); + pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16)); break; /* case 0xff: * 0xHHff * pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0,FALSE,FALSE)); @@ -588,9 +594,7 @@ static void genAddLit (iCode *ic, int lit) pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0)); pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi)); - emitSKPNC; - pic16_emitpcode(POC_MOVLW,pic16_popGetLit((hi+1) & 0xff)); - pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),MSB16)); + pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16)); break; } @@ -605,44 +609,8 @@ static void genAddLit (iCode *ic, int lit) lo = BYTEofLONG(lit,0); if(carry_info) { - switch(lo) { - case 0: - switch(carry_info) { - case 1: - emitSKPNZ; - pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset)); - break; - case 2: - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offset)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(1)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset)); - break; - default: /* carry_info = 3 */ - emitSKPNC; - pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset)); - carry_info = 1; - break; - } - break; - case 0xff: - pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); - if(carry_info==1) - emitSKPZ; - else - emitSKPC; - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset)); - break; - default: - pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); - if(carry_info==1) - emitSKPNZ; - else - emitSKPNC; - pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo+1)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset)); - carry_info=2; - break; - } + pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); + pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset)); }else { /* no carry info from previous step */ /* this means this is the first time to add */ @@ -688,7 +656,6 @@ static void genAddLit (iCode *ic, int lit) } } - } */ } @@ -714,10 +681,8 @@ static void genAddLit (iCode *ic, int lit) /* left addend is in a register */ switch(lit & 0xff) { case 0: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); + pic16_mov2w(AOP(left),0); emitMOVWF(result, 0); - //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE)); - emitMOVWF(result,0); break; case 1: pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0)); @@ -745,176 +710,530 @@ static void genAddLit (iCode *ic, int lit) pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); } else { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); + pic16_mov2w(AOP(left),0); /* We don't know the state of the carry bit at this point */ clear_carry = 1; } //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE)); emitMOVWF(result,0); while(--size) { - lit >>= 8; - if(lit & 0xff) { - if(clear_carry) { - /* The ls byte of the lit must've been zero - that - means we don't have to deal with carry */ - - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(left),offset)); - - clear_carry = 0; - - } else { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); - //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset,FALSE,FALSE)); - emitMOVWF(result,offset); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset)); - emitSKPNC; - pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset)); - } - + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); + if (offset < AOP_SIZE(left)) { + pic16_emitpcode(clear_carry ? POC_ADDFW : POC_ADDFWC, pic16_popGet(AOP(left),offset)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); } else { - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offset)); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset)); + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); + if (!SPEC_USIGN(operandType(IC_LEFT(ic)))) { + /* sign-extend left (in result) */ + pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left),AOP_SIZE(left)-1,7)); + pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset)); + } + pic16_emitpcode(clear_carry ? POC_ADDWF : POC_ADDWFC, pic16_popGet(AOP(result),offset)); } + clear_carry = 0; offset++; } } } } -/*-----------------------------------------------------------------*/ -/* pic16_genPlus - generates code for addition */ -/*-----------------------------------------------------------------*/ -void pic16_genPlus (iCode *ic) +#else + /* this fails when result is an SFR because value is written there + * during addition and not at the end */ + +static void genAddLit (iCode *ic, int lit) { - int i, size, offset = 0; - operand *result, *left, *right; - - /* special cases :- */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - - result = IC_RESULT(ic); - left = IC_LEFT(ic); - right = IC_RIGHT(ic); - pic16_aopOp (left,ic,FALSE); - pic16_aopOp (right,ic,FALSE); - pic16_aopOp (result,ic,TRUE); - DEBUGpic16_pic16_AopType(__LINE__,left, right, result); - // pic16_DumpOp("(left)",left); + int size,sizeL,same; + int i, llit; - /* if literal, literal on the right or - if left requires ACC or right is already - in ACC */ - - if ( (AOP_TYPE(left) == AOP_LIT) || (pic16_sameRegs(AOP(right), AOP(result))) ) { - operand *t = right; - right = left; - left = t; - } + operand *result; + operand *left; + sym_link *lleft; - /* if both left & right are in bit space */ - if (AOP_TYPE(left) == AOP_CRY && - AOP_TYPE(right) == AOP_CRY) { - pic16_genPlusBits (ic); - goto release ; - } + FENTRY; - /* if left in bit space & right literal */ - if (AOP_TYPE(left) == AOP_CRY && - AOP_TYPE(right) == AOP_LIT) { - /* if result in bit space */ - if(AOP_TYPE(result) == AOP_CRY){ - if((unsigned long)floatFromVal(AOP(right)->aopu.aop_lit) != 0L) { - pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),0)); - if (!pic16_sameRegs(AOP(left), AOP(result)) ) - pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),0)); - } - } else { - size = pic16_getDataSize(result); - while (size--) { - MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - pic16_emitcode("addc","a,#00 ;%d",__LINE__); - pic16_aopPut(AOP(result),"a",offset++); - } - } - goto release ; - } // left == CRY - /* if I can do an increment instead - of add then GOOD for ME */ - if (pic16_genPlusIncr (ic) == TRUE) - goto release; + left = IC_LEFT(ic); + lleft = operandType (left); + result = IC_RESULT(ic); + same = pic16_sameRegs(AOP(left), AOP(result)); + size = pic16_getDataSize(result); + sizeL = pic16_getDataSize(left); + llit = lit; + +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + /* move left to result -- possibly sign extend */ + for (i=0; i < MIN(size, sizeL); i++) { + pic16_mov2f (AOP(result), AOP(left), i); + } // for i +#undef MIN + + /* extend to result size */ + if (IS_UNSIGNED(lleft)) { + /* zero-extend */ + for (i = sizeL; i < size; i++) { + pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), i)); + } // for i + } else { + /* sign-extend */ + if (size == sizeL + 1) { + pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), sizeL)); + pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP(left),sizeL-1,7)); + pic16_emitpcode (POC_SETF, pic16_popGet (AOP(result), sizeL)); + } else { + pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg)); + pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP(left),sizeL-1,7)); + pic16_emitpcode (POC_SETF, pic16_popCopyReg (&pic16_pc_wreg)); + + for (i=sizeL; i < size; i++) { + pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), i)); + } // for i + } // if + } // if (SIGNED) + + /* special cases */ + if (lit == 0) { + /* nothing to do */ + } else if (lit == 1) { + switch (size) { + case 1: + /* handled below */ + break; + case 2: + pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(result), 0)); + break; + default: + assert (size > 2); + pic16_emitpcode (POC_INCF, pic16_popGet(AOP(result), 0)); + for (i=1; i < size-1; i++) { + emitSKPNC; /* a jump here saves up to 2(size-2)cycles */ + pic16_emitpcode (POC_INCF, pic16_popGet(AOP(result), i)); + } // for i + emitSKPNC; + break; + } // switch + + pic16_emitpcode (POC_INCF, pic16_popGet (AOP(result), size-1)); + } else { + /* general case */ + + /* add literal to result */ + for (i=0; i < size; i++) { + pic16_emitpcode (POC_MOVLW, pic16_popGetLit (llit)); + llit >>= 8; /* FIXME: arithmetic right shift for signed literals? */ + pic16_emitpcode (i == 0 ? POC_ADDWF : POC_ADDWFC, + pic16_popGet (AOP(result), i)); + } + } - size = pic16_getDataSize(IC_RESULT(ic)); +#if 0 - if(AOP(IC_RIGHT(ic))->type == AOP_LIT) { - /* Add a literal to something else */ - //bool know_W=0; - unsigned lit = (unsigned) floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit); - //unsigned l1=0; + if(same) { - //offset = 0; - DEBUGpic16_emitcode(";","adding lit to something. size %d",size); + /* Handle special cases first */ + if(size == 1) + genAddLit2byte (result, 0, lit); + + else if(size == 2) { + int hi = 0xff & (lit >> 8); + lo = lit & 0xff; - genAddLit (ic, lit); - goto release; + switch(hi) { + case 0: - } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) { + /* lit = 0x00LL */ + DEBUGpic16_emitcode ("; hi = 0","%s %d",__FUNCTION__,__LINE__); + switch(lo) { + case 0: + break; + case 1: + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0)); + emitSKPNZ; + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); + break; + case 0xff: + pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); - pic16_emitcode(";bitadd","right is bit: %s",pic16_aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE)); - pic16_emitcode(";bitadd","left is bit: %s",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE)); - pic16_emitcode(";bitadd","result is bit: %s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); + break; + default: + pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff)); + pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0)); + emitSKPNC; + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); - /* here we are adding a bit to a char or int */ - if(size == 1) { - if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) { - pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0)); - pic16_emitpcode(POC_INCF , pic16_popGet(AOP(IC_RESULT(ic)),0)); + } + break; - pic16_emitcode("btfsc","(%s >> 3), (%s & 7)", - AOP(IC_RIGHT(ic))->aopu.aop_dir, - AOP(IC_RIGHT(ic))->aopu.aop_dir); - pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); - } else { // not same + case 1: + /* lit = 0x01LL */ + DEBUGpic16_emitcode ("; hi = 1","%s %d",__FUNCTION__,__LINE__); + switch(lo) { + case 0: /* 0x0100 */ + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); + break; + case 1: /* 0x0101 */ + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0)); + emitSKPNZ; + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); + break; + case 0xff: /* 0x01ff */ + pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); + break; + default: /* 0x01LL */ + pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); + pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0)); + emitSKPNC; + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); + } + break; - if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) { - pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0)); - pic16_emitpcode(POC_XORLW , pic16_popGetLit(1)); + case 0xff: + DEBUGpic16_emitcode ("; hi = ff","%s %d",__FUNCTION__,__LINE__); + /* lit = 0xffLL */ + switch(lo) { + case 0: /* 0xff00 */ + pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16)); + break; + case 1: /*0xff01 */ + pic16_emitpcode(POC_INCFSZ, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16)); + break; +/* case 0xff: * 0xffff * + pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0,FALSE,FALSE)); + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16,FALSE,FALSE)); + pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0,FALSE,FALSE)); + break; +*/ + default: + pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); + pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0)); + emitSKPC; + pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16)); + + } - pic16_emitcode("btfsc","(%s >> 3), (%s & 7)", - AOP(IC_RIGHT(ic))->aopu.aop_dir, - AOP(IC_RIGHT(ic))->aopu.aop_dir); - pic16_emitcode(" xorlw","1"); - } else { - pic16_emitpcode(POC_MOVFW , pic16_popGet(AOP(IC_LEFT(ic)),0)); - pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0)); - pic16_emitpcode(POC_INCFW , pic16_popGet(AOP(IC_LEFT(ic)),0)); + break; + + default: + DEBUGpic16_emitcode ("; hi is generic","%d %s %d",hi,__FUNCTION__,__LINE__); - pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE)); + /* lit = 0xHHLL */ + switch(lo) { + case 0: /* 0xHH00 */ + genAddLit2byte (result, MSB16, hi); + break; + case 1: /* 0xHH01 */ + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi)); + pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16)); + break; +/* case 0xff: * 0xHHff * + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0,FALSE,FALSE)); + pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16,FALSE,FALSE)); + pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi)); + pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),MSB16,FALSE,FALSE)); + break; +*/ default: /* 0xHHLL */ + pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); + pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi)); + pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16)); + break; + } + + } + } else { + int carry_info = 0; + int offset = 0; + /* size > 2 */ + DEBUGpic16_emitcode ("; add lit to long","%s %d",__FUNCTION__,__LINE__); + + while(size--) { + lo = BYTEofLONG(lit,0); + + if(carry_info) { + pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); + pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset)); + }else { + /* no carry info from previous step */ + /* this means this is the first time to add */ + switch(lo) { + case 0: + break; + case 1: + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset)); + carry_info=1; + break; + default: + pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); + pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset)); + if(lit <0x100) + carry_info = 3; /* Were adding only one byte and propogating the carry */ + else + carry_info = 2; + break; + } + } + offset++; + lit >>= 8; + } + +/* + lo = BYTEofLONG(lit,0); + + if(lit < 0x100) { + if(lo) { + if(lo == 1) { + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0,FALSE,FALSE)); + emitSKPNZ; + } else { + pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); + pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0,FALSE,FALSE)); + emitSKPNC; + } + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),1,FALSE,FALSE)); + emitSKPNZ; + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),2,FALSE,FALSE)); + emitSKPNZ; + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),3,FALSE,FALSE)); + + } + } + +*/ + } + } else { + int offset = 1; + DEBUGpic16_emitcode ("; left and result aren't same","%s %d",__FUNCTION__,__LINE__); + + if(size == 1) { + + if(AOP_TYPE(left) == AOP_ACC) { + /* left addend is already in accumulator */ + switch(lit & 0xff) { + case 0: + //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE)); + emitMOVWF(result,0); + break; + default: + pic16_emitpcode(POC_ADDLW, pic16_popGetLit(lit & 0xff)); + //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE)); + emitMOVWF(result,0); + } + } else { + /* left addend is in a register */ + switch(lit & 0xff) { + case 0: + pic16_mov2w(AOP(left),0); + emitMOVWF(result, 0); + break; + case 1: + pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0)); + //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE)); + emitMOVWF(result,0); + break; + case 0xff: + pic16_emitpcode(POC_DECFW, pic16_popGet(AOP(left),0)); + //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE)); + emitMOVWF(result,0); + break; + default: + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); + pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); + //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE)); + emitMOVWF(result,0); + } + } + + } else { + int clear_carry=0; + + /* left is not the accumulator */ + if(lit & 0xff) { + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); + pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); + } else { + pic16_mov2w(AOP(left),0); + /* We don't know the state of the carry bit at this point */ + clear_carry = 1; + } + //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE)); + emitMOVWF(result,0); + while(--size) { + + lit >>= 8; + if(lit & 0xff) { + if(clear_carry) { + /* The ls byte of the lit must've been zero - that + means we don't have to deal with carry */ + + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); + pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offset)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); + + clear_carry = 0; + + } else { + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); + pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),offset)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); + } + + } else { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); + pic16_mov2w(AOP(left),offset); + pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset)); + } + offset++; + } + } + } +#endif +} + +#endif + +/*-----------------------------------------------------------------*/ +/* pic16_genPlus - generates code for addition */ +/*-----------------------------------------------------------------*/ +void pic16_genPlus (iCode *ic) +{ + int i, size, offset = 0; + operand *result, *left, *right; + + FENTRY; + + /* special cases :- */ + result = IC_RESULT(ic); + left = IC_LEFT(ic); + right = IC_RIGHT(ic); + pic16_aopOp (left,ic,FALSE); + pic16_aopOp (right,ic,FALSE); + pic16_aopOp (result,ic,TRUE); + DEBUGpic16_pic16_AopType(__LINE__,left, right, result); + // pic16_DumpOp("(left)",left); + + /* if literal, literal on the right or + if left requires ACC or right is already + in ACC */ + + if ( (AOP_TYPE(left) == AOP_LIT) || (pic16_sameRegs(AOP(right), AOP(result))) ) { + operand *t = right; + right = IC_RIGHT(ic) = left; + left = IC_LEFT(ic) = t; + } + + /* if both left & right are in bit space */ + if (AOP_TYPE(left) == AOP_CRY && + AOP_TYPE(right) == AOP_CRY) { + pic16_genPlusBits (ic); + goto release ; + } + + /* if left in bit space & right literal */ + if (AOP_TYPE(left) == AOP_CRY && + AOP_TYPE(right) == AOP_LIT) { + /* if result in bit space */ + if(AOP_TYPE(result) == AOP_CRY){ + if((unsigned long)floatFromVal(AOP(right)->aopu.aop_lit) != 0L) { + pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),0)); + if (!pic16_sameRegs(AOP(left), AOP(result)) ) + pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0)); + pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),0)); + } + } else { + unsigned long lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit); + size = pic16_getDataSize(result); + while (size--) { + pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset)); + pic16_emitpcode (POC_MOVLW, pic16_popGetLit ((lit >> (8*offset)) & 0xFF)); + pic16_emitpcode (POC_ADDWFC, pic16_popGet(AOP(result), offset++)); + //MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE)); + //pic16_emitcode("addc","a,#00 ;%d",__LINE__); + //pic16_aopPut(AOP(result),"a",offset++); + } + } + goto release ; + } // left == CRY + + /* if I can do an increment instead + of add then GOOD for ME */ + if (pic16_genPlusIncr (ic) == TRUE) + goto release; + + size = pic16_getDataSize(result); + + if(AOP(right)->type == AOP_LIT) { + /* Add a literal to something else */ + //bool know_W=0; + unsigned lit = (unsigned) floatFromVal(AOP(right)->aopu.aop_lit); + //unsigned l1=0; + + //offset = 0; + DEBUGpic16_emitcode(";","adding lit to something. size %d",size); + + genAddLit (ic, lit); + goto release; + + } else if(AOP_TYPE(right) == AOP_CRY) { + + pic16_emitcode(";bitadd","right is bit: %s",pic16_aopGet(AOP(right),0,FALSE,FALSE)); + pic16_emitcode(";bitadd","left is bit: %s",pic16_aopGet(AOP(left),0,FALSE,FALSE)); + pic16_emitcode(";bitadd","result is bit: %s",pic16_aopGet(AOP(result),0,FALSE,FALSE)); + + /* here we are adding a bit to a char or int */ + if(size == 1) { + if (pic16_sameRegs(AOP(left), AOP(result)) ) { + + pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_INCF , pic16_popGet(AOP(result),0)); + + pic16_emitcode("btfsc","(%s >> 3), (%s & 7)", + AOP(right)->aopu.aop_dir, + AOP(right)->aopu.aop_dir); + pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(result),0,FALSE,FALSE)); + } else { // not same + + if(AOP_TYPE(left) == AOP_ACC) { + pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_XORLW , pic16_popGetLit(1)); + + pic16_emitcode("btfsc","(%s >> 3), (%s & 7)", + AOP(right)->aopu.aop_dir, + AOP(right)->aopu.aop_dir); + pic16_emitcode(" xorlw","1"); + } else { + pic16_mov2w(AOP(left),0); + pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_INCFW , pic16_popGet(AOP(left),0)); + + pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(left),0,FALSE,FALSE)); pic16_emitcode("btfsc","(%s >> 3), (%s & 7)", - AOP(IC_RIGHT(ic))->aopu.aop_dir, - AOP(IC_RIGHT(ic))->aopu.aop_dir); - pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE)); + AOP(right)->aopu.aop_dir, + AOP(right)->aopu.aop_dir); + pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(left),0,FALSE,FALSE)); } - if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) { + if(AOP_TYPE(result) != AOP_ACC) { - if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) { + if(AOP_TYPE(result) == AOP_CRY) { pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1)); - pic16_emitpcode(POC_BCF , pic16_popGet(AOP(IC_RESULT(ic)),0)); + pic16_emitpcode(POC_BCF , pic16_popGet(AOP(result),0)); emitSKPZ; - pic16_emitpcode(POC_BSF , pic16_popGet(AOP(IC_RESULT(ic)),0)); + pic16_emitpcode(POC_BSF , pic16_popGet(AOP(result),0)); } else { - pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(IC_RESULT(ic)),0)); - pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); + pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result),0)); + pic16_emitcode("movwf","%s", pic16_aopGet(AOP(result),0,FALSE,FALSE)); } } } @@ -922,39 +1241,39 @@ void pic16_genPlus (iCode *ic) } else { int offset = 1; DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) { + if (pic16_sameRegs(AOP(left), AOP(result)) ) { emitCLRZ; - pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0)); - pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0)); + pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0)); pic16_emitcode("clrz",""); pic16_emitcode("btfsc","(%s >> 3), (%s & 7)", - AOP(IC_RIGHT(ic))->aopu.aop_dir, - AOP(IC_RIGHT(ic))->aopu.aop_dir); - pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); + AOP(right)->aopu.aop_dir, + AOP(right)->aopu.aop_dir); + pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(result),0,FALSE,FALSE)); } else { - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0)); - pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0)); - pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(IC_LEFT(ic)),0)); - //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE)); - emitMOVWF(IC_RIGHT(ic),0); - - pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE)); + emitCLRZ; // needed here as well: INCFW is not always executed, Z is undefined then + pic16_mov2w(AOP(left),0); + pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0)); + pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0)); + //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(right),0,FALSE,FALSE)); + emitMOVWF(right,0); + + pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(left),0,FALSE,FALSE)); pic16_emitcode("btfsc","(%s >> 3), (%s & 7)", - AOP(IC_RIGHT(ic))->aopu.aop_dir, - AOP(IC_RIGHT(ic))->aopu.aop_dir); - pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE)); - pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); + AOP(right)->aopu.aop_dir, + AOP(right)->aopu.aop_dir); + pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(left),0,FALSE,FALSE)); + pic16_emitcode("movwf","%s", pic16_aopGet(AOP(result),0,FALSE,FALSE)); } while(--size){ emitSKPZ; - pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),offset++)); - //pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE)); + pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset++)); + //pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(right),offset++,FALSE,FALSE)); } } @@ -979,11 +1298,20 @@ void pic16_genPlus (iCode *ic) DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); size = min( AOP_SIZE(result), AOP_SIZE(right) ); + size = min( size, AOP_SIZE(left) ); offset = 0; + if(pic16_debug_verbose) { +// fprintf(stderr, "%s:%d result: %d\tleft: %d\tright: %d\n", __FILE__, __LINE__, +// AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right)); +// fprintf(stderr, "%s:%d size of operands: %d\n", __FILE__, __LINE__, size); + } + + + if ((AOP_TYPE(left) == AOP_PCODE) && ( (AOP(left)->aopu.pcop->type == PO_LITERAL) || - (AOP(left)->aopu.pcop->type == PO_DIR) || +// (AOP(left)->aopu.pcop->type == PO_DIR) || // patch 9 (AOP(left)->aopu.pcop->type == PO_IMMEDIATE))) { // add to literal operand @@ -1002,6 +1330,8 @@ void pic16_genPlus (iCode *ic) } pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i)); } + + DEBUGpic16_pic16_AopTypeSign(__LINE__, NULL, right, NULL); // add leftover bytes if (SPEC_USIGN(getSpec(operandType(right)))) { @@ -1016,8 +1346,8 @@ void pic16_genPlus (iCode *ic) // right is signed, oh dear ... for(i=size; i< AOP_SIZE(result); i++) { pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),size-1,FALSE,FALSE),7,0)); - pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result),i)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); + pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),i)); pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i)); pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i)); } @@ -1031,7 +1361,7 @@ void pic16_genPlus (iCode *ic) // add first bytes for(i=0; i AOP_SIZE(IC_RIGHT(ic))) { - int sign = !(SPEC_USIGN(getSpec(operandType(IC_LEFT(ic)))) | - SPEC_USIGN(getSpec(operandType(IC_RIGHT(ic)))) ); - - - /* Need to extend result to higher bytes */ - size = AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_RIGHT(ic)) - 1; - - /* First grab the carry from the lower bytes */ - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - - - if(sign) { - /* Now this is really horrid. Gotta check the sign of the addends and propogate - * to the result */ - - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_LEFT(ic)),offset-1,FALSE,FALSE),7,0)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RIGHT(ic)),offset-1,FALSE,FALSE),7,0)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - - /* if chars or ints or being signed extended to longs: */ - if(size) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE),7,0)); - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff)); - } - } - - offset++; - while(size--) { - - if(sign) - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - else - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - - offset++; - } - } - - - //adjustArithmeticResult(ic); - - release: - pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); + assert( 0 ); + +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); } /*-----------------------------------------------------------------*/ @@ -1144,7 +1435,7 @@ bool pic16_genMinusDec (iCode *ic) unsigned int icount ; unsigned int size = pic16_getDataSize(IC_RESULT(ic)); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; /* will try to generate an increment */ /* if the right side is not a literal we cannot */ @@ -1167,8 +1458,7 @@ bool pic16_genMinusDec (iCode *ic) if(size == 2) { pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),LSB)); - pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(IC_RESULT(ic)),LSB)); - pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),MSB16)); + emitSKPC; pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),MSB16)); pic16_emitcode("decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)); @@ -1176,27 +1466,24 @@ bool pic16_genMinusDec (iCode *ic) pic16_emitcode(" decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)); } else { /* size is 3 or 4 */ - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(IC_RESULT(ic)),LSB)); - emitSKPNC; - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(IC_RESULT(ic)),MSB16)); - emitSKPNC; - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(IC_RESULT(ic)),MSB24)); + pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),LSB)); + pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg)); + pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),MSB16)); + pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),MSB24)); pic16_emitcode("movlw","0xff"); pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE)); - emitSKPNC; + //emitSKPNC; pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE)); - emitSKPNC; + //emitSKPNC; pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE)); if(size > 3) { - emitSKPNC; - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(IC_RESULT(ic)),MSB32)); + pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),MSB32)); pic16_emitcode("skpnc",""); - emitSKPNC; + //emitSKPNC; pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE)); } @@ -1254,12 +1541,12 @@ void pic16_addSign(operand *result, int offset, int sign) if(size == 1) { pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset)); - pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset)); + pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); + pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset)); } else { pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff)); while(size--) pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset+size)); @@ -1277,7 +1564,8 @@ void pic16_addSign(operand *result, int offset, int sign) void pic16_genMinusBits (iCode *ic) { symbol *lbl = newiTempLabel(NULL); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + FENTRY; if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){ pic16_emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir); pic16_emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100)); @@ -1304,7 +1592,7 @@ void pic16_genMinus (iCode *ic) int size, offset = 0, same=0; unsigned long lit = 0L; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; pic16_aopOp (IC_LEFT(ic),ic,FALSE); pic16_aopOp (IC_RIGHT(ic),ic,FALSE); pic16_aopOp (IC_RESULT(ic),ic,TRUE); @@ -1331,8 +1619,8 @@ void pic16_genMinus (iCode *ic) /* if I can do an decrement instead of subtract then GOOD for ME */ - // if (pic16_genMinusDec (ic) == TRUE) - // goto release; +// if (pic16_genMinusDec (ic) == TRUE) +// goto release; size = pic16_getDataSize(IC_RESULT(ic)); same = pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))); @@ -1413,7 +1701,7 @@ void pic16_genMinus (iCode *ic) if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) { if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) { if(lit & 1) { - pic16_emitpcode(POC_MOVLW , pic16_popGet(AOP(IC_RIGHT(ic)),0)); + pic16_emitpcode(POC_MOVLW , pic16_popGetLit(1)); pic16_emitpcode(POC_XORWF , pic16_popGet(AOP(IC_RIGHT(ic)),0)); } }else{ @@ -1429,12 +1717,12 @@ void pic16_genMinus (iCode *ic) pic16_emitpcode(POC_MOVLW , pic16_popGetLit(lit & 0xff)); pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0)); pic16_emitpcode(POC_MOVLW , pic16_popGetLit((lit-1) & 0xff)); - pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(IC_RESULT(ic)),0)); + //pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(IC_RESULT(ic)),0)); } } else { - pic16_emitpcode(POC_MOVFW , pic16_popGet(AOP(IC_LEFT(ic)),0)); + pic16_mov2w(AOP(IC_LEFT(ic)),0); pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0)); pic16_emitpcode(POC_DECFW , pic16_popGet(AOP(IC_LEFT(ic)),0)); } @@ -1469,8 +1757,7 @@ void pic16_genMinus (iCode *ic) if( (size == 1) && ((lit & 0xff) == 0) ) { /* res = 0 - right */ if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) { - pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_RIGHT(ic)),0)); - pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RIGHT(ic)),0)); + pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(IC_RIGHT(ic)),0)); } else { pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_RIGHT(ic)),0)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),0)); @@ -1479,66 +1766,23 @@ void pic16_genMinus (iCode *ic) goto release; } - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_RIGHT(ic)),0)); + pic16_mov2w(AOP(IC_RIGHT(ic)),0); pic16_emitpcode(POC_SUBLW, pic16_popGetLit(lit & 0xff)); pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0)); - offset = 1; + offset = 0; while(--size) { lit >>= 8; - - if(size == 1) { - /* This is the last byte in a multibyte subtraction - * There are a couple of tricks we can do by not worrying about - * propogating the carry */ - if(lit == 0xff) { - /* 0xff - x == ~x */ - if(same) { - pic16_emitpcode(POC_COMF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - emitSKPC; - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - } else { - pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - emitSKPC; - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - } - } else { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset)); - emitSKPC; - pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset)); - pic16_emitpcode(POC_SUBLW, pic16_popGetLit(lit & 0xff)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - } - - goto release; - } - + offset++; if(same) { - - if(lit & 0xff) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); - emitSKPC; - pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit & 0xff)-1)); - pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - } else { - emitSKPNC; - pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - - } + // here we have x = lit - x for sizeof(x)>1 + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); + pic16_emitpcode(POC_SUBFWB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset)); } else { - - if(lit & 0xff) { - pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - } else - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset)); - emitSKPC; - pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(IC_RIGHT(ic)),offset)); - pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); + pic16_emitpcode(POC_SUBFWB_D0, pic16_popGet(AOP(IC_RIGHT(ic)),offset)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); } } @@ -1554,19 +1798,13 @@ void pic16_genMinus (iCode *ic) DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_RIGHT(ic)),0)); pic16_emitpcode(POC_SUBLW, pic16_popGetLit(0)); - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0)); + if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) + pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0)); } else { - if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) { - pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_RIGHT(ic)),0)); - pic16_emitpcode(POC_SUBLW, pic16_popGetLit(0)); - if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) - pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0)); - } else { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); if(AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC) - pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(IC_RIGHT(ic)),0)); + pic16_mov2w(AOP(IC_RIGHT(ic)),0); if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(IC_LEFT(ic)),0)); @@ -1586,7 +1824,6 @@ void pic16_genMinus (iCode *ic) pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0)); } } - } } /* @@ -1597,247 +1834,51 @@ void pic16_genMinus (iCode *ic) } else { pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); - } - */ - offset = 1; - size--; - - while(size--){ - if (!pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - } - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset)); - emitSKPC; - pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(IC_RIGHT(ic)),offset)); - pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - - offset++; - } - - } - - - // adjustArithmeticResult(ic); - - release: - pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); - pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); -} - -/*-----------------------------------------------------------------* - * pic_genUMult8XLit_16 - unsigned multiplication of two 8-bit numbers. - * - * - *-----------------------------------------------------------------*/ -void pic16_genUMult8XLit_16 (operand *left, - operand *right, - operand *result, - pCodeOpReg *result_hi) - -{ - - unsigned int lit; - unsigned int i,have_first_bit; - int same; - pCodeOp *temp; - - if (AOP_TYPE(right) != AOP_LIT){ - fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__); - exit(1); - } - - - if(!result_hi) { - result_hi = PCOR(pic16_popGet(AOP(result),1)); - } - - lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit); - lit &= 0xff; - pic16_emitcode(";","Unrolled 8 X 8 multiplication"); - - same = pic16_sameRegs(AOP(left), AOP(result)); - - if(same) { - switch(lit) { - case 0: - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(left),0)); - return; - case 2: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - return; - case 3: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - return; - case 4: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - return; - case 5: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 2*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 3*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 5*F - return; - case 6: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - return; - case 7: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 2*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 3*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 5*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 7*F - return; - case 8: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 2*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 3*F - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 5*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 8*F - return; - case 9: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - return; - case 10: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 2*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 3*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 5*F - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - return; - case 11: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 2*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 3*F - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 5*F - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 8*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 11*F - return; - case 12: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - return; - case 13: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 2*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 3*F - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 5*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 8*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 13*F - return; - case 14: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 2*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 3*F - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 5*F - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 8*F - pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0)); // W = 11*F - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); // F = 14*F - return; - case 15: - temp = pic16_popGetTempReg(); - if(!temp) { - fprintf(stderr,"ERROR: unable to allocate register. %s:%d\n",__FUNCTION__,__LINE__); - exit(1); - } - pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVWF, temp); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_SWAPFW, temp); - pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(left),0)); - pic16_popReleaseTempReg(temp); - return; - case 16: - pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(left),0)); - return; - case 17: - pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0)); - return; - case 32: - pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xe0)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(left),0)); - return; - case 64: - pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xc0)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(left),0)); - return; - case 128: - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),0)); - return; - - } - } else { - - switch(lit) { - case 0: - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_CLRF, pic16_popCopyReg(result_hi)); - return; - case 2: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_CLRF, pic16_popCopyReg(result_hi)); - pic16_emitpcode(POC_RLCF, pic16_popCopyReg(result_hi)); - return; - } - - } - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_CLRF, pic16_popCopyReg(result_hi)); - - have_first_bit = 0; - for(i=0; i<8; i++) { - - if(lit & 1) { - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi)); - have_first_bit = 1; - } + } + */ + offset = 1; + size--; - if(have_first_bit) { - pic16_emitpcode(POC_RRCF, pic16_popCopyReg(result_hi)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0)); + while(size--){ + if (offset < AOP_SIZE(IC_RIGHT(ic))) + pic16_mov2w(AOP(IC_RIGHT(ic)),offset); + else { + pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg)); + if (!SPEC_USIGN(operandType(IC_RIGHT(ic)))) { + // signed -- sign extend the right operand + pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RIGHT(ic)),AOP_SIZE(IC_RIGHT(ic))-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); + pic16_emitpcode (POC_SETF, pic16_popCopyReg (&pic16_pc_wreg)); + } + } + if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) { + pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset)); + } else { + if (offset < AOP_SIZE(IC_LEFT(ic))) { + pic16_emitpcode(POC_SUBWFB_D0, pic16_popGet(AOP(IC_LEFT(ic)),offset)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); + } else { + // zero extend the left operand + pic16_emitpcode (POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)), offset)); + if (!SPEC_USIGN(operandType(IC_LEFT(ic)))) { + // signed -- sign extend the left operand + pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_LEFT(ic)),AOP_SIZE(IC_LEFT(ic))-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); + pic16_emitpcode (POC_SETF, pic16_popGet(AOP(IC_RESULT(ic)), offset)); // keep CARRY/#BORROW bit intact! + } + pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset)); + } + } + offset++; } - lit >>= 1; } + + // adjustArithmeticResult(ic); + + release: + pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE)); + pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE); } @@ -1852,6 +1893,11 @@ void pic16_genUMult8XLit_8 (operand *left, { unsigned int lit; int same; + int size = AOP_SIZE(result); + int i; + + FENTRY; + DEBUGpic16_pic16_AopType(__LINE__,left,right,result); if (AOP_TYPE(right) != AOP_LIT){ fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__); @@ -1867,133 +1913,187 @@ void pic16_genUMult8XLit_8 (operand *left, if(same) { switch(lit) { case 0: - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0)); + while (size--) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size)); + } // while return; case 2: // its faster to left shift - pic16_emitpcode(POC_RLNCF, pic16_popGet(AOP(left),0)); + for (i=1; i < size; i++) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i)); + } // for + emitCLRC; + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0)); + if (size > 1) + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1)); return; default: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0)); + if(AOP_TYPE(left) != AOP_ACC) + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0)); pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit)); pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0))); + if (size > 1) { + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh), + pic16_popGet(AOP(result), 1))); + for (i=2; i < size; i++) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i)); + } // for + } // if return; } } else { // operands different switch(lit) { case 0: - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0)); + while (size--) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size)); + } // while return; case 2: - pic16_emitpcode(POC_RLNCFW, pic16_popGet(AOP(left), 0)); + for (i=1; i < size; i++) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i)); + } // for + emitCLRC; + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); + if (size > 1) + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1)); return; default: - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0)); + if(AOP_TYPE(left) != AOP_ACC) + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0)); pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit)); pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0))); + + if (size > 1) { + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh), + pic16_popGet(AOP(result), 1))); + for (i=2; i < size; i++) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i)); + } // for + } // if return; } } } -/*-----------------------------------------------------------------* - * genUMult8X8_16 - unsigned multiplication of two 8-bit numbers. - * - * - *-----------------------------------------------------------------*/ -void pic16_genUMult8X8_16 (operand *left, - operand *right, - operand *result, - pCodeOpReg *result_hi) - +/*-----------------------------------------------------------------------* + * pic_genUMult16XLit_16 - unsigned multiplication of two 16-bit numbers * + *-----------------------------------------------------------------------*/ +void pic16_genUMult16XLit_16 (operand *left, + operand *right, + operand *result) { + pCodeOp *pct1, *pct2, *pct3, *pct4; + unsigned int lit; + int same; - int i; - int looped = 1; - - if(!result_hi) { - result_hi = PCOR(pic16_popGet(AOP(result),1)); - } - - if (AOP_TYPE(right) == AOP_LIT) { - pic16_genUMult8XLit_16(left,right,result,result_hi); - return; - } - - if(!looped) { - pic16_emitcode(";","Unrolled 8 X 8 multiplication"); - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_CLRF, pic16_popCopyReg(result_hi)); - emitCLRC; - - for(i=0; i<8; i++) { - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),i,0)); - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi)); - pic16_emitpcode(POC_RRCF, pic16_popCopyReg(result_hi)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0)); - } - - - /* - Here's another version that does the same thing and takes the - same number of instructions. The one above is slightly better - because the entry instructions have a higher probability of - being optimized out. - */ - /* - pic16_emitpcode(POC_CLRF, pic16_popCopyReg(result_hi)); - pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - - for(i=0; i<8; i++) { - emitSKPNC; - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi)); - pic16_emitpcode(POC_RRCF, pic16_popCopyReg(result_hi)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0)); - } - */ - - } else { - symbol *tlbl = newiTempLabel(NULL); - pCodeOp *temp; - - pic16_emitpcomment("; Looped 8 X 8 multiplication"); - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0)); - pic16_emitpcode(POC_CLRF, pic16_popCopyReg(result_hi)); - - pic16_emitpcode(POC_BSF, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),0,FALSE,FALSE),7,0)); - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0)); - - temp = pic16_popGetTempReg(); - pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(PCOR(temp))); - - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0)); - - pic16_emitpLabel(tlbl->key); - pic16_emitpcode(POC_RRCF, pic16_popCopyReg(PCOR(temp))); - emitSKPNC; - pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi)); + FENTRY; + + if (AOP_TYPE(right) != AOP_LIT){ + fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__); + exit(1); + } - pic16_emitpcode(POC_RRCF, pic16_popCopyReg(result_hi)); - pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),0)); + lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit); + lit &= 0xffff; - emitSKPC; - pic16_emitpcode(POC_GOTO, pic16_popGetLabel(tlbl->key)); + same = pic16_sameRegs(AOP(left), AOP(result)); + if(same) { + switch(lit) { + case 0: + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),1)); + return; + case 2: + // its faster to left shift + emitCLRC; + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0)); + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),1)); + return; - pic16_popReleaseTempReg(temp); - } + default: { + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + pct1 = pic16_popGetTempReg(1); + pct2 = pic16_popGetTempReg(1); + pct3 = pic16_popGetTempReg(1); + pct4 = pic16_popGetTempReg(1); + + pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff)); + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1))); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2))); + + /* WREG still holds the low literal */ + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3))); + + pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 )); + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4))); + + /* load result */ + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pct1, pic16_popGet(AOP(result), 0))); + pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct2)); + pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3)); + pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1)); + + pic16_popReleaseTempReg(pct4,1); + pic16_popReleaseTempReg(pct3,1); + pic16_popReleaseTempReg(pct2,1); + pic16_popReleaseTempReg(pct1,1); + }; return; + } + } else { + // operands different + switch(lit) { + case 0: + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0)); + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1)); + return; + case 2: + emitCLRC; + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 1)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1)); + return; + default: { + + pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff)); + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0))); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1))); + + /* WREG still holds the low literal */ + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1)); + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl)); + pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1)); + + pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 )); + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0)); + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl)); + pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1)); + + }; return; + } + } } + /*-----------------------------------------------------------------* * genUMult8X8_8 - unsigned multiplication of two 8-bit numbers. * @@ -2004,12 +2104,14 @@ void pic16_genUMult8X8_8 (operand *left, operand *result) { + FENTRY; + + if (AOP_TYPE(right) == AOP_LIT) { pic16_genUMult8XLit_8(left,right,result); return; } - pic16_emitpcomment("; Looped 8 X 8 multiplication"); /* cases: A = A x B B = A x B A = B x C @@ -2027,7 +2129,7 @@ void pic16_genUMult8X8_8 (operand *left, if(AOP_TYPE(left) != AOP_ACC) { // left is not WREG if(AOP_TYPE(right) != AOP_ACC) { - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0)); + pic16_mov2w(AOP(left), 0); pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); } else { pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0)); @@ -2041,53 +2143,410 @@ void pic16_genUMult8X8_8 (operand *left, if(AOP_TYPE(result) != AOP_ACC) { pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0))); + + + if(AOP_SIZE(result)>1) { + int i; + + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh), + pic16_popGet(AOP(result), 1))); + + for(i=2;i16 routine and - * then throw away the high byte of the result. - * + * pic16_genMult8X8_8 - multiplication of two 8-bit numbers * *-----------------------------------------------------------------*/ void pic16_genMult8X8_8 (operand *left, operand *right, operand *result) { - if (AOP_TYPE(right) == AOP_LIT) + FENTRY; + + if(AOP_TYPE(right) == AOP_LIT) pic16_genUMult8XLit_8(left,right,result); else pic16_genUMult8X8_8(left,right,result); } + + +/*-----------------------------------------------------------------* + * pic16_genMult16X16_16 - multiplication of two 16-bit numbers * + *-----------------------------------------------------------------*/ +void pic16_genMult16X16_16 (operand *left, + operand *right, + operand *result) +{ + FENTRY; + + if (AOP_TYPE(right) == AOP_LIT) + pic16_genUMult16XLit_16(left,right,result); + else + pic16_genUMult16X16_16(left,right,result); +} + + + + +/*-----------------------------------------------------------------------* + * pic_genUMult32XLit_32 - unsigned multiplication of two 32-bit numbers * + *-----------------------------------------------------------------------*/ +void pic16_genUMult32XLit_32 (operand *left, + operand *right, + operand *result) +{ + pCodeOp *pct1, *pct2, *pct3, *pct4; + unsigned int lit; + int same; + + + FENTRY; + + if (AOP_TYPE(right) != AOP_LIT){ + fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__); + exit(1); + } + + lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit); + lit &= 0xffff; + + same = pic16_sameRegs(AOP(left), AOP(result)); + if(same) { + switch(lit) { + case 0: + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0)); + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),1)); + return; + case 2: + // its faster to left shift + emitCLRC; + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0)); + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),1)); + return; + + default: { + DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + + pct1 = pic16_popGetTempReg(1); + pct2 = pic16_popGetTempReg(1); + pct3 = pic16_popGetTempReg(1); + pct4 = pic16_popGetTempReg(1); + + pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff)); + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1))); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2))); + + /* WREG still holds the low literal */ + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3))); + + pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 )); + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4))); + + /* load result */ + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pct1, pic16_popGet(AOP(result), 0))); + pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct2)); + pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3)); + pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1)); + + pic16_popReleaseTempReg( pct4, 1 ); + pic16_popReleaseTempReg( pct3, 1 ); + pic16_popReleaseTempReg( pct2, 1 ); + pic16_popReleaseTempReg( pct1, 1 ); + }; return; + } + } else { + // operands different + switch(lit) { + case 0: + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0)); + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1)); + return; + case 2: + emitCLRC; + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); + pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 1)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1)); + return; + default: { + + pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff)); + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0))); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1))); + + /* WREG still holds the low literal */ + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1)); + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl)); + pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1)); + + pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 )); + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0)); + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl)); + pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1)); + + }; return; + } + } +} + + +/*------------------------------------------------------------------* + * genUMult32X32_32 - unsigned multiplication of two 32-bit numbers * + *------------------------------------------------------------------*/ +void pic16_genUMult32X32_32 (operand *left, + operand *right, + operand *result) + +{ + pCodeOp *pct1, *pct2, *pct3, *pct4; + + FENTRY; + + if (AOP_TYPE(right) == AOP_LIT) { + pic16_genUMult8XLit_8(left,right,result); + return; + } + + /* cases: + A = A x B B = A x B + A = B x C + */ + /* if result == right then exchange left and right */ + if(pic16_sameRegs(AOP(result), AOP(right))) { + operand *tmp; + tmp = left; + left = right; + right = tmp; + } + + + if(pic16_sameRegs(AOP(result), AOP(left))) { + + pct1 = pic16_popGetTempReg(1); + pct2 = pic16_popGetTempReg(1); + pct3 = pic16_popGetTempReg(1); + pct4 = pic16_popGetTempReg(1); + + pic16_mov2w(AOP(left), 0); + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1))); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2))); + + /* WREG still holds the lower left */ + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3))); + + pic16_mov2w(AOP(left), 1); + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4))); + + /* load result */ + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_pCodeOpCopy( pct1 ), pic16_popGet(AOP(result), 0))); + pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy( pct2 )); + pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3)); + pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1)); + + pic16_popReleaseTempReg( pct4, 1 ); + pic16_popReleaseTempReg( pct3, 1 ); + pic16_popReleaseTempReg( pct2, 1 ); + pic16_popReleaseTempReg( pct1, 1 ); + + } else { + + pic16_mov2w(AOP(left), 0); + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0))); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p( + pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1))); + + /* WREG still holds the lower left */ + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1)); + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl)); + pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1)); + + pic16_mov2w(AOP(left), 1); + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); + pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl)); + pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1)); + } +} + + +/*-----------------------------------------------------------------* + * pic16_genMult32X32_32 - multiplication of two 32-bit numbers * + *-----------------------------------------------------------------*/ +void pic16_genMult32X32_32 (operand *left, + operand *right, + operand *result) +{ + FENTRY; + + if (AOP_TYPE(right) == AOP_LIT) + pic16_genUMult32XLit_32(left,right,result); + else + pic16_genUMult32X32_32(left,right,result); +} + + + + + + + #if 0 /*-----------------------------------------------------------------*/ /* constMult - generates code for multiplication by a constant */