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