* src/z80/gen.c (_vemit2): suppress compiler warning
[fw/sdcc] / 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 #if 0
81 static void DebugAop(asmop *aop)
82 {
83         if(!aop)
84                 return;
85         printf("%s\n",AopType(aop->type));
86         printf(" current offset: %d\n",aop->coff);
87         printf("           size: %d\n",aop->size);
88         
89         switch(aop->type) {
90         case AOP_LIT:
91                 printf("          name: %s\n",aop->aopu.aop_lit->name);
92                 break;
93         case AOP_REG:
94                 printf("          name: %s\n",aop->aopu.aop_reg[0]->name);
95                 break;
96         case AOP_CRY:
97         case AOP_DIR:
98                 printf("          name: %s\n",aop->aopu.aop_dir);
99                 break;
100         case AOP_STK:
101                 printf("   Stack offset: %d\n",aop->aopu.aop_stk);
102                 break;
103         case AOP_IMMD:
104                 printf("     immediate: %s\n",aop->aopu.aop_immd);
105                 break;
106         case AOP_STR:
107                 printf("    aop_str[0]: %s\n",aop->aopu.aop_str[0]);
108                 break;
109         case AOP_PCODE:
110                 //printpCode(stdout,aop->aopu.pcop);
111                 break;
112         }
113 }
114 #endif
115
116 const char *pCodeOpType(  pCodeOp *pcop)
117 {
118         
119         if(pcop) {
120                 
121                 switch(pcop->type) {
122                         
123                 case  PO_NONE:
124                         return "PO_NONE";
125                 case  PO_W:
126                         return  "PO_W";
127                 case  PO_STATUS:
128                         return  "PO_STATUS";
129                 case  PO_FSR:
130                         return  "PO_FSR";
131                 case  PO_INDF:
132                         return  "PO_INDF";
133                 case  PO_INTCON:
134                         return  "PO_INTCON";
135                 case  PO_GPR_REGISTER:
136                         return  "PO_GPR_REGISTER";
137                 case  PO_GPR_POINTER:
138                         return  "PO_GPR_POINTER";
139                 case  PO_GPR_BIT:
140                         return  "PO_GPR_BIT";
141                 case  PO_GPR_TEMP:
142                         return  "PO_GPR_TEMP";
143                 case  PO_SFR_REGISTER:
144                         return  "PO_SFR_REGISTER";
145                 case  PO_PCL:
146                         return  "PO_PCL";
147                 case  PO_PCLATH:
148                         return  "PO_PCLATH";
149                 case  PO_LITERAL:
150                         return  "PO_LITERAL";
151                 case  PO_IMMEDIATE:
152                         return  "PO_IMMEDIATE";
153                 case  PO_DIR:
154                         return  "PO_DIR";
155                 case  PO_CRY:
156                         return  "PO_CRY";
157                 case  PO_BIT:
158                         return  "PO_BIT";
159                 case  PO_STR:
160                         return  "PO_STR";
161                 case  PO_LABEL:
162                         return  "PO_LABEL";
163                 case  PO_WILD:
164                         return  "PO_WILD";
165                 }
166         }
167         
168         return "BAD PO_TYPE";
169 }
170
171 /*-----------------------------------------------------------------*/
172 /* genPlusIncr :- does addition with increment if possible         */
173 /*-----------------------------------------------------------------*/
174 static bool genPlusIncr (iCode *ic)
175 {
176         unsigned int icount ;
177         unsigned int size = pic14_getDataSize(IC_RESULT(ic));
178         FENTRY;
179         
180         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
181         DEBUGpic14_emitcode ("; ","result %s, left %s, right %s",
182                 AopType(AOP_TYPE(IC_RESULT(ic))),
183                 AopType(AOP_TYPE(IC_LEFT(ic))),
184                 AopType(AOP_TYPE(IC_RIGHT(ic))));
185         
186         /* will try to generate an increment */
187         /* if the right side is not a literal 
188         we cannot */
189         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
190                 return FALSE ;
191         
192         DEBUGpic14_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
193         /* if the literal value of the right hand side
194         is greater than 1 then it is faster to add */
195         if ((icount = (unsigned int) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
196                 return FALSE ;
197         
198         /* if increment 16 bits in register */
199         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
200                 (icount == 1)) {
201                 
202                 int offset = MSB16;
203                 
204                 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB));
205                 //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
206                 
207                 while(--size) {
208                         emitSKPNZ;
209                         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++));
210                         //pic14_emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
211                 }
212                 
213                 return TRUE;
214         }
215         
216         DEBUGpic14_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
217         /* if left is in accumulator  - probably a bit operation*/
218         if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a")  &&
219                 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
220                 
221                 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
222                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
223                         AOP(IC_RESULT(ic))->aopu.aop_dir,
224                         AOP(IC_RESULT(ic))->aopu.aop_dir);
225                 if(icount)
226                         emitpcode(POC_XORLW,popGetLit(1));
227                 //pic14_emitcode("xorlw","1");
228                 else
229                         emitpcode(POC_ANDLW,popGetLit(1));
230                 //pic14_emitcode("andlw","1");
231                 
232                 emitSKPZ;
233                 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
234                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
235                         AOP(IC_RESULT(ic))->aopu.aop_dir,
236                         AOP(IC_RESULT(ic))->aopu.aop_dir);
237                 
238                 return TRUE;
239         }
240         
241         
242         
243         /* if the sizes are greater than 1 then we cannot */
244         if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
245                 AOP_SIZE(IC_LEFT(ic)) > 1   )
246                 return FALSE ;
247         
248         /* If we are incrementing the same register by two: */
249         
250         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
251                 
252                 while (icount--) 
253                         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
254                 //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
255                 
256                 return TRUE ;
257         }
258         
259         DEBUGpic14_emitcode ("; ","couldn't increment ");
260         
261         return FALSE ;
262 }
263
264 #if 0
265 /*-----------------------------------------------------------------*/
266 /* pic14_outBitAcc - output a bit in acc                                 */
267 /*-----------------------------------------------------------------*/
268 static void pic14_outBitAcc(operand *result)
269 {
270         symbol *tlbl = newiTempLabel(NULL);
271         /* if the result is a bit */
272         FENTRY;
273         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
274         
275         if (AOP_TYPE(result) == AOP_CRY){
276                 aopPut(AOP(result),"a",0);
277         }
278         else {
279                 pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
280                 pic14_emitcode("mov","a,#01");
281                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
282                 pic14_outAcc(result);
283         }
284 }
285 #endif
286
287 #if 0
288 /* This is the original version of this code.
289 *
290 * This is being kept around for reference, 
291 * because I am not entirely sure I got it right...
292 */
293 static void adjustArithmeticResult(iCode *ic)
294 {
295         if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
296                 AOP_SIZE(IC_LEFT(ic)) == 3   &&
297                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
298                 aopPut(AOP(IC_RESULT(ic)),
299                 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
300                 2);
301         
302         if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
303                 AOP_SIZE(IC_RIGHT(ic)) == 3   &&
304                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
305                 aopPut(AOP(IC_RESULT(ic)),
306                 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
307                 2);
308         
309         if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
310                 AOP_SIZE(IC_LEFT(ic)) < 3    &&
311                 AOP_SIZE(IC_RIGHT(ic)) < 3   &&
312                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
313                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
314                 char buffer[5];
315                 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
316                 aopPut(AOP(IC_RESULT(ic)),buffer,2);
317         }
318 }
319 //#else
320 /* This is the pure and virtuous version of this code.
321 * I'm pretty certain it's right, but not enough to toss the old 
322 * code just yet...
323 */
324 static void adjustArithmeticResult(iCode *ic)
325 {
326         if (opIsGptr(IC_RESULT(ic)) &&
327                 opIsGptr(IC_LEFT(ic))   &&
328                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
329         {
330                 aopPut(AOP(IC_RESULT(ic)),
331                         aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
332                         GPTRSIZE - 1);
333         }
334         
335         if (opIsGptr(IC_RESULT(ic)) &&
336                 opIsGptr(IC_RIGHT(ic))   &&
337                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
338         {
339                 aopPut(AOP(IC_RESULT(ic)),
340                         aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
341                         GPTRSIZE - 1);
342         }
343         
344         if (opIsGptr(IC_RESULT(ic))      &&
345                 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
346                 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
347                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
348                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
349                 char buffer[5];
350                 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
351                 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
352         }
353 }
354 #endif
355
356 /*-----------------------------------------------------------------*/
357 /* genAddlit - generates code for addition                         */
358 /*-----------------------------------------------------------------*/
359 static void genAddLit2byte (operand *result, int offr, int lit)
360 {
361         FENTRY;
362         
363         switch(lit & 0xff) {
364         case 0:
365                 break;
366         case 1:
367                 emitpcode(POC_INCF, popGet(AOP(result),offr));
368                 break;
369         case 0xff:
370                 emitpcode(POC_DECF, popGet(AOP(result),offr));
371                 break;
372         default:
373                 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
374                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
375         }
376         
377 }
378
379 static void emitMOVWF(operand *reg, int offset)
380 {
381         FENTRY;
382         if(!reg)
383                 return;
384         
385         emitpcode(POC_MOVWF, popGet(AOP(reg),offset));
386         
387 }
388
389 static void genAddLit (iCode *ic, int lit)
390 {
391         
392         int size,same;
393         int lo;
394         
395         operand *result;
396         operand *left;
397         
398         FENTRY;
399         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
400         
401         
402         left = IC_LEFT(ic);
403         result = IC_RESULT(ic);
404         same = pic14_sameRegs(AOP(left), AOP(result));
405         size = pic14_getDataSize(result);
406         if (size > pic14_getDataSize(left))
407                 size = pic14_getDataSize(left);
408         
409         if(same) {
410                 
411                 /* Handle special cases first */
412                 if(size == 1) 
413                         genAddLit2byte (result, 0, lit);
414                 
415                 else if(size == 2) {
416                         int hi = 0xff & (lit >> 8);
417                         lo = lit & 0xff;
418                         
419                         switch(hi) {
420                         case 0: 
421                                 
422                                 /* lit = 0x00LL */
423                                 DEBUGpic14_emitcode ("; hi = 0","%s  %d",__FUNCTION__,__LINE__);
424                                 switch(lo) {
425                                 case 0:
426                                         break;
427                                 case 1:
428                                         emitpcode(POC_INCF, popGet(AOP(result),0));
429                                         emitSKPNZ;
430                                         emitpcode(POC_INCF, popGet(AOP(result),MSB16));
431                                         break;
432                                 case 0xff:
433                                         emitpcode(POC_DECF, popGet(AOP(result),0));
434                                         emitpcode(POC_INCFSZW, popGet(AOP(result),0));
435                                         emitpcode(POC_INCF, popGet(AOP(result),MSB16));
436                                         
437                                         break;
438                                 default:
439                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
440                                         emitpcode(POC_ADDWF,popGet(AOP(result),0));
441                                         emitSKPNC;
442                                         emitpcode(POC_INCF, popGet(AOP(result),MSB16));
443                                         
444                                         
445                                 }
446                                 break;
447                                 
448                                 case 1:
449                                         /* lit = 0x01LL */
450                                         DEBUGpic14_emitcode ("; hi = 1","%s  %d",__FUNCTION__,__LINE__);
451                                         switch(lo) {
452                                         case 0:  /* 0x0100 */
453                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
454                                                 break;
455                                         case 1:  /* 0x0101  */
456                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
457                                                 emitpcode(POC_INCF, popGet(AOP(result),0));
458                                                 emitSKPNZ;
459                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
460                                                 break;
461                                         case 0xff: /* 0x01ff */
462                                                 emitpcode(POC_DECF, popGet(AOP(result),0));
463                                                 emitpcode(POC_INCFSZW, popGet(AOP(result),0));
464                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
465                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
466                                         }   
467                                         break;
468                                         
469                                         case 0xff:
470                                                 DEBUGpic14_emitcode ("; hi = ff","%s  %d",__FUNCTION__,__LINE__);
471                                                 /* lit = 0xffLL */
472                                                 switch(lo) {
473                                                 case 0:  /* 0xff00 */
474                                                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
475                                                         break;
476                                                 case 1:  /*0xff01 */
477                                                         emitpcode(POC_INCFSZ, popGet(AOP(result),0));
478                                                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
479                                                         break;
480                                                         /*  case 0xff: * 0xffff *
481                                                         emitpcode(POC_INCFSZW, popGet(AOP(result),0,FALSE,FALSE));
482                                                         emitpcode(POC_INCF, popGet(AOP(result),MSB16,FALSE,FALSE));
483                                                         emitpcode(POC_DECF, popGet(AOP(result),0,FALSE,FALSE));
484                                                         break;
485                                                         */
486                                                 default:
487                                                         emitpcode(POC_MOVLW,popGetLit(lo));
488                                                         emitpcode(POC_ADDWF,popGet(AOP(result),0));
489                                                         emitSKPC;
490                                                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
491                                                         
492                                                 }
493                                                 
494                                                 break;
495                                                 
496                                                 default:
497                                                         DEBUGpic14_emitcode ("; hi is generic","%d   %s  %d",hi,__FUNCTION__,__LINE__);
498                                                         
499                                                         /* lit = 0xHHLL */
500                                                         switch(lo) {
501                                                         case 0:  /* 0xHH00 */
502                                                                 genAddLit2byte (result, MSB16, hi);
503                                                                 break;
504                                                         case 1:  /* 0xHH01 */
505                                                                 emitpcode(POC_MOVLW,popGetLit((hi+1)&0xff));
506                                                                 emitpcode(POC_INCFSZ, popGet(AOP(result),0));
507                                                                 emitpcode(POC_MOVLW,popGetLit(hi));
508                                                                 emitpcode(POC_ADDWF,popGet(AOP(result),MSB16));
509                                                                 break;
510                                                                 /*  case 0xff: * 0xHHff *
511                                                                 emitpcode(POC_MOVFW, popGet(AOP(result),0,FALSE,FALSE));
512                                                                 emitpcode(POC_DECF, popGet(AOP(result),MSB16,FALSE,FALSE));
513                                                                 emitpcode(POC_MOVLW,popGetLit(hi));
514                                                                 emitpcode(POC_ADDWF,popGet(AOP(result),MSB16,FALSE,FALSE));
515                                                                 break;
516                                                                 */  default:  /* 0xHHLL */
517                                                                 emitpcode(POC_MOVLW,popGetLit(lo));
518                                                                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
519                                                                 emitpcode(POC_MOVLW,popGetLit(hi));
520                                                                 emitSKPNC;
521                                                                 emitpcode(POC_MOVLW,popGetLit((hi+1) & 0xff));
522                                                                 emitpcode(POC_ADDWF,popGet(AOP(result),MSB16));
523                                                                 break;
524                                                         }
525                                                         
526                         }
527                 } else {
528                         int carry_info = 0;
529                         int offset = 0;
530                         /* size > 2 */
531                         DEBUGpic14_emitcode (";  add lit to long","%s  %d",__FUNCTION__,__LINE__);
532                         
533                         while(size--) {
534                                 lo = BYTEofLONG(lit,0);
535                                 
536                                 if(carry_info) {
537                                         switch(lo) {
538                                         case 0:
539                                                 switch(carry_info) {
540                                                 case 1:
541                                                         emitSKPNZ;
542                                                         emitpcode(POC_INCF, popGet(AOP(result),offset));
543                                                         break;
544                                                 case 2:
545                                                         emitpcode(POC_RLFW, popGet(AOP(result),offset));
546                                                         emitpcode(POC_ANDLW,popGetLit(1));
547                                                         emitpcode(POC_ADDWF, popGet(AOP(result),offset));
548                                                         break;
549                                                 default: /* carry_info = 3  */
550                                                         emitSKPNC;
551                                                         emitpcode(POC_INCF, popGet(AOP(result),offset));
552                                                         carry_info = 1;
553                                                         break;
554                                                 }
555                                                 break;
556                                                 case 0xff:
557                                                         emitpcode(POC_MOVLW,popGetLit(lo));
558                                                         if(carry_info==1) 
559                                                                 emitSKPZ;
560                                                         else
561                                                                 emitSKPC;
562                                                         emitpcode(POC_ADDWF, popGet(AOP(result),offset));
563                                                         break;
564                                                 default:
565                                                         emitpcode(POC_MOVLW,popGetLit(lo));
566                                                         if(carry_info==1) 
567                                                                 emitSKPNZ;
568                                                         else
569                                                                 emitSKPNC;
570                                                         emitpcode(POC_MOVLW,popGetLit(lo+1));
571                                                         emitpcode(POC_ADDWF, popGet(AOP(result),offset));
572                                                         carry_info=2;
573                                                         break;
574                                         }
575                                 }else {
576                                         /* no carry info from previous step */
577                                         /* this means this is the first time to add */
578                                         switch(lo) {
579                                         case 0:
580                                                 break;
581                                         case 1:
582                                                 emitpcode(POC_INCF, popGet(AOP(result),offset));
583                                                 carry_info=1;
584                                                 break;
585                                         default:
586                                                 emitpcode(POC_MOVLW,popGetLit(lo));
587                                                 emitpcode(POC_ADDWF, popGet(AOP(result),offset));
588                                                 if(lit <0x100) 
589                                                         carry_info = 3;  /* Were adding only one byte and propogating the carry */
590                                                 else
591                                                         carry_info = 2;
592                                                 break;
593                                         }
594                                 }
595                                 offset++;
596                                 lit >>= 8;
597                         }
598                         
599                         /*
600                                 lo = BYTEofLONG(lit,0);
601                         
602                                 if(lit < 0x100) {
603                                         if(lo) {
604                                                 if(lo == 1) {
605                                                         emitpcode(POC_INCF, popGet(AOP(result),0,FALSE,FALSE));
606                                                         emitSKPNZ;
607                                                 } else {
608                                                         emitpcode(POC_MOVLW,popGetLit(lo));
609                                                         emitpcode(POC_ADDWF, popGet(AOP(result),0,FALSE,FALSE));
610                                                         emitSKPNC;
611                                                 }
612                                                 emitpcode(POC_INCF, popGet(AOP(result),1,FALSE,FALSE));
613                                                 emitSKPNZ;
614                                                 emitpcode(POC_INCF, popGet(AOP(result),2,FALSE,FALSE));
615                                                 emitSKPNZ;
616                                                 emitpcode(POC_INCF, popGet(AOP(result),3,FALSE,FALSE));
617                                                 
618                                         } 
619                                 } 
620                                 
621                         */
622                 }
623         } else {
624                 int offset = 1;
625                 DEBUGpic14_emitcode (";  left and result aren't same","%s  %d",__FUNCTION__,__LINE__);
626                 
627                 if(size == 1) {
628                         
629                         /* left addend is in a register */
630                         switch(lit & 0xff) {
631                         case 0:
632                                 emitpcode(POC_MOVFW, popGet(AOP(left),0));
633                                 emitMOVWF(result, 0);
634                                 //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
635                                 emitMOVWF(result,0);
636                                 break;
637                         case 1:
638                                 emitpcode(POC_INCFW, popGet(AOP(left),0));
639                                 //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
640                                 emitMOVWF(result,0);
641                                 break;
642                         case 0xff:
643                                 emitpcode(POC_DECFW, popGet(AOP(left),0));
644                                 //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
645                                 emitMOVWF(result,0);
646                                 break;
647                         default:
648                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
649                                 emitpcode(POC_ADDFW, popGet(AOP(left),0));
650                                 //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
651                                 emitMOVWF(result,0);
652                         }
653                         
654                 } else {
655                         int clear_carry=0;
656                         
657                         /* left is not the accumulator */
658                         if(lit & 0xff) {
659                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
660                                 emitpcode(POC_ADDFW, popGet(AOP(left),0));
661                         } else {
662                                 emitpcode(POC_MOVFW, popGet(AOP(left),0));
663                                 /* We don't know the state of the carry bit at this point */
664                                 clear_carry = 1;
665                         }
666                         //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
667                         emitMOVWF(result,0);
668                         while(--size) {
669                                 
670                                 lit >>= 8;
671                                 if(lit & 0xff) {
672                                         if(clear_carry) {
673                                         /* The ls byte of the lit must've been zero - that 
674                                                 means we don't have to deal with carry */
675                                                 
676                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
677                                                 emitpcode(POC_ADDFW,  popGet(AOP(left),offset));
678                                                 emitpcode(POC_MOVWF, popGet(AOP(left),offset));
679                                                 
680                                                 clear_carry = 0;
681                                                 
682                                         } else {
683                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
684                                                 //emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
685                                                 emitMOVWF(result,offset);
686                                                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
687                                                 emitSKPNC;
688                                                 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
689                                                 emitpcode(POC_ADDWF,  popGet(AOP(result),offset));
690                                         }
691                                         
692                                 } else {
693                                         emitpcode(POC_CLRF,  popGet(AOP(result),offset));
694                                         emitpcode(POC_RLF,   popGet(AOP(result),offset));
695                                         emitpcode(POC_MOVFW, popGet(AOP(left),offset));
696                                         emitpcode(POC_ADDWF, popGet(AOP(result),offset));
697                                 }
698                                 offset++;
699                         }
700                 }
701         }
702
703         size = pic14_getDataSize(result);
704         if (size > pic14_getDataSize(left))
705                 size = pic14_getDataSize(left);
706         addSign(result, size, 0);
707 }
708
709 /*-----------------------------------------------------------------*/
710 /* genPlus - generates code for addition                           */
711 /*-----------------------------------------------------------------*/
712 void genPlus (iCode *ic)
713 {
714         int size, offset = 0;
715         
716         /* special cases :- */
717         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
718         FENTRY;
719         
720         aopOp (IC_LEFT(ic),ic,FALSE);
721         aopOp (IC_RIGHT(ic),ic,FALSE);
722         aopOp (IC_RESULT(ic),ic,TRUE);
723         
724         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),IC_RIGHT(ic),IC_RESULT(ic));
725         
726         /* if literal, literal on the right or
727         if left requires ACC or right is already
728         in ACC */
729         
730         if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
731                 operand *t = IC_RIGHT(ic);
732                 IC_RIGHT(ic) = IC_LEFT(ic);
733                 IC_LEFT(ic) = t;
734         }
735         
736         /* if left in bit space & right literal */
737         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
738                 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
739                 /* if result in bit space */
740                 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
741                         if(ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
742                                 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0));
743                                 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
744                                         emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0));
745                                 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0));
746                         }
747                 } else {
748                         size = pic14_getDataSize(IC_RESULT(ic));
749                         while (size--) {
750                                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
751                                 pic14_emitcode("addc","a,#00  ;%d",__LINE__);
752                                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
753                         }
754                 }
755                 goto release ;
756         }
757         
758         /* if I can do an increment instead
759         of add then GOOD for ME */
760         if (genPlusIncr (ic) == TRUE)
761                 goto release;   
762         
763         size = pic14_getDataSize(IC_RESULT(ic));
764         
765         if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
766                 /* Add a literal to something else */
767                 //bool know_W=0;
768                 unsigned lit = (unsigned) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
769                 //      unsigned l1=0;
770                 
771                 //      offset = 0;
772                 DEBUGpic14_emitcode(";","adding lit to something. size %d",size);
773                 
774                 genAddLit (ic,  lit);
775                 goto release;
776                 
777         } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
778                 
779                 pic14_emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
780                 pic14_emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
781                 pic14_emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
782                 
783                 /* here we are adding a bit to a char or int */
784                 if(size == 1) {
785                         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
786                                 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
787                                 emitpcode(POC_INCF ,  popGet(AOP(IC_RESULT(ic)),0));
788                         } else {
789                                 
790                                 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0));
791                                 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
792                                 emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0));
793                                 
794                                 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
795                                         emitpcode(POC_ANDLW , popGetLit(1));
796                                         emitpcode(POC_BCF ,   popGet(AOP(IC_RESULT(ic)),0));
797                                         emitSKPZ;
798                                         emitpcode(POC_BSF ,   popGet(AOP(IC_RESULT(ic)),0));
799                                 } else {
800                                         emitpcode(POC_MOVWF ,   popGet(AOP(IC_RESULT(ic)),0));
801                                 }
802                         }
803                         
804                 } else {
805                         int offset = 1;
806                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
807                         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
808                                 emitCLRZ;
809                                 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0));
810                                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
811                         } else {
812                                 
813                                 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0));
814                                 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0));
815                                 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0));
816                                 //emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
817                                 emitMOVWF(IC_RIGHT(ic),0);
818                         }
819                         
820                         while(--size){
821                                 emitSKPZ;
822                                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),offset++));
823                         }
824                         
825                 }
826                 
827         } else {
828                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
829                 
830                 /* Add the first bytes */
831                 
832                 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
833                         emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0));
834                         emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
835                 } else {
836                         
837                         emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0));
838
839                         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
840                                 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0));
841                         else {
842                                 PIC_OPCODE poc = POC_ADDFW;
843                                 
844                                 if (op_isLitLike (IC_LEFT (ic)))
845                                         poc = POC_ADDLW;
846                                 emitpcode(poc, popGetAddr(AOP(IC_LEFT(ic)),0,0));
847                                 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
848                         }
849                 }
850                 
851                 size = min( AOP_SIZE(IC_RESULT(ic)), AOP_SIZE(IC_RIGHT(ic))) - 1;
852                 offset = 1;
853                 
854                 
855                 if(size){
856                         if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) {
857                                 if (op_isLitLike (IC_LEFT(ic)))
858                                 {
859                                         while(size--){
860                                                 emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset));
861                                                 emitSKPNC;
862                                                 emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset));
863                                                 emitpcode(POC_ADDLW,   popGetAddr(AOP(IC_LEFT(ic)),offset,0));
864                                                 emitpcode(POC_MOVWF,   popGet(AOP(IC_RESULT(ic)),offset));
865                                                 offset++;
866                                         }
867                                 } else {
868                                         while(size--){
869                                                 emitpcode(POC_MOVFW,   popGet(AOP(IC_LEFT(ic)),offset));
870                                                 emitSKPNC;
871                                                 emitpcode(POC_INCFSZW, popGet(AOP(IC_LEFT(ic)),offset));
872                                                 emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset));
873                                                 offset++;
874                                         }
875                                 }
876                         } else {
877                                 PIC_OPCODE poc = POC_MOVFW;
878                                 if (op_isLitLike (IC_LEFT(ic)))
879                                         poc = POC_MOVLW;
880                                 while(size--){
881                                         if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
882                                                 emitpcode(poc, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
883                                                 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
884                                         }
885                                         emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset));
886                                         emitSKPNC;
887                                         emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset));
888                                         emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset));
889                                         offset++;
890                                 }
891                         }
892                 }
893         }
894         
895         if (AOP_SIZE(IC_RESULT(ic)) > AOP_SIZE(IC_RIGHT(ic))) {
896                 int sign =  !(SPEC_USIGN(getSpec(operandType(IC_LEFT(ic)))) |
897                         SPEC_USIGN(getSpec(operandType(IC_RIGHT(ic)))) );
898                 
899                 
900                 /* Need to extend result to higher bytes */
901                 size = AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_RIGHT(ic)) - 1;
902                 
903                 /* First grab the carry from the lower bytes */
904                 if (AOP_SIZE(IC_LEFT(ic)) > AOP_SIZE(IC_RIGHT(ic))) { 
905                         int leftsize = AOP_SIZE(IC_LEFT(ic)) - AOP_SIZE(IC_RIGHT(ic));
906                         PIC_OPCODE poc = POC_MOVFW;
907                         if (op_isLitLike (IC_LEFT(ic)))
908                                 poc = POC_MOVLW;
909                         while(leftsize-- > 0) {
910                                 emitpcode(poc, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
911                                 emitSKPNC;
912                                 emitpcode(POC_ADDLW, popGetLit(0x01));
913                                 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
914                                 //emitSKPNC;
915                                 //emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset)); /* INCF does not update Carry! */
916                                 offset++;
917                                 if (size)
918                                         size--;
919                                 else
920                                         break;
921                         }
922                 } else {
923                         emitpcode(POC_CLRF, popGet(AOP(IC_RESULT(ic)),offset));
924                         emitpcode(POC_RLF,  popGet(AOP(IC_RESULT(ic)),offset));
925                 }
926                 
927                 
928                 if(sign && offset > 0 && offset < AOP_SIZE(IC_RESULT(ic))) {
929                 /* Now this is really horrid. Gotta check the sign of the addends and propogate
930                         * to the result */
931                         
932                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(IC_LEFT(ic)),offset-1,FALSE,FALSE),7,0));
933                         emitpcode(POC_DECF,  popGet(AOP(IC_RESULT(ic)),offset));
934                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(IC_RIGHT(ic)),offset-1,FALSE,FALSE),7,0));
935                         emitpcode(POC_DECF,  popGet(AOP(IC_RESULT(ic)),offset));
936                         
937                         /* if chars or ints or being signed extended to longs: */
938                         if(size) {
939                                 emitpcode(POC_MOVLW, popGetLit(0));
940                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE),7,0));
941                                 emitpcode(POC_MOVLW, popGetLit(0xff));
942                         }
943                 }
944                 
945                 offset++;
946                 while(size--) {
947                         
948                         if(sign)
949                                 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
950                         else
951                                 emitpcode(POC_CLRF,  popGet(AOP(IC_RESULT(ic)),offset));
952                         
953                         offset++;
954                 }
955         }
956         
957         
958         //adjustArithmeticResult(ic);
959         
960 release:
961         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
962         freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
963         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
964 }
965
966 /*-----------------------------------------------------------------*/
967 /* addSign - propogate sign bit to higher bytes                    */
968 /*-----------------------------------------------------------------*/
969 void addSign(operand *result, int offset, int sign)
970 {
971         int size = (pic14_getDataSize(result) - offset);
972         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
973         FENTRY;
974         
975         if(size > 0){
976                 if(sign && offset) {
977                         
978                         if(size == 1) {
979                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
980                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
981                                 emitpcode(POC_DECF, popGet(AOP(result),offset));
982                         } else {
983                                 
984                                 emitpcode(POC_MOVLW, popGetLit(0));
985                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
986                                 emitpcode(POC_MOVLW, popGetLit(0xff));
987                                 while(size--)
988                                         emitpcode(POC_MOVWF, popGet(AOP(result),offset+size));
989                         }
990                 } else
991                         while(size--)
992                                 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
993         }
994 }
995
996 /*-----------------------------------------------------------------*/
997 /* genMinus - generates code for subtraction                       */
998 /*-----------------------------------------------------------------*/
999 void genMinus (iCode *ic)
1000 {
1001         int size, offset = 0, same=0;
1002         unsigned long lit = 0L;
1003         int isLit;
1004         symbol *lbl_comm, *lbl_next;
1005         asmop *left, *right, *result;
1006
1007         FENTRY;
1008         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1009         aopOp (IC_LEFT(ic),ic,FALSE);
1010         aopOp (IC_RIGHT(ic),ic,FALSE);
1011         aopOp (IC_RESULT(ic),ic,TRUE);
1012         
1013         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY  &&
1014                 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1015                 operand *t = IC_RIGHT(ic);
1016                 IC_RIGHT(ic) = IC_LEFT(ic);
1017                 IC_LEFT(ic) = t;
1018         }
1019         
1020         DEBUGpic14_emitcode ("; ","result %s, left %s, right %s",
1021                 AopType(AOP_TYPE(IC_RESULT(ic))),
1022                 AopType(AOP_TYPE(IC_LEFT(ic))),
1023                 AopType(AOP_TYPE(IC_RIGHT(ic))));
1024         
1025         left = AOP(IC_LEFT(ic));
1026         right = AOP(IC_RIGHT(ic));
1027         result = AOP(IC_RESULT(ic));
1028         
1029         size = pic14_getDataSize(IC_RESULT(ic));
1030         same = pic14_sameRegs(right, result);
1031
1032         if((AOP_TYPE(IC_LEFT(ic)) != AOP_LIT)
1033             && (pic14_getDataSize(IC_LEFT(ic)) < size))
1034         {
1035                 fprintf(stderr, "%s:%d(%s):WARNING: left operand too short for result\n",
1036                         ic->filename, ic->lineno, __FUNCTION__);
1037         } // if
1038         if((AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1039             && (pic14_getDataSize(IC_RIGHT(ic)) < size))
1040         {
1041                 fprintf(stderr, "%s:%d(%s):WARNING: right operand too short for result\n",
1042                         ic->filename, ic->lineno, __FUNCTION__ );
1043         } // if
1044
1045         if(AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1046                 /* Add a literal to something else */
1047                 
1048                 lit = ulFromVal(right->aopu.aop_lit);
1049                 lit = -(long)lit;
1050                 
1051                 genAddLit(ic, lit);
1052                 
1053         } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1054                 // bit subtraction
1055                 
1056                 pic14_emitcode(";bitsub","right is bit: %s",aopGet(right,0,FALSE,FALSE));
1057                 pic14_emitcode(";bitsub","left is bit: %s",aopGet(left,0,FALSE,FALSE));
1058                 pic14_emitcode(";bitsub","result is bit: %s",aopGet(result,0,FALSE,FALSE));
1059                 
1060                 /* here we are subtracting a bit from a char or int */
1061                 if(size == 1) {
1062                         if(pic14_sameRegs(left, result)) {
1063                                 
1064                                 emitpcode(POC_BTFSC, popGet(right, 0));
1065                                 emitpcode(POC_DECF , popGet(result, 0));
1066                                 
1067                         } else {
1068                                 
1069                                 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
1070                                         (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1071                                         /*
1072                                          * result = literal - bit
1073                                          *
1074                                          * XXX: probably fails for AOP_IMMDs!
1075                                          */
1076                                         
1077                                         lit = ulFromVal (left->aopu.aop_lit);
1078                                         
1079                                         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1080                                                 if(pic14_sameRegs(right, result)) {
1081                                                         if(lit & 1) {
1082                                                                 emitpcode(POC_MOVLW, popGet(right, 0));
1083                                                                 emitpcode(POC_XORWF, popGet(result, 0));
1084                                                         }
1085                                                 } else {
1086                                                         emitpcode(POC_BCF, popGet(result, 0));
1087                                                         if(lit & 1) 
1088                                                                 emitpcode(POC_BTFSS, popGet(right, 0));
1089                                                         else
1090                                                                 emitpcode(POC_BTFSC, popGet(right, 0));
1091                                                         emitpcode(POC_BSF, popGet(result, 0));
1092                                                 }
1093                                                 goto release;
1094                                         } else {
1095                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
1096                                                 emitpcode(POC_BTFSC, popGet(right, 0));
1097                                                 emitpcode(POC_MOVLW, popGetLit((lit-1) & 0xff));
1098                                                 emitpcode(POC_MOVWF, popGet(result, 0));
1099                                         }
1100                                         
1101                                 } else {
1102                                         // result = register - bit
1103                                         // XXX: Fails for lit-like left operands
1104                                         emitpcode(POC_MOVFW, popGet(left, 0));
1105                                         emitpcode(POC_BTFSC, popGet(right, 0));
1106                                         emitpcode(POC_DECFW, popGet(left, 0));
1107                                         emitpcode(POC_MOVWF, popGet(result, 0));
1108                                 }
1109                         }
1110                 } else {
1111                     fprintf(stderr, "WARNING: subtracting bit from multi-byte operands is incomplete.\n");
1112                     //exit(EXIT_FAILURE);
1113                 } // if
1114         } else {
1115                 /*
1116                  * RIGHT is not a literal and not a bit operand,
1117                  * LEFT is unknown (register, literal, bit, ...)
1118                  */
1119                 lit = 0;
1120                 isLit = 0;
1121
1122                 if(AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
1123                         lit = ulFromVal (left->aopu.aop_lit);
1124                         isLit = 1;
1125                         DEBUGpic14_emitcode ("; left is lit","line %d result %s, left %s, right %s",__LINE__,
1126                                 AopType(AOP_TYPE(IC_RESULT(ic))),
1127                                 AopType(AOP_TYPE(IC_LEFT(ic))),
1128                                 AopType(AOP_TYPE(IC_RIGHT(ic))));
1129                 } // if
1130
1131
1132                 /*
1133                  * First byte, no carry-in.
1134                  * Any optimizations that are longer than 2 instructions are
1135                  * useless.
1136                  */
1137                 if(same && isLit && ((lit & 0xff) == 0xff)) {
1138                         // right === res = 0xFF - right = ~right
1139                         emitpcode(POC_COMF, popGet(right, 0));
1140                         if(size > 1) {
1141                                 // setup CARRY/#BORROW
1142                                 emitSETC;
1143                         } // if
1144                 } else if((size == 1) && isLit && ((lit & 0xff) == 0xff)) {
1145                         // res = 0xFF - right = ~right
1146                         emitpcode(POC_COMFW, popGet(right, 0));
1147                         emitpcode(POC_MOVWF, popGet(result, 0));
1148                         // CARRY/#BORROW is not setup correctly
1149                 } else if((size == 1) && same && isLit && ((lit & 0xff) == 0)) {
1150                         // right === res = 0 - right = ~right + 1
1151                         emitpcode(POC_COMF, popGet(right, 0));
1152                         emitpcode(POC_INCF, popGet(right, 0));
1153                         // CARRY/#BORROW is not setup correctly
1154                 } else {
1155                         // general case, should always work
1156                         mov2w(right, 0);
1157                         if (pic14_sameRegs(left, result)) {
1158                                 // result === left = left - right (in place)
1159                                 emitpcode(POC_SUBWF, popGet(result, 0));
1160                         } else {
1161                                 // works always: result = left - right
1162                                 emitpcode(op_isLitLike(IC_LEFT(ic))
1163                                         ? POC_SUBLW : POC_SUBFW,
1164                                         popGetAddr(left, 0, 0));
1165                                 emitpcode(POC_MOVWF, popGet(result, 0));
1166                         } // if
1167                 } // if
1168                 
1169                 /*
1170                  * Now for the remaining bytes with carry-in (and carry-out).
1171                  */
1172                 offset = 0;
1173                 while(--size) {
1174                         lit >>= 8;
1175                         offset++;
1176
1177                         /*
1178                          * The following code generation templates are ordered
1179                          * according to increasing length; the first template
1180                          * that matches will thus be the shortest and produce
1181                          * the best code possible with thees templates.
1182                          */
1183
1184                         if(pic14_sameRegs(left, right)) {
1185                             /*
1186                              * This case should not occur; however, the
1187                              * template works if LEFT, RIGHT, and RESULT are
1188                              * register operands and LEFT and RIGHT are the
1189                              * same register(s) and at least as long as the
1190                              * result.
1191                              *
1192                              *   CLRF   result
1193                              *
1194                              * 1 cycle
1195                              */
1196                             emitpcode(POC_CLRF, popGet(result, offset));
1197                         } else if(pic14_sameRegs(left, result)) {
1198                             /*
1199                              * This template works if LEFT, RIGHT, and
1200                              * RESULT are register operands and LEFT and
1201                              * RESULT are the same register(s).
1202                              *
1203                              *   MOVF   right, W    ; W := right
1204                              *   BTFSS  STATUS, C
1205                              *   INCFSZ right, W    ; W := right + BORROW
1206                              *   SUBWF  result, F   ; res === left := left - (right + BORROW)
1207                              *
1208                              * The SUBWF *must* be skipped if we have a
1209                              * BORROW bit and right == 0xFF in order to
1210                              * keep the BORROW bit intact!
1211                              *
1212                              * 4 cycles
1213                              */
1214                             mov2w(right, offset);
1215                             emitSKPC;
1216                             emitpcode(POC_INCFSZW, popGet(right, offset));
1217                             emitpcode(POC_SUBWF, popGet(result, offset));
1218                         } else if((size == 1) && isLit && ((lit & 0xff) == 0xff)) {
1219                             /*
1220                              * This template works for the last byte (MSB) of
1221                              * the subtraction and ignores correct propagation
1222                              * of the outgoing BORROW bit. RIGHT and RESULT
1223                              * must be register operands, LEFT must be the
1224                              * literal 0xFF.
1225                              *
1226                              * (The case LEFT === RESULT is optimized above.)
1227                              *
1228                              * 0xFF - right - BORROW = ~right - BORROW
1229                              *
1230                              *   COMF   right, W    ; W := 0xff - right
1231                              *   BTFSS  STATUS, C
1232                              *   ADDLW  0xFF        ; W := 0xff - right - BORROW
1233                              *   MOVWF  result
1234                              *
1235                              * 4 cycles
1236                              */
1237                             emitpcode(POC_COMFW, popGet(right, offset));
1238                             emitSKPC;
1239                             emitpcode(POC_ADDLW, popGetLit(0xff));
1240                             emitpcode(POC_MOVWF, popGet(result, offset));
1241                         } else if(size == 1) {
1242                             /*
1243                              * This template works for the last byte (MSB) of
1244                              * the subtraction and ignores correct propagation
1245                              * of the outgoing BORROW bit. RIGHT and RESULT
1246                              * must be register operands, LEFT can be a
1247                              * register or a literal operand.
1248                              *
1249                              * (The case LEFT === RESULT is optimized above.)
1250                              *
1251                              *   MOVF   right, W    ; W := right
1252                              *   BTFSS  STATUS, C
1253                              *   INCF   right, W    ; W := right + BORROW
1254                              *   SUBxW  left, W     ; W := left - right - BORROW
1255                              *   MOVWF  result
1256                              *
1257                              * 5 cycles
1258                              */
1259                             mov2w(right, offset);
1260                             emitSKPC;
1261                             emitpcode(POC_INCFW, popGet(right, offset));
1262                             emitpcode(op_isLitLike(IC_LEFT(ic))
1263                                     ? POC_SUBLW : POC_SUBFW,
1264                                     popGetAddr(left, offset, 0));
1265                             emitpcode(POC_MOVWF, popGet(result, offset));
1266                         } else if(IS_ITEMP(IC_RESULT(ic))
1267                                 && !pic14_sameRegs(right, result)) {
1268                             /*
1269                              * This code template works if RIGHT and RESULT
1270                              * are different register operands and RESULT
1271                              * is not volatile/an SFR (written twice).
1272                              *
1273                              * #########################################
1274                              * Since we cannot determine that for sure,
1275                              * we approximate via IS_ITEMP() for now.
1276                              * #########################################
1277                              *
1278                              *   MOVxW  left, W     ; copy left to result
1279                              *   MOVWF  result
1280                              *   MOVF   right, W    ; W := right
1281                              *   BTFSS  STATUS, C
1282                              *   INCFSZ right, W    ; W := right + BORROW
1283                              *   SUBWF  result, F   ; res === left := left - (right + BORROW)
1284                              *
1285                              * 6 cycles, but fails for SFR RESULT operands
1286                              */
1287                             mov2w(left, offset);
1288                             emitpcode(POC_MOVWF, popGet(result, offset));
1289                             mov2w(right, offset);
1290                             emitSKPC;
1291                             emitpcode(POC_INCFSZW, popGet(right, offset));
1292                             emitpcode(POC_SUBWF, popGet(result, offset));
1293                         } else if(!optimize.codeSize && isLit && ((lit & 0xff) != 0)) {
1294                             /*
1295                              * This template works if RIGHT and RESULT are
1296                              * register operands and LEFT is a literal
1297                              * operand != 0.
1298                              *
1299                              *   MOVxW  right, W
1300                              *   BTFSC  STATUS, C
1301                              *   GOTO   next
1302                              *   SUBLW  left-1
1303                              *   GOTO   common
1304                              * next:
1305                              *   SUBLW  left
1306                              * common:
1307                              *   MOVWF  result
1308                              *
1309                              * 6 cycles, 7 iff BORROW
1310                              * (9 instructions)
1311                              */
1312                             lbl_comm = newiTempLabel(NULL);
1313                             lbl_next = newiTempLabel(NULL);
1314
1315                             mov2w(right, offset);
1316                             emitSKPNC;
1317                             emitpcode(POC_GOTO, popGetLabel(lbl_next->key));
1318                             emitpcode(POC_SUBLW, popGetLit((lit - 1) & 0xff));
1319                             emitpcode(POC_GOTO, popGetLabel(lbl_comm->key));
1320                             emitpLabel(lbl_next->key);
1321                             emitpcode(POC_SUBLW, popGetLit(lit & 0xff));
1322                             emitpLabel(lbl_comm->key);
1323                             emitpcode(POC_MOVWF, popGet(result, offset));
1324                         } else {
1325                             /*
1326                              * This code template works if RIGHT and RESULT
1327                              * are register operands.
1328                              *
1329                              *   MOVF   right, W    ; W := right
1330                              *   BTFSS  STATUS, C
1331                              *   INCFSZ right, W    ; W := right + BORROW
1332                              *   GOTO   common
1333                              *   MOVxW  left        ; if we subtract 0x100 = 0xFF + 1, ...
1334                              *   GOTO   next        ; res := left, but keep BORROW intact
1335                              * common:
1336                              *   SUBxW  left, W     ; W := left - (right + BORROW)
1337                              * next:
1338                              *   MOVW   result      ; res := left - (right + BORROW)
1339                              *
1340                              * 7 cycles, 8 iff BORROW and (right == 0xFF)
1341                              * (8 instructions)
1342                              *
1343                              *
1344                              *
1345                              * Alternative approach using -x = ~x + 1 ==> ~x = -x - 1 = -(x + 1)
1346                              *
1347                              *   COMFW  right, W    ; W := -right - (assumed BORROW)
1348                              *   BTFSC  STATUS, C   ; SKIP if we have a BORROW
1349                              *   ADDLW  1           ; W := -right (no BORROW)
1350                              *   BTFSC  STATUS, C   ; (***)
1351                              *   MOVLW  left        ; (***)
1352                              *   BTFSS  STATUS, C   ; (***)
1353                              *   ADDFW  left, W     ; W := left - right - BORROW (if any)
1354                              *   MOVWF  result      ; result := left - right - BORROW (if any)
1355                              *
1356                              * 8 cycles
1357                              *
1358                              * Case A: C=0 (BORROW)
1359                              * r=0x00, W=0xFF, W=left+0xFF, C iff left>0x00
1360                              * r=0x01, W=0xFE, W=left+0xFE, C iff left>0x01
1361                              * r=0xFE, W=0x01, W=left+0x01, C iff left>0xFE
1362                              * r=0xFF, W=0x00, W=left+0x00, C iff left>0xFF
1363                              *
1364                              * Case B: C=1 (no BORROW)
1365                              * r=0x00, W=0xFF, W=0x00/C=1, W=left+0x00, C iff left>=0x100 (***)
1366                              * r=0x01, W=0xFE, W=0xFF/C=0, W=left+0xFF, C iff left>=0x01
1367                              * r=0xFE, W=0x01, W=0x02/C=0, W=left+0x02, C iff left>=0xFE
1368                              * r=0xFF, W=0x00, W=0x01/C=0, W=left+0x01, C iff left>=0xFF
1369                              */
1370                             lbl_comm = newiTempLabel(NULL);
1371                             lbl_next = newiTempLabel(NULL);
1372
1373                             mov2w(right, offset);
1374                             emitSKPC;
1375                             emitpcode(POC_INCFSZW, popGet(right, offset));
1376                             emitpcode(POC_GOTO, popGetLabel(lbl_comm->key));
1377                             mov2w(left, offset);
1378                             emitpcode(POC_GOTO, popGetLabel(lbl_next->key));
1379                             emitpLabel(lbl_comm->key);
1380                             emitpcode(op_isLitLike(IC_LEFT(ic))
1381                                     ? POC_SUBLW : POC_SUBFW,
1382                                     popGetAddr(left, offset, 0));
1383                             emitpLabel(lbl_next->key);
1384                             emitpcode(POC_MOVWF, popGet(result, offset));
1385                         } // if
1386                 } // while
1387         } // if
1388
1389         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1390             fprintf(stderr, "WARNING: AOP_CRY (bit-) results are probably broken. Please report this with source code as a bug.\n");
1391             mov2w(result, 0); // load Z flag
1392             emitpcode(POC_BCF, popGet(result, 0));
1393             emitSKPZ;
1394             emitpcode(POC_BSF, popGet(result, 0));
1395         } // if
1396         
1397         //    adjustArithmeticResult(ic);
1398         
1399 release:
1400         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1401         freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1402         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1403 }
1404