Imported Upstream version 2.9.0
[debian/cc1111] / src / pic / genarith.c
1 /*-------------------------------------------------------------------------
2   genarith.c - source file for code generation - arithmetic 
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18   
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22   
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26   
27   Notes:
28   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
29       Made everything static
30 -------------------------------------------------------------------------*/
31
32 #if defined(_MSC_VER) && (_MSC_VER < 1300)
33 #define __FUNCTION__    __FILE__
34 #endif
35
36 #include "common.h"
37 #include "newalloc.h"
38 //#include "SDCCglobl.h"
39 //#include "SDCCpeeph.h"
40
41 #include "gen.h"
42 #include "pcode.h"
43 #include "ralloc.h"
44
45
46 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
47
48 const char *AopType(short type)
49 {
50         switch(type) {
51         case AOP_LIT:
52                 return "AOP_LIT";
53                 break;
54         case AOP_REG:
55                 return "AOP_REG";
56                 break;
57         case AOP_DIR:
58                 return "AOP_DIR";
59                 break;
60         case AOP_STK:
61                 return "AOP_STK";
62                 break;
63         case AOP_IMMD:
64                 return "AOP_IMMD";
65                 break;
66         case AOP_STR:
67                 return "AOP_STR";
68                 break;
69         case AOP_CRY:
70                 return "AOP_CRY";
71                 break;
72         case AOP_PCODE:
73                 return "AOP_PCODE";
74                 break;
75         }
76         
77         return "BAD TYPE";
78 }
79
80 const char *pCodeOpType(pCodeOp *pcop)
81 {
82         
83         if(pcop) {
84                 
85                 switch(pcop->type) {
86                         
87                 case  PO_NONE:
88                         return "PO_NONE";
89                 case  PO_W:
90                         return  "PO_W";
91                 case  PO_STATUS:
92                         return  "PO_STATUS";
93                 case  PO_FSR:
94                         return  "PO_FSR";
95                 case  PO_INDF:
96                         return  "PO_INDF";
97                 case  PO_INTCON:
98                         return  "PO_INTCON";
99                 case  PO_GPR_REGISTER:
100                         return  "PO_GPR_REGISTER";
101                 case  PO_GPR_POINTER:
102                         return  "PO_GPR_POINTER";
103                 case  PO_GPR_BIT:
104                         return  "PO_GPR_BIT";
105                 case  PO_GPR_TEMP:
106                         return  "PO_GPR_TEMP";
107                 case  PO_SFR_REGISTER:
108                         return  "PO_SFR_REGISTER";
109                 case  PO_PCL:
110                         return  "PO_PCL";
111                 case  PO_PCLATH:
112                         return  "PO_PCLATH";
113                 case  PO_LITERAL:
114                         return  "PO_LITERAL";
115                 case  PO_IMMEDIATE:
116                         return  "PO_IMMEDIATE";
117                 case  PO_DIR:
118                         return  "PO_DIR";
119                 case  PO_CRY:
120                         return  "PO_CRY";
121                 case  PO_BIT:
122                         return  "PO_BIT";
123                 case  PO_STR:
124                         return  "PO_STR";
125                 case  PO_LABEL:
126                         return  "PO_LABEL";
127                 case  PO_WILD:
128                         return  "PO_WILD";
129                 }
130         }
131         
132         return "BAD PO_TYPE";
133 }
134
135 /*-----------------------------------------------------------------*/
136 /* genPlusIncr :- does addition with increment if possible         */
137 /*-----------------------------------------------------------------*/
138 static bool genPlusIncr (iCode *ic)
139 {
140         unsigned int icount ;
141         unsigned int size = pic14_getDataSize(IC_RESULT(ic));
142         FENTRY;
143         
144         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
145         DEBUGpic14_emitcode ("; ","result %s, left %s, right %s",
146                 AopType(AOP_TYPE(IC_RESULT(ic))),
147                 AopType(AOP_TYPE(IC_LEFT(ic))),
148                 AopType(AOP_TYPE(IC_RIGHT(ic))));
149         
150         /* will try to generate an increment */
151         /* if the right side is not a literal 
152         we cannot */
153         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
154                 return FALSE ;
155         
156         DEBUGpic14_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
157         /* if the literal value of the right hand side
158         is greater than 1 then it is faster to add */
159         if ((icount = (unsigned int) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
160                 return FALSE ;
161         
162         /* if increment 16 bits in register */
163         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
164                 (icount == 1)) {
165                 
166                 int offset = MSB16;
167                 
168                 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB));
169                 //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
170                 
171                 while(--size) {
172                         emitSKPNZ;
173                         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++));
174                         //pic14_emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
175                 }
176                 
177                 return TRUE;
178         }
179         
180         DEBUGpic14_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
181         /* if left is in accumulator  - probably a bit operation*/
182         if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a")  &&
183                 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
184                 
185                 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
186                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
187                         AOP(IC_RESULT(ic))->aopu.aop_dir,
188                         AOP(IC_RESULT(ic))->aopu.aop_dir);
189                 if(icount)
190                         emitpcode(POC_XORLW,popGetLit(1));
191                 //pic14_emitcode("xorlw","1");
192                 else
193                         emitpcode(POC_ANDLW,popGetLit(1));
194                 //pic14_emitcode("andlw","1");
195                 
196                 emitSKPZ;
197                 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
198                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
199                         AOP(IC_RESULT(ic))->aopu.aop_dir,
200                         AOP(IC_RESULT(ic))->aopu.aop_dir);
201                 
202                 return TRUE;
203         }
204         
205         
206         
207         /* if the sizes are greater than 1 then we cannot */
208         if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
209                 AOP_SIZE(IC_LEFT(ic)) > 1   )
210                 return FALSE ;
211         
212         /* If we are incrementing the same register by two: */
213         
214         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
215                 
216                 while (icount--) 
217                         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
218                 //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
219                 
220                 return TRUE ;
221         }
222         
223         DEBUGpic14_emitcode ("; ","couldn't increment ");
224         
225         return FALSE ;
226 }
227
228 /*-----------------------------------------------------------------*/
229 /* genAddlit - generates code for addition                         */
230 /*-----------------------------------------------------------------*/
231 static void genAddLit2byte (operand *result, int offr, int lit)
232 {
233         FENTRY;
234         
235         switch(lit & 0xff) {
236         case 0:
237                 break;
238         case 1:
239                 emitpcode(POC_INCF, popGet(AOP(result),offr));
240                 break;
241         case 0xff:
242                 emitpcode(POC_DECF, popGet(AOP(result),offr));
243                 break;
244         default:
245                 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
246                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
247         }
248         
249 }
250
251 static void emitMOVWF(operand *reg, int offset)
252 {
253         FENTRY;
254         if(!reg)
255                 return;
256         
257         emitpcode(POC_MOVWF, popGet(AOP(reg),offset));
258         
259 }
260
261 static void genAddLit (iCode *ic, int lit)
262 {
263         
264         int size,same;
265         int lo;
266         
267         operand *result;
268         operand *left;
269         
270         FENTRY;
271         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
272         
273         
274         left = IC_LEFT(ic);
275         result = IC_RESULT(ic);
276         same = pic14_sameRegs(AOP(left), AOP(result));
277         size = pic14_getDataSize(result);
278         if (size > pic14_getDataSize(left))
279                 size = pic14_getDataSize(left);
280         
281         if(same) {
282                 
283                 /* Handle special cases first */
284                 if(size == 1) 
285                         genAddLit2byte (result, 0, lit);
286                 
287                 else if(size == 2) {
288                         int hi = 0xff & (lit >> 8);
289                         lo = lit & 0xff;
290                         
291                         switch(hi) {
292                         case 0: 
293                                 
294                                 /* lit = 0x00LL */
295                                 DEBUGpic14_emitcode ("; hi = 0","%s  %d",__FUNCTION__,__LINE__);
296                                 switch(lo) {
297                                 case 0:
298                                         break;
299                                 case 1:
300                                         emitpcode(POC_INCF, popGet(AOP(result),0));
301                                         emitSKPNZ;
302                                         emitpcode(POC_INCF, popGet(AOP(result),MSB16));
303                                         break;
304                                 case 0xff:
305                                         emitpcode(POC_DECF, popGet(AOP(result),0));
306                                         emitpcode(POC_INCFSZW, popGet(AOP(result),0));
307                                         emitpcode(POC_INCF, popGet(AOP(result),MSB16));
308                                         
309                                         break;
310                                 default:
311                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
312                                         emitpcode(POC_ADDWF,popGet(AOP(result),0));
313                                         emitSKPNC;
314                                         emitpcode(POC_INCF, popGet(AOP(result),MSB16));
315                                         
316                                         
317                                 }
318                                 break;
319                                 
320                                 case 1:
321                                         /* lit = 0x01LL */
322                                         DEBUGpic14_emitcode ("; hi = 1","%s  %d",__FUNCTION__,__LINE__);
323                                         switch(lo) {
324                                         case 0:  /* 0x0100 */
325                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
326                                                 break;
327                                         case 1:  /* 0x0101  */
328                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
329                                                 emitpcode(POC_INCF, popGet(AOP(result),0));
330                                                 emitSKPNZ;
331                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
332                                                 break;
333                                         case 0xff: /* 0x01ff */
334                                                 emitpcode(POC_DECF, popGet(AOP(result),0));
335                                                 emitpcode(POC_INCFSZW, popGet(AOP(result),0));
336                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
337                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
338                                         }   
339                                         break;
340                                         
341                                         case 0xff:
342                                                 DEBUGpic14_emitcode ("; hi = ff","%s  %d",__FUNCTION__,__LINE__);
343                                                 /* lit = 0xffLL */
344                                                 switch(lo) {
345                                                 case 0:  /* 0xff00 */
346                                                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
347                                                         break;
348                                                 case 1:  /*0xff01 */
349                                                         emitpcode(POC_INCFSZ, popGet(AOP(result),0));
350                                                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
351                                                         break;
352                                                 default:
353                                                         emitpcode(POC_MOVLW,popGetLit(lo));
354                                                         emitpcode(POC_ADDWF,popGet(AOP(result),0));
355                                                         emitSKPC;
356                                                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
357                                                         
358                                                 }
359                                                 
360                                                 break;
361                                                 
362                                                 default:
363                                                         DEBUGpic14_emitcode ("; hi is generic","%d   %s  %d",hi,__FUNCTION__,__LINE__);
364                                                         
365                                                         /* lit = 0xHHLL */
366                                                         switch(lo) {
367                                                         case 0:  /* 0xHH00 */
368                                                                 genAddLit2byte (result, MSB16, hi);
369                                                                 break;
370                                                         case 1:  /* 0xHH01 */
371                                                                 emitpcode(POC_MOVLW,popGetLit((hi+1)&0xff));
372                                                                 emitpcode(POC_INCFSZ, popGet(AOP(result),0));
373                                                                 emitpcode(POC_MOVLW,popGetLit(hi));
374                                                                 emitpcode(POC_ADDWF,popGet(AOP(result),MSB16));
375                                                                 break;
376                                                         default:  /* 0xHHLL */
377                                                                 emitpcode(POC_MOVLW,popGetLit(lo));
378                                                                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
379                                                                 emitpcode(POC_MOVLW,popGetLit(hi));
380                                                                 emitSKPNC;
381                                                                 emitpcode(POC_MOVLW,popGetLit((hi+1) & 0xff));
382                                                                 emitpcode(POC_ADDWF,popGet(AOP(result),MSB16));
383                                                                 break;
384                                                         }
385                                                         
386                         }
387                 } else {
388                         int carry_info = 0;
389                         int offset = 0;
390                         /* size > 2 */
391                         DEBUGpic14_emitcode (";  add lit to long","%s  %d",__FUNCTION__,__LINE__);
392                         
393                         while(size--) {
394                                 lo = BYTEofLONG(lit,0);
395                                 
396                                 if(carry_info) {
397                                         switch(lo) {
398                                         case 0:
399                                                 switch(carry_info) {
400                                                 case 1:
401                                                         emitSKPNZ;
402                                                         emitpcode(POC_INCF, popGet(AOP(result),offset));
403                                                         break;
404                                                 case 2:
405                                                         emitpcode(POC_RLFW, popGet(AOP(result),offset));
406                                                         emitpcode(POC_ANDLW,popGetLit(1));
407                                                         emitpcode(POC_ADDWF, popGet(AOP(result),offset));
408                                                         break;
409                                                 default: /* carry_info = 3  */
410                                                         emitSKPNC;
411                                                         emitpcode(POC_INCF, popGet(AOP(result),offset));
412                                                         carry_info = 1;
413                                                         break;
414                                                 }
415                                                 break;
416                                                 case 0xff:
417                                                         emitpcode(POC_MOVLW,popGetLit(lo));
418                                                         if(carry_info==1) 
419                                                                 emitSKPZ;
420                                                         else
421                                                                 emitSKPC;
422                                                         emitpcode(POC_ADDWF, popGet(AOP(result),offset));
423                                                         break;
424                                                 default:
425                                                         emitpcode(POC_MOVLW,popGetLit(lo));
426                                                         if(carry_info==1) 
427                                                                 emitSKPNZ;
428                                                         else
429                                                                 emitSKPNC;
430                                                         emitpcode(POC_MOVLW,popGetLit(lo+1));
431                                                         emitpcode(POC_ADDWF, popGet(AOP(result),offset));
432                                                         carry_info=2;
433                                                         break;
434                                         }
435                                 }else {
436                                         /* no carry info from previous step */
437                                         /* this means this is the first time to add */
438                                         switch(lo) {
439                                         case 0:
440                                                 break;
441                                         case 1:
442                                                 emitpcode(POC_INCF, popGet(AOP(result),offset));
443                                                 carry_info=1;
444                                                 break;
445                                         default:
446                                                 emitpcode(POC_MOVLW,popGetLit(lo));
447                                                 emitpcode(POC_ADDWF, popGet(AOP(result),offset));
448                                                 if(lit <0x100) 
449                                                         carry_info = 3;  /* Were adding only one byte and propogating the carry */
450                                                 else
451                                                         carry_info = 2;
452                                                 break;
453                                         }
454                                 }
455                                 offset++;
456                                 lit >>= 8;
457                         }
458                 }
459         } else {
460                 int offset = 1;
461                 DEBUGpic14_emitcode (";  left and result aren't same","%s  %d",__FUNCTION__,__LINE__);
462                 
463                 if(size == 1) {
464                         
465                         /* left addend is in a register */
466                         switch(lit & 0xff) {
467                         case 0:
468                                 emitpcode(POC_MOVFW, popGet(AOP(left),0));
469                                 emitMOVWF(result, 0);
470                                 emitMOVWF(result,0);
471                                 break;
472                         case 1:
473                                 emitpcode(POC_INCFW, popGet(AOP(left),0));
474                                 emitMOVWF(result,0);
475                                 break;
476                         case 0xff:
477                                 emitpcode(POC_DECFW, popGet(AOP(left),0));
478                                 emitMOVWF(result,0);
479                                 break;
480                         default:
481                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
482                                 emitpcode(POC_ADDFW, popGet(AOP(left),0));
483                                 emitMOVWF(result,0);
484                         }
485                         
486                 } else {
487                         int clear_carry=0;
488                         
489                         /* left is not the accumulator */
490                         if(lit & 0xff) {
491                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
492                                 emitpcode(POC_ADDFW, popGet(AOP(left),0));
493                         } else {
494                                 emitpcode(POC_MOVFW, popGet(AOP(left),0));
495                                 /* We don't know the state of the carry bit at this point */
496                                 clear_carry = 1;
497                         }
498                         emitMOVWF(result,0);
499                         while(--size) {
500                                 
501                                 lit >>= 8;
502                                 if(lit & 0xff) {
503                                         if(clear_carry) {
504                                         /* The ls byte of the lit must've been zero - that 
505                                                 means we don't have to deal with carry */
506                                                 
507                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
508                                                 emitpcode(POC_ADDFW,  popGet(AOP(left),offset));
509                                                 emitpcode(POC_MOVWF, popGet(AOP(left),offset));
510                                                 
511                                                 clear_carry = 0;
512                                                 
513                                         } else {
514                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
515                                                 emitMOVWF(result,offset);
516                                                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
517                                                 emitSKPNC;
518                                                 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
519                                                 emitpcode(POC_ADDWF,  popGet(AOP(result),offset));
520                                         }
521                                         
522                                 } else {
523                                         emitpcode(POC_CLRF,  popGet(AOP(result),offset));
524                                         emitpcode(POC_RLF,   popGet(AOP(result),offset));
525                                         emitpcode(POC_MOVFW, popGet(AOP(left),offset));
526                                         emitpcode(POC_ADDWF, popGet(AOP(result),offset));
527                                 }
528                                 offset++;
529                         }
530                 }
531         }
532
533         size = pic14_getDataSize(result);
534         if (size > pic14_getDataSize(left))
535                 size = pic14_getDataSize(left);
536         addSign(result, size, 0);
537 }
538
539 /*-----------------------------------------------------------------*/
540 /* genPlus - generates code for addition                           */
541 /*-----------------------------------------------------------------*/
542 void genPlus (iCode *ic)
543 {
544         int size, offset = 0;
545         
546         /* special cases :- */
547         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
548         FENTRY;
549         
550         aopOp (IC_LEFT(ic),ic,FALSE);
551         aopOp (IC_RIGHT(ic),ic,FALSE);
552         aopOp (IC_RESULT(ic),ic,TRUE);
553         
554         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),IC_RIGHT(ic),IC_RESULT(ic));
555         
556         /* if literal, literal on the right or
557         if left requires ACC or right is already
558         in ACC */
559         
560         if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
561                 operand *t = IC_RIGHT(ic);
562                 IC_RIGHT(ic) = IC_LEFT(ic);
563                 IC_LEFT(ic) = t;
564         }
565         
566         /* if left in bit space & right literal */
567         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
568                 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
569                 /* if result in bit space */
570                 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
571                         if(ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
572                                 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0));
573                                 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
574                                         emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0));
575                                 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0));
576                         }
577                 } else {
578                         size = pic14_getDataSize(IC_RESULT(ic));
579                         while (size--) {
580                                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
581                                 pic14_emitcode("addc","a,#00  ;%d",__LINE__);
582                                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
583                         }
584                 }
585                 goto release ;
586         }
587         
588         /* if I can do an increment instead
589         of add then GOOD for ME */
590         if (genPlusIncr (ic) == TRUE)
591                 goto release;   
592         
593         size = pic14_getDataSize(IC_RESULT(ic));
594         
595         if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
596                 /* Add a literal to something else */
597                 unsigned lit = (unsigned) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
598                 DEBUGpic14_emitcode(";","adding lit to something. size %d",size);
599                 
600                 genAddLit (ic,  lit);
601                 goto release;
602                 
603         } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
604                 
605                 pic14_emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
606                 pic14_emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
607                 pic14_emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
608                 
609                 /* here we are adding a bit to a char or int */
610                 if(size == 1) {
611                         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
612                                 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
613                                 emitpcode(POC_INCF ,  popGet(AOP(IC_RESULT(ic)),0));
614                         } else {
615                                 
616                                 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0));
617                                 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
618                                 emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0));
619                                 
620                                 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
621                                         emitpcode(POC_ANDLW , popGetLit(1));
622                                         emitpcode(POC_BCF ,   popGet(AOP(IC_RESULT(ic)),0));
623                                         emitSKPZ;
624                                         emitpcode(POC_BSF ,   popGet(AOP(IC_RESULT(ic)),0));
625                                 } else {
626                                         emitpcode(POC_MOVWF ,   popGet(AOP(IC_RESULT(ic)),0));
627                                 }
628                         }
629                         
630                 } else {
631                         int offset = 1;
632                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
633                         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
634                                 emitCLRZ;
635                                 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0));
636                                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
637                         } else {
638                                 
639                                 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0));
640                                 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0));
641                                 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0));
642                                 emitMOVWF(IC_RIGHT(ic),0);
643                         }
644                         
645                         while(--size){
646                                 emitSKPZ;
647                                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),offset++));
648                         }
649                         
650                 }
651                 
652         } else {
653                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
654                 
655                 /* Add the first bytes */
656                 
657                 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
658                         emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0));
659                         emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
660                 } else {
661                         
662                         emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0));
663
664                         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
665                                 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0));
666                         else {
667                                 PIC_OPCODE poc = POC_ADDFW;
668                                 
669                                 if (op_isLitLike (IC_LEFT (ic)))
670                                         poc = POC_ADDLW;
671                                 emitpcode(poc, popGetAddr(AOP(IC_LEFT(ic)),0,0));
672                                 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
673                         }
674                 }
675                 
676                 size = min( AOP_SIZE(IC_RESULT(ic)), AOP_SIZE(IC_RIGHT(ic))) - 1;
677                 offset = 1;
678                 
679                 
680                 if(size){
681                         if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) {
682                                 if (op_isLitLike (IC_LEFT(ic)))
683                                 {
684                                         while(size--){
685                                                 emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset));
686                                                 emitSKPNC;
687                                                 emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset));
688                                                 emitpcode(POC_ADDLW,   popGetAddr(AOP(IC_LEFT(ic)),offset,0));
689                                                 emitpcode(POC_MOVWF,   popGet(AOP(IC_RESULT(ic)),offset));
690                                                 offset++;
691                                         }
692                                 } else {
693                                         while(size--){
694                                                 emitpcode(POC_MOVFW,   popGet(AOP(IC_LEFT(ic)),offset));
695                                                 emitSKPNC;
696                                                 emitpcode(POC_INCFSZW, popGet(AOP(IC_LEFT(ic)),offset));
697                                                 emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset));
698                                                 offset++;
699                                         }
700                                 }
701                         } else {
702                                 PIC_OPCODE poc = POC_MOVFW;
703                                 if (op_isLitLike (IC_LEFT(ic)))
704                                         poc = POC_MOVLW;
705                                 while(size--){
706                                         if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
707                                                 emitpcode(poc, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
708                                                 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
709                                         }
710                                         emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset));
711                                         emitSKPNC;
712                                         emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset));
713                                         emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset));
714                                         offset++;
715                                 }
716                         }
717                 }
718         }
719         
720         if (AOP_SIZE(IC_RESULT(ic)) > AOP_SIZE(IC_RIGHT(ic))) {
721                 int sign =  !(SPEC_USIGN(getSpec(operandType(IC_LEFT(ic)))) |
722                         SPEC_USIGN(getSpec(operandType(IC_RIGHT(ic)))) );
723                 
724                 
725                 /* Need to extend result to higher bytes */
726                 size = AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_RIGHT(ic)) - 1;
727                 
728                 /* First grab the carry from the lower bytes */
729                 if (AOP_SIZE(IC_LEFT(ic)) > AOP_SIZE(IC_RIGHT(ic))) { 
730                         int leftsize = AOP_SIZE(IC_LEFT(ic)) - AOP_SIZE(IC_RIGHT(ic));
731                         PIC_OPCODE poc = POC_MOVFW;
732                         if (op_isLitLike (IC_LEFT(ic)))
733                                 poc = POC_MOVLW;
734                         while(leftsize-- > 0) {
735                                 emitpcode(poc, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
736                                 emitSKPNC;
737                                 emitpcode(POC_ADDLW, popGetLit(0x01));
738                                 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
739                                 //emitSKPNC;
740                                 //emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset)); /* INCF does not update Carry! */
741                                 offset++;
742                                 if (size)
743                                         size--;
744                                 else
745                                         break;
746                         }
747                 } else {
748                         emitpcode(POC_CLRF, popGet(AOP(IC_RESULT(ic)),offset));
749                         emitpcode(POC_RLF,  popGet(AOP(IC_RESULT(ic)),offset));
750                 }
751                 
752                 
753                 if(sign && offset > 0 && offset < AOP_SIZE(IC_RESULT(ic))) {
754                 /* Now this is really horrid. Gotta check the sign of the addends and propogate
755                         * to the result */
756                         
757                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(IC_LEFT(ic)),offset-1,FALSE,FALSE),7,0));
758                         emitpcode(POC_DECF,  popGet(AOP(IC_RESULT(ic)),offset));
759                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(IC_RIGHT(ic)),offset-1,FALSE,FALSE),7,0));
760                         emitpcode(POC_DECF,  popGet(AOP(IC_RESULT(ic)),offset));
761                         
762                         /* if chars or ints or being signed extended to longs: */
763                         if(size) {
764                                 emitpcode(POC_MOVLW, popGetLit(0));
765                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE),7,0));
766                                 emitpcode(POC_MOVLW, popGetLit(0xff));
767                         }
768                 }
769                 
770                 offset++;
771                 while(size--) {
772                         
773                         if(sign)
774                                 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
775                         else
776                                 emitpcode(POC_CLRF,  popGet(AOP(IC_RESULT(ic)),offset));
777                         
778                         offset++;
779                 }
780         }
781         
782         
783         //adjustArithmeticResult(ic);
784         
785 release:
786         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
787         freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
788         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
789 }
790
791 /*-----------------------------------------------------------------*/
792 /* addSign - propogate sign bit to higher bytes                    */
793 /*-----------------------------------------------------------------*/
794 void addSign(operand *result, int offset, int sign)
795 {
796         int size = (pic14_getDataSize(result) - offset);
797         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
798         FENTRY;
799         
800         if(size > 0){
801                 if(sign && offset) {
802                         
803                         if(size == 1) {
804                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
805                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
806                                 emitpcode(POC_DECF, popGet(AOP(result),offset));
807                         } else {
808                                 
809                                 emitpcode(POC_MOVLW, popGetLit(0));
810                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
811                                 emitpcode(POC_MOVLW, popGetLit(0xff));
812                                 while(size--)
813                                         emitpcode(POC_MOVWF, popGet(AOP(result),offset+size));
814                         }
815                 } else
816                         while(size--)
817                                 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
818         }
819 }
820
821 /*-----------------------------------------------------------------*/
822 /* genMinus - generates code for subtraction                       */
823 /*-----------------------------------------------------------------*/
824 void genMinus (iCode *ic)
825 {
826         int size, offset = 0, same=0;
827         unsigned long lit = 0L;
828         int isLit;
829         symbol *lbl_comm, *lbl_next;
830         asmop *left, *right, *result;
831
832         FENTRY;
833         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
834         aopOp (IC_LEFT(ic),ic,FALSE);
835         aopOp (IC_RIGHT(ic),ic,FALSE);
836         aopOp (IC_RESULT(ic),ic,TRUE);
837         
838         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY  &&
839                 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
840                 operand *t = IC_RIGHT(ic);
841                 IC_RIGHT(ic) = IC_LEFT(ic);
842                 IC_LEFT(ic) = t;
843         }
844         
845         DEBUGpic14_emitcode ("; ","result %s, left %s, right %s",
846                 AopType(AOP_TYPE(IC_RESULT(ic))),
847                 AopType(AOP_TYPE(IC_LEFT(ic))),
848                 AopType(AOP_TYPE(IC_RIGHT(ic))));
849         
850         left = AOP(IC_LEFT(ic));
851         right = AOP(IC_RIGHT(ic));
852         result = AOP(IC_RESULT(ic));
853         
854         size = pic14_getDataSize(IC_RESULT(ic));
855         same = pic14_sameRegs(right, result);
856
857         if((AOP_TYPE(IC_LEFT(ic)) != AOP_LIT)
858             && (pic14_getDataSize(IC_LEFT(ic)) < size))
859         {
860                 fprintf(stderr, "%s:%d(%s):WARNING: left operand too short for result\n",
861                         ic->filename, ic->lineno, __FUNCTION__);
862         } // if
863         if((AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
864             && (pic14_getDataSize(IC_RIGHT(ic)) < size))
865         {
866                 fprintf(stderr, "%s:%d(%s):WARNING: right operand too short for result\n",
867                         ic->filename, ic->lineno, __FUNCTION__ );
868         } // if
869
870         if(AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
871                 /* Add a literal to something else */
872                 
873                 lit = ulFromVal(right->aopu.aop_lit);
874                 lit = -(long)lit;
875                 
876                 genAddLit(ic, lit);
877                 
878         } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
879                 // bit subtraction
880                 
881                 pic14_emitcode(";bitsub","right is bit: %s",aopGet(right,0,FALSE,FALSE));
882                 pic14_emitcode(";bitsub","left is bit: %s",aopGet(left,0,FALSE,FALSE));
883                 pic14_emitcode(";bitsub","result is bit: %s",aopGet(result,0,FALSE,FALSE));
884                 
885                 /* here we are subtracting a bit from a char or int */
886                 if(size == 1) {
887                         if(pic14_sameRegs(left, result)) {
888                                 
889                                 emitpcode(POC_BTFSC, popGet(right, 0));
890                                 emitpcode(POC_DECF , popGet(result, 0));
891                                 
892                         } else {
893                                 
894                                 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
895                                         (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
896                                         /*
897                                          * result = literal - bit
898                                          *
899                                          * XXX: probably fails for AOP_IMMDs!
900                                          */
901                                         
902                                         lit = ulFromVal (left->aopu.aop_lit);
903                                         
904                                         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
905                                                 if(pic14_sameRegs(right, result)) {
906                                                         if(lit & 1) {
907                                                                 emitpcode(POC_MOVLW, popGet(right, 0));
908                                                                 emitpcode(POC_XORWF, popGet(result, 0));
909                                                         }
910                                                 } else {
911                                                         emitpcode(POC_BCF, popGet(result, 0));
912                                                         if(lit & 1) 
913                                                                 emitpcode(POC_BTFSS, popGet(right, 0));
914                                                         else
915                                                                 emitpcode(POC_BTFSC, popGet(right, 0));
916                                                         emitpcode(POC_BSF, popGet(result, 0));
917                                                 }
918                                                 goto release;
919                                         } else {
920                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
921                                                 emitpcode(POC_BTFSC, popGet(right, 0));
922                                                 emitpcode(POC_MOVLW, popGetLit((lit-1) & 0xff));
923                                                 emitpcode(POC_MOVWF, popGet(result, 0));
924                                         }
925                                         
926                                 } else {
927                                         // result = register - bit
928                                         // XXX: Fails for lit-like left operands
929                                         emitpcode(POC_MOVFW, popGet(left, 0));
930                                         emitpcode(POC_BTFSC, popGet(right, 0));
931                                         emitpcode(POC_DECFW, popGet(left, 0));
932                                         emitpcode(POC_MOVWF, popGet(result, 0));
933                                 }
934                         }
935                 } else {
936                     fprintf(stderr, "WARNING: subtracting bit from multi-byte operands is incomplete.\n");
937                     //exit(EXIT_FAILURE);
938                 } // if
939         } else {
940                 /*
941                  * RIGHT is not a literal and not a bit operand,
942                  * LEFT is unknown (register, literal, bit, ...)
943                  */
944                 lit = 0;
945                 isLit = 0;
946
947                 if(AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
948                         lit = ulFromVal (left->aopu.aop_lit);
949                         isLit = 1;
950                         DEBUGpic14_emitcode ("; left is lit","line %d result %s, left %s, right %s",__LINE__,
951                                 AopType(AOP_TYPE(IC_RESULT(ic))),
952                                 AopType(AOP_TYPE(IC_LEFT(ic))),
953                                 AopType(AOP_TYPE(IC_RIGHT(ic))));
954                 } // if
955
956
957                 /*
958                  * First byte, no carry-in.
959                  * Any optimizations that are longer than 2 instructions are
960                  * useless.
961                  */
962                 if(same && isLit && ((lit & 0xff) == 0xff)) {
963                         // right === res = 0xFF - right = ~right
964                         emitpcode(POC_COMF, popGet(right, 0));
965                         if(size > 1) {
966                                 // setup CARRY/#BORROW
967                                 emitSETC;
968                         } // if
969                 } else if((size == 1) && isLit && ((lit & 0xff) == 0xff)) {
970                         // res = 0xFF - right = ~right
971                         emitpcode(POC_COMFW, popGet(right, 0));
972                         emitpcode(POC_MOVWF, popGet(result, 0));
973                         // CARRY/#BORROW is not setup correctly
974                 } else if((size == 1) && same && isLit && ((lit & 0xff) == 0)) {
975                         // right === res = 0 - right = ~right + 1
976                         emitpcode(POC_COMF, popGet(right, 0));
977                         emitpcode(POC_INCF, popGet(right, 0));
978                         // CARRY/#BORROW is not setup correctly
979                 } else {
980                         // general case, should always work
981                         mov2w(right, 0);
982                         if (pic14_sameRegs(left, result)) {
983                                 // result === left = left - right (in place)
984                                 emitpcode(POC_SUBWF, popGet(result, 0));
985                         } else {
986                                 // works always: result = left - right
987                                 emitpcode(op_isLitLike(IC_LEFT(ic))
988                                         ? POC_SUBLW : POC_SUBFW,
989                                         popGetAddr(left, 0, 0));
990                                 emitpcode(POC_MOVWF, popGet(result, 0));
991                         } // if
992                 } // if
993                 
994                 /*
995                  * Now for the remaining bytes with carry-in (and carry-out).
996                  */
997                 offset = 0;
998                 while(--size) {
999                         lit >>= 8;
1000                         offset++;
1001
1002                         /*
1003                          * The following code generation templates are ordered
1004                          * according to increasing length; the first template
1005                          * that matches will thus be the shortest and produce
1006                          * the best code possible with thees templates.
1007                          */
1008
1009                         if(pic14_sameRegs(left, right)) {
1010                             /*
1011                              * This case should not occur; however, the
1012                              * template works if LEFT, RIGHT, and RESULT are
1013                              * register operands and LEFT and RIGHT are the
1014                              * same register(s) and at least as long as the
1015                              * result.
1016                              *
1017                              *   CLRF   result
1018                              *
1019                              * 1 cycle
1020                              */
1021                             emitpcode(POC_CLRF, popGet(result, offset));
1022                         } else if(pic14_sameRegs(left, result)) {
1023                             /*
1024                              * This template works if LEFT, RIGHT, and
1025                              * RESULT are register operands and LEFT and
1026                              * RESULT are the same register(s).
1027                              *
1028                              *   MOVF   right, W    ; W := right
1029                              *   BTFSS  STATUS, C
1030                              *   INCFSZ right, W    ; W := right + BORROW
1031                              *   SUBWF  result, F   ; res === left := left - (right + BORROW)
1032                              *
1033                              * The SUBWF *must* be skipped if we have a
1034                              * BORROW bit and right == 0xFF in order to
1035                              * keep the BORROW bit intact!
1036                              *
1037                              * 4 cycles
1038                              */
1039                             mov2w(right, offset);
1040                             emitSKPC;
1041                             emitpcode(POC_INCFSZW, popGet(right, offset));
1042                             emitpcode(POC_SUBWF, popGet(result, offset));
1043                         } else if((size == 1) && isLit && ((lit & 0xff) == 0xff)) {
1044                             /*
1045                              * This template works for the last byte (MSB) of
1046                              * the subtraction and ignores correct propagation
1047                              * of the outgoing BORROW bit. RIGHT and RESULT
1048                              * must be register operands, LEFT must be the
1049                              * literal 0xFF.
1050                              *
1051                              * (The case LEFT === RESULT is optimized above.)
1052                              *
1053                              * 0xFF - right - BORROW = ~right - BORROW
1054                              *
1055                              *   COMF   right, W    ; W := 0xff - right
1056                              *   BTFSS  STATUS, C
1057                              *   ADDLW  0xFF        ; W := 0xff - right - BORROW
1058                              *   MOVWF  result
1059                              *
1060                              * 4 cycles
1061                              */
1062                             emitpcode(POC_COMFW, popGet(right, offset));
1063                             emitSKPC;
1064                             emitpcode(POC_ADDLW, popGetLit(0xff));
1065                             emitpcode(POC_MOVWF, popGet(result, offset));
1066                         } else if(size == 1) {
1067                             /*
1068                              * This template works for the last byte (MSB) of
1069                              * the subtraction and ignores correct propagation
1070                              * of the outgoing BORROW bit. RIGHT and RESULT
1071                              * must be register operands, LEFT can be a
1072                              * register or a literal operand.
1073                              *
1074                              * (The case LEFT === RESULT is optimized above.)
1075                              *
1076                              *   MOVF   right, W    ; W := right
1077                              *   BTFSS  STATUS, C
1078                              *   INCF   right, W    ; W := right + BORROW
1079                              *   SUBxW  left, W     ; W := left - right - BORROW
1080                              *   MOVWF  result
1081                              *
1082                              * 5 cycles
1083                              */
1084                             mov2w(right, offset);
1085                             emitSKPC;
1086                             emitpcode(POC_INCFW, popGet(right, offset));
1087                             emitpcode(op_isLitLike(IC_LEFT(ic))
1088                                     ? POC_SUBLW : POC_SUBFW,
1089                                     popGetAddr(left, offset, 0));
1090                             emitpcode(POC_MOVWF, popGet(result, offset));
1091                         } else if(IS_ITEMP(IC_RESULT(ic))
1092                                 && !pic14_sameRegs(right, result)) {
1093                             /*
1094                              * This code template works if RIGHT and RESULT
1095                              * are different register operands and RESULT
1096                              * is not volatile/an SFR (written twice).
1097                              *
1098                              * #########################################
1099                              * Since we cannot determine that for sure,
1100                              * we approximate via IS_ITEMP() for now.
1101                              * #########################################
1102                              *
1103                              *   MOVxW  left, W     ; copy left to result
1104                              *   MOVWF  result
1105                              *   MOVF   right, W    ; W := right
1106                              *   BTFSS  STATUS, C
1107                              *   INCFSZ right, W    ; W := right + BORROW
1108                              *   SUBWF  result, F   ; res === left := left - (right + BORROW)
1109                              *
1110                              * 6 cycles, but fails for SFR RESULT operands
1111                              */
1112                             mov2w(left, offset);
1113                             emitpcode(POC_MOVWF, popGet(result, offset));
1114                             mov2w(right, offset);
1115                             emitSKPC;
1116                             emitpcode(POC_INCFSZW, popGet(right, offset));
1117                             emitpcode(POC_SUBWF, popGet(result, offset));
1118                         } else if(!optimize.codeSize && isLit && ((lit & 0xff) != 0)) {
1119                             /*
1120                              * This template works if RIGHT and RESULT are
1121                              * register operands and LEFT is a literal
1122                              * operand != 0.
1123                              *
1124                              *   MOVxW  right, W
1125                              *   BTFSC  STATUS, C
1126                              *   GOTO   next
1127                              *   SUBLW  left-1
1128                              *   GOTO   common
1129                              * next:
1130                              *   SUBLW  left
1131                              * common:
1132                              *   MOVWF  result
1133                              *
1134                              * 6 cycles, 7 iff BORROW
1135                              * (9 instructions)
1136                              */
1137                             lbl_comm = newiTempLabel(NULL);
1138                             lbl_next = newiTempLabel(NULL);
1139
1140                             mov2w(right, offset);
1141                             emitSKPNC;
1142                             emitpcode(POC_GOTO, popGetLabel(lbl_next->key));
1143                             emitpcode(POC_SUBLW, popGetLit((lit - 1) & 0xff));
1144                             emitpcode(POC_GOTO, popGetLabel(lbl_comm->key));
1145                             emitpLabel(lbl_next->key);
1146                             emitpcode(POC_SUBLW, popGetLit(lit & 0xff));
1147                             emitpLabel(lbl_comm->key);
1148                             emitpcode(POC_MOVWF, popGet(result, offset));
1149                         } else {
1150                             /*
1151                              * This code template works if RIGHT and RESULT
1152                              * are register operands.
1153                              *
1154                              *   MOVF   right, W    ; W := right
1155                              *   BTFSS  STATUS, C
1156                              *   INCFSZ right, W    ; W := right + BORROW
1157                              *   GOTO   common
1158                              *   MOVxW  left        ; if we subtract 0x100 = 0xFF + 1, ...
1159                              *   GOTO   next        ; res := left, but keep BORROW intact
1160                              * common:
1161                              *   SUBxW  left, W     ; W := left - (right + BORROW)
1162                              * next:
1163                              *   MOVW   result      ; res := left - (right + BORROW)
1164                              *
1165                              * 7 cycles, 8 iff BORROW and (right == 0xFF)
1166                              * (8 instructions)
1167                              *
1168                              *
1169                              *
1170                              * Alternative approach using -x = ~x + 1 ==> ~x = -x - 1 = -(x + 1)
1171                              *
1172                              *   COMFW  right, W    ; W := -right - (assumed BORROW)
1173                              *   BTFSC  STATUS, C   ; SKIP if we have a BORROW
1174                              *   ADDLW  1           ; W := -right (no BORROW)
1175                              *   BTFSC  STATUS, C   ; (***)
1176                              *   MOVLW  left        ; (***)
1177                              *   BTFSS  STATUS, C   ; (***)
1178                              *   ADDFW  left, W     ; W := left - right - BORROW (if any)
1179                              *   MOVWF  result      ; result := left - right - BORROW (if any)
1180                              *
1181                              * 8 cycles
1182                              *
1183                              * Case A: C=0 (BORROW)
1184                              * r=0x00, W=0xFF, W=left+0xFF, C iff left>0x00
1185                              * r=0x01, W=0xFE, W=left+0xFE, C iff left>0x01
1186                              * r=0xFE, W=0x01, W=left+0x01, C iff left>0xFE
1187                              * r=0xFF, W=0x00, W=left+0x00, C iff left>0xFF
1188                              *
1189                              * Case B: C=1 (no BORROW)
1190                              * r=0x00, W=0xFF, W=0x00/C=1, W=left+0x00, C iff left>=0x100 (***)
1191                              * r=0x01, W=0xFE, W=0xFF/C=0, W=left+0xFF, C iff left>=0x01
1192                              * r=0xFE, W=0x01, W=0x02/C=0, W=left+0x02, C iff left>=0xFE
1193                              * r=0xFF, W=0x00, W=0x01/C=0, W=left+0x01, C iff left>=0xFF
1194                              */
1195                             lbl_comm = newiTempLabel(NULL);
1196                             lbl_next = newiTempLabel(NULL);
1197
1198                             mov2w(right, offset);
1199                             emitSKPC;
1200                             emitpcode(POC_INCFSZW, popGet(right, offset));
1201                             emitpcode(POC_GOTO, popGetLabel(lbl_comm->key));
1202                             mov2w(left, offset);
1203                             emitpcode(POC_GOTO, popGetLabel(lbl_next->key));
1204                             emitpLabel(lbl_comm->key);
1205                             emitpcode(op_isLitLike(IC_LEFT(ic))
1206                                     ? POC_SUBLW : POC_SUBFW,
1207                                     popGetAddr(left, offset, 0));
1208                             emitpLabel(lbl_next->key);
1209                             emitpcode(POC_MOVWF, popGet(result, offset));
1210                         } // if
1211                 } // while
1212         } // if
1213
1214         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1215             fprintf(stderr, "WARNING: AOP_CRY (bit-) results are probably broken. Please report this with source code as a bug.\n");
1216             mov2w(result, 0); // load Z flag
1217             emitpcode(POC_BCF, popGet(result, 0));
1218             emitSKPZ;
1219             emitpcode(POC_BSF, popGet(result, 0));
1220         } // if
1221         
1222         //    adjustArithmeticResult(ic);
1223         
1224 release:
1225         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1226         freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1227         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1228 }
1229