X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fpic16%2Fgenarith.c;h=68fdf921a77726cb367b5ed71776a23c92d033ae;hb=b4e2bdce4a68e6e125a3f2cdad9147c72e3b6258;hp=f8d34fbd7b57d4dcce5f9d301d1b9916a0375860;hpb=4e39e662bca4e52121166ee8f3b8dae33eb568d6;p=fw%2Fsdcc diff --git a/src/pic16/genarith.c b/src/pic16/genarith.c index f8d34fbd..68fdf921 100644 --- a/src/pic16/genarith.c +++ b/src/pic16/genarith.c @@ -48,10 +48,6 @@ #include "pcode.h" #include "gen.h" -//#define D_POS(txt) DEBUGpic16_emitcode ("; TECODEV::: " txt, " (%s:%d (%s))", __FILE__, __LINE__, __FUNCTION__) - -#define D_POS(msg) DEBUGpic16_emitcode("; ", msg, "%s:%d (%s)", __FILE__, __LINE__, __FUNCTION__) - #if 1 #define pic16_emitcode DEBUGpic16_emitcode #endif @@ -117,6 +113,7 @@ const char *pic16_pCodeOpType(pCodeOp *pcop) 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"; } } @@ -156,6 +153,7 @@ const char *pic16_pCodeOpSubType(pCodeOp *pcop) 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"; } } @@ -167,10 +165,11 @@ const char *pic16_pCodeOpSubType(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))), @@ -206,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) ) { @@ -280,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))), @@ -420,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; @@ -441,6 +441,7 @@ static void genAddLit2byte (operand *result, int offr, int lit) } } +#endif static void emitMOVWF(operand *reg, int offset) { @@ -456,6 +457,9 @@ static void emitMOVWF(operand *reg, int offset) } + +#if 1 + static void genAddLit (iCode *ic, int lit) { @@ -465,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); @@ -532,7 +536,6 @@ static void genAddLit (iCode *ic, int lit) pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16)); break; default: /* 0x01LL */ - D_POS("FIXED: added default case for adding 0x01??"); pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0)); emitSKPNC; @@ -577,11 +580,9 @@ static void genAddLit (iCode *ic, int lit) genAddLit2byte (result, MSB16, hi); break; case 1: /* 0xHH01 */ - D_POS(">>> IMPROVED"); 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)); - D_POS("<<< IMPROVED"); break; /* case 0xff: * 0xHHff * pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0,FALSE,FALSE)); @@ -593,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)); - D_POS(">>> IMPROVED"); pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16)); - D_POS("<<< IMPROVED"); break; } @@ -610,26 +609,339 @@ static void genAddLit (iCode *ic, int lit) 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: - D_POS(">>> IMPROVED and compacted 0"); - emitSKPNC; + break; + case 1: pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset)); - D_POS("<<< IMPROVED and compacted"); + carry_info=1; break; - case 0xff: + default: pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo)); - D_POS(">>> Changed from SKPZ/SKPC to always SKPC"); - emitSKPC; 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; - default: - D_POS(">>> IMPROVED and compacted - default"); + } + } + 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_ADDWFC, pic16_popGet(AOP(result),offset)); - D_POS("<<< IMPROVED and compacted"); - break; + 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; + 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)); + 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++; + } + } + } +} + +#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 size,sizeL,same; + int i, llit; + + operand *result; + operand *left; + + FENTRY; + + + left = IC_LEFT(ic); + 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 */ + pic16_addSign(result, sizeL, !IS_UNSIGNED(operandType(left))); + + /* 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)); + } + } + +#if 0 + + if(same) { + + /* Handle special cases first */ + if(size == 1) + genAddLit2byte (result, 0, lit); + + else if(size == 2) { + int hi = 0xff & (lit >> 8); + lo = lit & 0xff; + + switch(hi) { + case 0: + + /* 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)); + + 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)); + + + } + break; + + 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; + + 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)); + + } + + break; + + default: + DEBUGpic16_emitcode ("; hi is generic","%d %s %d",hi,__FUNCTION__,__LINE__); + + /* 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 */ @@ -675,7 +987,6 @@ static void genAddLit (iCode *ic, int lit) } } - } */ } @@ -701,9 +1012,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); - D_POS(">>> REMOVED double assignment"); break; case 1: pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0)); @@ -731,7 +1041,7 @@ 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; } @@ -747,45 +1057,41 @@ static void genAddLit (iCode *ic, int lit) pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offset)); - D_POS(">>> FIXED from left to result"); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); - D_POS("<<< FIXED from left to result"); clear_carry = 0; } else { - D_POS(">>> FIXED"); 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)); - D_POS("<<< FIXED"); } } else { - D_POS(">>> IMPROVED"); pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offset)); + pic16_mov2w(AOP(left),offset); pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset)); - D_POS("<<< IMPROVED"); } offset++; } } } +#endif } +#endif + /*-----------------------------------------------------------------*/ /* pic16_genPlus - generates code for addition */ /*-----------------------------------------------------------------*/ void pic16_genPlus (iCode *ic) { - int i, size, offset = 0; - operand *result, *left, *right; - - /* special cases :- */ - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - + int i, size, offset = 0; + operand *result, *left, *right; + FENTRY; + + /* special cases :- */ result = IC_RESULT(ic); left = IC_LEFT(ic); right = IC_RIGHT(ic); @@ -801,8 +1107,8 @@ void pic16_genPlus (iCode *ic) if ( (AOP_TYPE(left) == AOP_LIT) || (pic16_sameRegs(AOP(right), AOP(result))) ) { operand *t = right; - right = left; - left = t; + right = IC_RIGHT(ic) = left; + left = IC_LEFT(ic) = t; } /* if both left & right are in bit space */ @@ -824,11 +1130,15 @@ void pic16_genPlus (iCode *ic) 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--) { - MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE)); - pic16_emitcode("addc","a,#00 ;%d",__LINE__); - pic16_aopPut(AOP(result),"a",offset++); + 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 ; @@ -839,12 +1149,12 @@ void pic16_genPlus (iCode *ic) if (pic16_genPlusIncr (ic) == TRUE) goto release; - size = pic16_getDataSize(IC_RESULT(ic)); + size = pic16_getDataSize(result); - if(AOP(IC_RIGHT(ic))->type == AOP_LIT) { + if(AOP(right)->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 lit = (unsigned) floatFromVal(AOP(right)->aopu.aop_lit); //unsigned l1=0; //offset = 0; @@ -853,55 +1163,55 @@ void pic16_genPlus (iCode *ic) genAddLit (ic, lit); goto release; - } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) { + } else if(AOP_TYPE(right) == AOP_CRY) { - 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)); + 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(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) { + if (pic16_sameRegs(AOP(left), AOP(result)) ) { - 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("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 { // not same - if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) { - pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0)); + 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(IC_RIGHT(ic))->aopu.aop_dir, - AOP(IC_RIGHT(ic))->aopu.aop_dir); + AOP(right)->aopu.aop_dir, + AOP(right)->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)); + 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(IC_LEFT(ic)),0,FALSE,FALSE)); + 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)); } } } @@ -909,39 +1219,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 { emitCLRZ; // needed here as well: INCFW is not always executed, Z is undefined then - 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_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(IC_LEFT(ic)),0,FALSE,FALSE)); + 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)); } } @@ -1014,10 +1324,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)); - D_POS(">>> FIXED sign test from result to right"); pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - D_POS("<<< FIXED sign test from result to right"); - pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result),i)); + 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 +1339,7 @@ void pic16_genPlus (iCode *ic) // add first bytes for(i=0; i>> FIXED added to uninitialized result"); - pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg)); - pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i)); - D_POS ("<<< FIXED"); - } - } - } else { - // right is signed - for(i=size; i< AOP_SIZE(result); i++) { - if(size < AOP_SIZE(left)) { - pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg)); - pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); - pic16_emitpcode(POC_COMFW, pic16_popCopyReg(&pic16_pc_wreg)); - if (pic16_sameRegs(AOP(left), AOP(result))) - { - pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i)); - } else { // not same - pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i)); - } - } else { - pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg)); - pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), i)); - } - } - } + // either left or right is too short + for (i=size; i < AOP_SIZE(result); i++) { + // get right operand into WREG + if (i < AOP_SIZE(right)) { + pic16_mov2w (AOP(right), i); + } else { + // right is too short + pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg)); + if (!SPEC_USIGN(getSpec(operandType(right)))) { + // right operand is signed + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),AOP_SIZE(right)-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); + pic16_emitpcode(POC_SETF, pic16_popCopyReg (&pic16_pc_wreg)); + } + } + + // get left+WREG+CARRY into result + if (i < AOP_SIZE(left)) { + if (pic16_sameRegs (AOP(left), AOP(result))) { + pic16_emitpcode (POC_ADDWFC, pic16_popGet (AOP(result), i)); + } else { + pic16_emitpcode (POC_ADDFWC, pic16_popGet (AOP(left), i)); + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i)); + } + } else { + // left is too short + pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), i)); + if (!SPEC_USIGN(getSpec(operandType(left)))) { + // left operand is signed + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE),7,0, PO_GPR_REGISTER)); + pic16_emitpcode(POC_SETF, pic16_popGet (AOP(result), i)); + } + pic16_emitpcode (POC_ADDWFC, pic16_popGet (AOP(result), i)); + } + } // for i goto release; } } assert( 0 ); - // TODO: anything from here to before "release:" is probably obsolete and should be removed - // when the regression tests are stable - - if (AOP_SIZE(IC_RESULT(ic)) > 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, PO_GPR_REGISTER)); - 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, PO_GPR_REGISTER)); - 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, PO_GPR_REGISTER)); - 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); + +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); } /*-----------------------------------------------------------------*/ @@ -1153,7 +1413,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 */ @@ -1176,8 +1436,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)); @@ -1185,27 +1444,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)); } @@ -1264,7 +1520,7 @@ 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, PO_GPR_REGISTER)); - pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset)); + pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset)); } else { pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0)); @@ -1286,7 +1542,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)); @@ -1301,7 +1558,7 @@ void pic16_genMinusBits (iCode *ic) pic16_emitcode("inc","a"); pic16_emitcode("","%05d_DS_:",(lbl->key+100)); pic16_aopPut(AOP(IC_RESULT(ic)),"a",0); - pic16_addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic))))); + pic16_addSign(IC_RESULT(ic), MSB16, !IS_UNSIGNED(operandType(IC_RESULT(ic)))); } } @@ -1313,7 +1570,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); @@ -1422,7 +1679,6 @@ 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) { - D_POS(">>> FIXED from MOVLW right(=result) to MOVLW left(=literal,left&1==1)"); pic16_emitpcode(POC_MOVLW , pic16_popGetLit(1)); pic16_emitpcode(POC_XORWF , pic16_popGet(AOP(IC_RIGHT(ic)),0)); } @@ -1439,13 +1695,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)); - D_POS(">>> IMPROVED removed following assignment W-->result"); //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)); } @@ -1480,9 +1735,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))) ) { - D_POS(">>> IMPROVED changed comf,incf to negf"); pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(IC_RIGHT(ic)),0)); - D_POS("<<< IMPROVED changed comf,incf to negf"); } else { pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_RIGHT(ic)),0)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),0)); @@ -1491,7 +1744,7 @@ 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)); @@ -1500,7 +1753,6 @@ void pic16_genMinus (iCode *ic) while(--size) { lit >>= 8; offset++; - D_POS(">>> FIXED and compacted"); if(same) { // here we have x = lit - x for sizeof(x)>1 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff)); @@ -1510,7 +1762,6 @@ void pic16_genMinus (iCode *ic) pic16_emitpcode(POC_SUBFWB_D0, pic16_popGet(AOP(IC_RIGHT(ic)),offset)); pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); } - D_POS("<<< FIXED and compacted"); } @@ -1531,7 +1782,7 @@ void pic16_genMinus (iCode *ic) 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)); @@ -1567,16 +1818,32 @@ void pic16_genMinus (iCode *ic) size--; 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_MOVFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset)); - D_POS(">>> IMPROVED by replacing emitSKPC, incfszw by subwfb"); - pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset)); - D_POS("<<< IMPROVED by replacing emitSKPC, incfszw by subwfb"); + pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset)); } else { - D_POS(">>> FIXED for same regs right and result"); - pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_RIGHT(ic)),offset)); - pic16_emitpcode(POC_SUBWFB_D0, pic16_popGet(AOP(IC_LEFT(ic)),offset)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset)); + 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++; } @@ -1594,73 +1861,127 @@ void pic16_genMinus (iCode *ic) /*-----------------------------------------------------------------* - * pic_genUMult8XLit_8 - unsigned multiplication of two 8-bit numbers. + * pic_genMult8XLit_n - multiplication of two 8-bit numbers. * * *-----------------------------------------------------------------*/ -void pic16_genUMult8XLit_8 (operand *left, - operand *right, - operand *result) +void pic16_genMult8XLit_n (operand *left, + operand *right, + operand *result) { - unsigned int lit; + int lit; int same; + int size = AOP_SIZE(result); + int i; + FENTRY; + DEBUGpic16_pic16_AopType(__LINE__,left,right,result); - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - 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__); - exit(1); - } + 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 &= 0xff; - pic16_emitpcomment("Unrolled 8 X 8 multiplication"); - pic16_emitpcomment("FIXME: the function does not support result==WREG"); + lit = (int)floatFromVal(AOP(right)->aopu.aop_lit); + assert( (lit >= -128) && (lit < 256) ); + pic16_emitpcomment("Unrolled 8 X 8 multiplication"); + pic16_emitpcomment("FIXME: the function does not support result==WREG"); + + same = pic16_sameRegs(AOP(left), AOP(result)); + if(same) { + switch(lit & 0x00ff) { + case 0: + while (size--) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size)); + } // while + return; - same = pic16_sameRegs(AOP(left), AOP(result)); - if(same) { - switch(lit) { - case 0: - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0)); - return; - case 2: - // its faster to left shift - emitCLRC; - pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0)); - return; + case 2: + /* sign extend left in result */ + pic16_addSign(result, 1, !IS_UNSIGNED(operandType(left))); + // its faster to left shift + emitCLRC; + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0)); + if (size > 1) + pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1)); + return; - default: - 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))); - return; - } + default: + if(AOP_TYPE(left) != AOP_ACC) + pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0)); + pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit & 0x00ff)); + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( + &pic16_pc_prodl), pic16_popGet(AOP(result), 0))); + /* Adjust result's high bytes below! */ + } + } else { + // operands different + switch(lit & 0x00ff) { + case 0: + while (size--) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),size)); + } // while + return; + + case 2: + if (IS_UNSIGNED(operandType(result))) { + for (i=1; i < size; i++) { + pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i)); + } // for } else { - // operands different - switch(lit) { - case 0: - pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0)); - return; - case 2: - emitCLRC; - pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0)); - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0)); - return; - default: - 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))); - return; - } + /* sign extend left to result */ + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7)); + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff)); + for (i=1; i < size; i++) { + pic16_emitpcode(POC_MOVWF, 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: + 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))); + /* Adjust result's high bytes below! */ + } + } + + if (size > 1) { + /* We need to fix PRODH for + * (a) literals < 0 and + * (b) signed register operands < 0. + */ + //printf( "%s: lit %d, left unsigned: %d\n", __FUNCTION__, lit, SPEC_USIGN(getSpec(operandType(left)))); + if (lit < 0) { + /* literal negative (i.e. in [-128..-1]), high byte == -1 */ + pic16_mov2w(AOP(left), 0); + pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh)); + } + + if (!SPEC_USIGN(getSpec(operandType(left)))) { + /* register operand signed, determine signedness of high byte */ + pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0x00ff)); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7)); + pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh)); + } + + pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg( + &pic16_pc_prodh), pic16_popGet(AOP(result), 1))); + + /* Need to sign-extend here. */ + pic16_addSign(result, 2, !IS_UNSIGNED(operandType(result))); + } // if } +#if 0 /*-----------------------------------------------------------------------* * pic_genUMult16XLit_16 - unsigned multiplication of two 16-bit numbers * *-----------------------------------------------------------------------*/ @@ -1673,8 +1994,8 @@ void pic16_genUMult16XLit_16 (operand *left, int same; - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); - + FENTRY; + if (AOP_TYPE(right) != AOP_LIT){ fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__); exit(1); @@ -1773,73 +2094,101 @@ void pic16_genUMult16XLit_16 (operand *left, } } } +#endif /*-----------------------------------------------------------------* - * genUMult8X8_8 - unsigned multiplication of two 8-bit numbers. + * genMult8X8_n - multiplication of two 8-bit numbers. * * *-----------------------------------------------------------------*/ -void pic16_genUMult8X8_8 (operand *left, - operand *right, - operand *result) +void pic16_genMult8X8_n (operand *left, operand *right, operand *result) { - DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); + FENTRY; - if (AOP_TYPE(right) == AOP_LIT) { - pic16_genUMult8XLit_8(left,right,result); - return; - } + if (AOP_TYPE(right) == AOP_LIT) { + pic16_genMult8XLit_n(left,right,result); + return; + } - /* cases: - A = A x B B = A x B - A = B x C - W = A x B - W = W x B W = B x W - */ - /* if result == right then exchange left and right */ - if(pic16_sameRegs(AOP(result), AOP(right))) { - operand *tmp; - tmp = left; - left = right; - right = tmp; - } - - 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_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); - } else { - pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0)); - } - } else { - // left is WREG, right cannot be WREG (or can?!) - pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(right), 0)); - } - - /* result is in PRODL:PRODH */ - if(AOP_TYPE(result) != AOP_ACC) { - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl), - pic16_popGet(AOP(result), 0))); + /* cases: + A = A x B B = A x B + A = B x C + W = A x B + W = W x B W = B x W + */ + /* if result == right then exchange left and right */ + if(pic16_sameRegs(AOP(result), AOP(right))) { + operand *tmp; + tmp = left; + left = right; + right = tmp; + } + if(AOP_TYPE(left) != AOP_ACC) { + // left is not WREG + if(AOP_TYPE(right) != AOP_ACC) { + pic16_mov2w(AOP(left), 0); + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0)); + } else { + pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0)); + } + } else { + // left is WREG, right cannot be WREG (or can?!) + pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(right), 0)); + } - if(AOP_SIZE(result)>1) { - int i; + /* result is in PRODL:PRODH */ + 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) { + + /* If s8 x s8 --> s16 multiplication was called for, fixup high byte. + * (left=a1a0, right=b1b0, X1: high byte, X0: low byte) + * + * a1a0 * b1b0 + * -------------- + * a1b0 a0b0 + * a1b1 a0b1 + * --------------- + * a0b0 a1= 0, b1= 0 (both unsigned) + * -b0 a0b0 a1=-1, b1= 0 (a signed and < 0, b unsigned or >= 0) + * -a0 a0b0 a1= 0, b1=-1 (b signed and < 0, a unsigned or >= 0) + * -(a0+b0) a0b0 a1=-1, b1=-1 (a and b signed and < 0) + * + * Currently, PRODH:PRODL holds a0b0 as 16 bit value; we need to + * subtract a0 and/or b0 from PRODH. */ + if (!IS_UNSIGNED(operandType(right))) { + /* right operand (b1) signed and < 0, then subtract left op (a0) */ + pic16_mov2w( AOP(left), 0 ); + pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7)); + pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh)); + } - pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh), - pic16_popGet(AOP(result), 1))); - - for(i=2;i