+/*-----------------------------------------------------------------*/
+/* 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(ulFromVal (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 = ulFromVal (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) ulFromVal (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));
+ } 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));
+ } else {
+ pic16_mov2w(AOP(left),0);
+ pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0));
+ pic16_emitpcode(POC_INCFW , pic16_popGet(AOP(left),0));
+ }
+
+ if(AOP_TYPE(result) != AOP_ACC) {
+
+ if(AOP_TYPE(result) == AOP_CRY) {
+ pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
+ pic16_emitpcode(POC_BCF , pic16_popGet(AOP(result),0));
+ emitSKPZ;
+ pic16_emitpcode(POC_BSF , pic16_popGet(AOP(result),0));
+ } else {
+ pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(result),0));
+ }
+ }
+ }
+
+ } else {
+ int offset = 1;
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+ if (pic16_sameRegs(AOP(left), AOP(result)) ) {
+ emitCLRZ;
+ pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
+ pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
+ } 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));
+ emitMOVWF(right,0);
+ }
+
+ while(--size){
+ emitSKPZ;
+ pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset++));
+ }
+
+ }
+
+ } else {
+ // add bytes
+
+ // Note: the following is an example of WISC code, eg.
+ // it's supposed to run on a Weird Instruction Set Computer :o)
+
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+
+ if ( AOP_TYPE(left) == AOP_ACC) {
+ DEBUGpic16_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
+ pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right),0));
+ if ( AOP_TYPE(result) != AOP_ACC)
+ pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
+ goto release; // we're done, since WREG is 1 byte
+ }
+
+
+ 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) || // patch 9
+ (AOP(left)->aopu.pcop->type == PO_IMMEDIATE)))
+ {
+ // add to literal operand
+
+ // add first bytes
+ for(i=0; i<size; i++) {
+ if (AOP_TYPE(right) == AOP_ACC) {
+ pic16_emitpcode(POC_ADDLW, pic16_popGet(AOP(left),i));
+ } else {
+ pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
+ if(i) { // add with carry
+ pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(right),i));
+ } else { // add without
+ pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right),i));
+ }
+ }
+ 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)))) {
+ // right is unsigned
+ for(i=size; i< AOP_SIZE(result); i++) {
+ pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
+ pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
+ pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
+ }
+
+ } else {
+ // 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(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));
+ }
+
+ }
+ goto release;
+
+ } 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))));
+ }