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";
(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
- pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
- AOP(IC_RESULT(ic))->aopu.aop_dir,
- AOP(IC_RESULT(ic))->aopu.aop_dir);
if(icount)
pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
//pic16_emitcode("xorlw","1");
emitSKPZ;
pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
- pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
- AOP(IC_RESULT(ic))->aopu.aop_dir,
- AOP(IC_RESULT(ic))->aopu.aop_dir);
return TRUE;
}
pic16_emitpcode(POC_XORLW, pic16_popGetLit(1));
pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
pic16_emitpcode(POC_XORLW, pic16_popGetLit(1));
-
- pic16_emitcode("clrw","");
- 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");
- pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
- AOP(IC_LEFT(ic))->aopu.aop_dir,
- AOP(IC_LEFT(ic))->aopu.aop_dir);
- pic16_emitcode("xorlw","1");
break;
case AOP_REG:
pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
-
- pic16_emitcode("movlw","(1 << (%s & 7))",
- AOP(IC_RESULT(ic))->aopu.aop_dir,
- AOP(IC_RESULT(ic))->aopu.aop_dir);
- pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
- AOP(IC_RESULT(ic))->aopu.aop_dir,
- AOP(IC_RESULT(ic))->aopu.aop_dir);
- pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
- AOP(IC_RIGHT(ic))->aopu.aop_dir,
- AOP(IC_RIGHT(ic))->aopu.aop_dir);
- pic16_emitcode("xorwf","(%s >>3),f",
- AOP(IC_RESULT(ic))->aopu.aop_dir);
- pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
- AOP(IC_LEFT(ic))->aopu.aop_dir,
- AOP(IC_LEFT(ic))->aopu.aop_dir);
- pic16_emitcode("xorwf","(%s>>3),f",
- AOP(IC_RESULT(ic))->aopu.aop_dir);
break;
}
{
int size,same;
- int lo;
+ int lo, offset;
operand *result;
operand *left;
- FENTRY;
-
+ FENTRY;
left = IC_LEFT(ic);
result = IC_RESULT(ic);
same = pic16_sameRegs(AOP(left), AOP(result));
size = pic16_getDataSize(result);
+ if ((AOP_PCODE == AOP_TYPE(left))
+ && (PO_IMMEDIATE == AOP(left)->aopu.pcop->type))
+ {
+ /* see #1888004 for an example case for this */
+ for (offset = 0; offset < size; offset++) {
+ pic16_emitpcode(POC_MOVLW, pic16_newpCodeOpImmd(AOP(left)->aopu.pcop->name,
+ offset, PCOI(AOP(left)->aopu.pcop)->index + lit, 0));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
+ } // for
+ return;
+ } // if
+
if(same) {
/* Handle special cases first */
}
}
+// } else if (pic16_isLitAop(AOP(left))) {
+// // adding two literals
+// assert ( !"adding two literals is not yet supported" );
} 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));
+ pic16_mov2w(AOP(left),0);
+ pic16_emitpcode(POC_ADDLW, pic16_popGetLit(lit & 0xff));
} else {
pic16_mov2w(AOP(left),0);
/* We don't know the state of the carry bit at this point */
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(right)->aopu.aop_dir,
- AOP(right)->aopu.aop_dir);
- pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(left),0,FALSE,FALSE));
}
if(AOP_TYPE(result) != AOP_ACC) {
pic16_emitpcode(POC_BSF , pic16_popGet(AOP(result),0));
} else {
pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result),0));
- pic16_emitcode("movwf","%s", pic16_aopGet(AOP(result),0,FALSE,FALSE));
}
}
}
emitCLRZ;
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(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_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(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(result),offset++));
- //pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(right),offset++,FALSE,FALSE));
}
}
} else {
// add regs
+ if (pic16_sameRegs(AOP(left), AOP(result))
+ && (AOP_SIZE(left) < AOP_SIZE(result)))
+ {
+ // extend left operand, sign-bit still intact
+ pic16_addSign (result, AOP_SIZE(left), !SPEC_USIGN(getSpec(operandType(left))));
+ }
+
// add first bytes
for(i=0; i<size; i++) {
if (AOP_TYPE(right) != AOP_ACC)
// get right operand into WREG
if (i < AOP_SIZE(right)) {
pic16_mov2w (AOP(right), i);
- } else {
- // right is too short
+ } else {
+ // right is too short, not overwritten with result
pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
if (!SPEC_USIGN(getSpec(operandType(right)))) {
// right operand is signed
+ // Make sure that right's sign is not yet overwritten
+ assert (!pic16_sameRegs (AOP(right), AOP(result)));
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));
- }
+ if (pic16_sameRegs (AOP(left), AOP(result))) {
+ // left might have been extended in result above
+ pic16_emitpcode (POC_ADDWFC, pic16_popGet (AOP(result), i));
+ } else if (i < AOP_SIZE(left)) {
+ pic16_emitpcode (POC_ADDFWC, pic16_popGet (AOP(left), i));
+ pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
} else {
- // left is too short
+ // left is too short, not overwritten with result
pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), i));
if (!SPEC_USIGN(getSpec(operandType(left)))) {
// left operand is signed
}
}
-/*-----------------------------------------------------------------*/
-/* pic16_genMinusBits - generates code for subtraction of two bits */
-/*-----------------------------------------------------------------*/
-void pic16_genMinusBits (iCode *ic)
-{
- symbol *lbl = newiTempLabel(NULL);
-
- 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));
- pic16_emitcode("cpl","c");
- pic16_emitcode("","%05d_DS_:",(lbl->key+100));
- pic16_outBitC(IC_RESULT(ic));
- }
- else{
- pic16_emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
- pic16_emitcode("subb","a,acc");
- pic16_emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
- 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, !IS_UNSIGNED(operandType(IC_RESULT(ic))));
- }
-}
-
/*-----------------------------------------------------------------*/
/* pic16_genMinus - generates code for subtraction */
/*-----------------------------------------------------------------*/
lit = - (long)lit;
genAddLit ( ic, lit);
-
-#if 0
- /* add the first byte: */
- pic16_emitcode("movlw","0x%x", lit & 0xff);
- pic16_emitcode("addwf","%s,f", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
- pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(IC_LEFT(ic)),0));
-
-
- offset = 1;
- size--;
-
- while(size-- > 0) {
-
- lit >>= 8;
-
- if(lit & 0xff) {
-
- if((lit & 0xff) == 0xff) {
- pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
- emitSKPC;
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(IC_LEFT(ic)),offset));
- } else {
- pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
- emitSKPNC;
- pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(IC_LEFT(ic)),offset));
- }
-
- } else {
- /* do the rlf known zero trick here */
- pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
- emitSKPNC;
- pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(IC_LEFT(ic)),offset));
- }
- offset++;
- }
-#endif
} else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
// bit subtraction
pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
pic16_emitpcode(POC_DECF , pic16_popGet(AOP(IC_RESULT(ic)),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));
} else {
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));
- }else if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
- (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
+ }else if( (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
lit = ulFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit);
}
}
- } else if(// (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
- (AOP(IC_LEFT(ic))->type == AOP_LIT) &&
+ } else if((AOP(IC_LEFT(ic))->type == AOP_LIT) &&
(AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC)) {
lit = ulFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit);
pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
+ if ((AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RESULT(ic)))
+ && pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
+ // extend left in result
+ pic16_addSign (IC_RESULT(ic), AOP_SIZE(IC_LEFT(ic)), !SPEC_USIGN(getSpec(operandType(IC_LEFT(ic)))));
+ }
+
+ if ((AOP_SIZE(IC_RIGHT(ic)) < AOP_SIZE(IC_RESULT(ic)))
+ && pic16_sameRegs (AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) {
+ // extend right in result---fails if left resides in result as well...
+ assert ((IC_LEFT(ic) == IC_RIGHT(ic)) || !pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))));
+ pic16_addSign (IC_RESULT(ic), AOP_SIZE(IC_RIGHT(ic)), !SPEC_USIGN(getSpec(operandType(IC_RIGHT(ic)))));
+ }
+
if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
pic16_emitpcode(POC_SUBFW, pic16_popGet(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));
else {
- if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
- (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
+ if( (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
pic16_emitpcode(POC_SUBLW, pic16_popGet(AOP(IC_LEFT(ic)),0));
} else {
pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
offset = 1;
size--;
- while(size--){
- if (offset < AOP_SIZE(IC_RIGHT(ic)))
+ while (size--) {
+ if (pic16_sameRegs (AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) {
+ pic16_mov2w (AOP(IC_RESULT(ic)), offset);
+ } else if (offset < AOP_SIZE(IC_RIGHT(ic)))
pic16_mov2w(AOP(IC_RIGHT(ic)),offset);
else {
+ // right operand is too short, not overwritten with result
pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
if (!SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
// signed -- sign extend the right operand
}
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 {
- 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));
+ // left operand is too short, not overwritten with result
+ 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++;
}
-
}
-
// adjustArithmeticResult(ic);
release: