Added new regression test add2.c - tests adding lit's to unsigned ints. Literal addit...
[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)
40 #define __FUNCTION__            __FILE__
41 #endif
42
43 #ifdef HAVE_SYS_ISA_DEFS_H
44 #include <sys/isa_defs.h>
45 #else
46 #ifdef HAVE_MACHINE_ENDIAN_H
47 #include <machine/endian.h>
48 #else
49 #ifdef HAVE_ENDIAN_H
50 #include <endian.h>
51 #else
52 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
53 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
54 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
55 #endif
56 #endif
57 #endif
58 #endif
59
60 #include "common.h"
61 #include "SDCCpeeph.h"
62 #include "ralloc.h"
63 #include "pcode.h"
64 #include "gen.h"
65
66 /*-----------------------------------------------------------------*/
67 /* genPlusIncr :- does addition with increment if possible         */
68 /*-----------------------------------------------------------------*/
69 bool genPlusIncr (iCode *ic)
70 {
71     unsigned int icount ;
72     unsigned int size = pic14_getDataSize(IC_RESULT(ic));
73
74     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
75     DEBUGpic14_emitcode ("; ","result %d, left %d, right %d",
76                    AOP_TYPE(IC_RESULT(ic)),
77                    AOP_TYPE(IC_LEFT(ic)),
78                    AOP_TYPE(IC_RIGHT(ic)));
79
80     /* will try to generate an increment */
81     /* if the right side is not a literal 
82        we cannot */
83     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
84         return FALSE ;
85     
86     DEBUGpic14_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
87     /* if the literal value of the right hand side
88        is greater than 1 then it is faster to add */
89     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
90         return FALSE ;
91     
92     /* if increment 16 bits in register */
93     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
94         (icount == 1)) {
95
96       int offset = MSB16;
97
98       emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
99       //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
100
101       while(--size) {
102         emitSKPNZ;
103         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
104         //pic14_emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
105       }
106
107       return TRUE;
108     }
109     
110     DEBUGpic14_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
111     /* if left is in accumulator  - probably a bit operation*/
112     if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a")  &&
113         (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
114       
115       emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
116       pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
117                AOP(IC_RESULT(ic))->aopu.aop_dir,
118                AOP(IC_RESULT(ic))->aopu.aop_dir);
119       if(icount)
120         emitpcode(POC_XORLW,popGetLit(1));
121       //pic14_emitcode("xorlw","1");
122       else
123         emitpcode(POC_ANDLW,popGetLit(1));
124       //pic14_emitcode("andlw","1");
125
126       emitSKPZ;
127       emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
128       pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
129                AOP(IC_RESULT(ic))->aopu.aop_dir,
130                AOP(IC_RESULT(ic))->aopu.aop_dir);
131
132       return TRUE;
133     }
134
135
136
137     /* if the sizes are greater than 1 then we cannot */
138     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
139         AOP_SIZE(IC_LEFT(ic)) > 1   )
140         return FALSE ;
141     
142     /* If we are incrementing the same register by two: */
143
144     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
145         
146       while (icount--) 
147         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
148       //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
149         
150       return TRUE ;
151     }
152     
153     DEBUGpic14_emitcode ("; ","couldn't increment result-%s  left-%s",
154                    aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
155                    aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
156     return FALSE ;
157 }
158
159 /*-----------------------------------------------------------------*/
160 /* pic14_outBitAcc - output a bit in acc                                 */
161 /*-----------------------------------------------------------------*/
162 void pic14_outBitAcc(operand *result)
163 {
164     symbol *tlbl = newiTempLabel(NULL);
165     /* if the result is a bit */
166     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
167
168     if (AOP_TYPE(result) == AOP_CRY){
169         aopPut(AOP(result),"a",0);
170     }
171     else {
172         pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
173         pic14_emitcode("mov","a,#01");
174         pic14_emitcode("","%05d_DS_:",tlbl->key+100);
175         pic14_outAcc(result);
176     }
177 }
178
179 /*-----------------------------------------------------------------*/
180 /* genPlusBits - generates code for addition of two bits           */
181 /*-----------------------------------------------------------------*/
182 void genPlusBits (iCode *ic)
183 {
184
185     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
186     /*
187       The following block of code will add two bits. 
188       Note that it'll even work if the destination is
189       the carry (C in the status register).
190       It won't work if the 'Z' bit is a source or destination.
191     */
192
193     /* If the result is stored in the accumulator (w) */
194     //if(strcmp(aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
195     if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
196       //emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
197       //              popGet(AOP(result),0,FALSE,FALSE));
198
199       emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
200       emitpcode(POC_BCF,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
201       emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
202       emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
203       emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
204       emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
205
206         pic14_emitcode("movlw","(1 << (%s & 7))",
207                  AOP(IC_RESULT(ic))->aopu.aop_dir,
208                  AOP(IC_RESULT(ic))->aopu.aop_dir);
209         pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
210                  AOP(IC_RESULT(ic))->aopu.aop_dir,
211                  AOP(IC_RESULT(ic))->aopu.aop_dir);
212         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
213                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
214                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
215         pic14_emitcode("xorwf","(%s >>3),f",
216                  AOP(IC_RESULT(ic))->aopu.aop_dir);
217         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
218                  AOP(IC_LEFT(ic))->aopu.aop_dir,
219                  AOP(IC_LEFT(ic))->aopu.aop_dir);
220         pic14_emitcode("xorwf","(%s>>3),f",
221                  AOP(IC_RESULT(ic))->aopu.aop_dir);
222     } else { 
223
224       emitpcode(POC_CLRW, NULL);
225       emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
226       emitpcode(POC_XORLW, popGetLit(1));
227       emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
228       emitpcode(POC_XORLW, popGetLit(1));
229
230       pic14_emitcode("clrw","");
231       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
232                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
233                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
234       pic14_emitcode("xorlw","1");
235       pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
236                AOP(IC_LEFT(ic))->aopu.aop_dir,
237                AOP(IC_LEFT(ic))->aopu.aop_dir);
238       pic14_emitcode("xorlw","1");
239     }
240
241 }
242
243 #if 0
244 /* This is the original version of this code.
245  *
246  * This is being kept around for reference, 
247  * because I am not entirely sure I got it right...
248  */
249 static void adjustArithmeticResult(iCode *ic)
250 {
251     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
252         AOP_SIZE(IC_LEFT(ic)) == 3   &&
253         !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
254         aopPut(AOP(IC_RESULT(ic)),
255                aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
256                2);
257
258     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
259         AOP_SIZE(IC_RIGHT(ic)) == 3   &&
260         !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
261         aopPut(AOP(IC_RESULT(ic)),
262                aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
263                2);
264     
265     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
266         AOP_SIZE(IC_LEFT(ic)) < 3    &&
267         AOP_SIZE(IC_RIGHT(ic)) < 3   &&
268         !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
269         !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
270         char buffer[5];
271         sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
272         aopPut(AOP(IC_RESULT(ic)),buffer,2);
273     }
274 }
275 //#else
276 /* This is the pure and virtuous version of this code.
277  * I'm pretty certain it's right, but not enough to toss the old 
278  * code just yet...
279  */
280 static void adjustArithmeticResult(iCode *ic)
281 {
282     if (opIsGptr(IC_RESULT(ic)) &&
283         opIsGptr(IC_LEFT(ic))   &&
284         !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
285     {
286         aopPut(AOP(IC_RESULT(ic)),
287                aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
288                GPTRSIZE - 1);
289     }
290
291     if (opIsGptr(IC_RESULT(ic)) &&
292         opIsGptr(IC_RIGHT(ic))   &&
293         !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
294     {
295         aopPut(AOP(IC_RESULT(ic)),
296                aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
297                GPTRSIZE - 1);
298     }
299
300     if (opIsGptr(IC_RESULT(ic))            &&
301         AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
302         AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
303          !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
304          !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
305          char buffer[5];
306          sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
307          aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
308      }
309 }
310 #endif
311
312 /*-----------------------------------------------------------------*/
313 /* genAddlit - generates code for addition                         */
314 /*-----------------------------------------------------------------*/
315 static void genAddLit2byte (operand *result, int offr, int lit)
316 {
317
318   switch(lit & 0xff) {
319   case 0:
320     break;
321   case 1:
322     emitpcode(POC_INCF, popGet(AOP(result),offr,FALSE,FALSE));
323     break;
324   case 0xff:
325     emitpcode(POC_DECF, popGet(AOP(result),offr,FALSE,FALSE));
326     break;
327   default:
328     emitpcode(POC_MOVLW,popGetLit(lit&0xff));
329     emitpcode(POC_ADDWF,popGet(AOP(result),offr,FALSE,FALSE));
330   }
331
332 }
333
334 static void genAddLit (operand *result,operand *left, int lit)
335 {
336
337   int size,same;
338   int knowW=0,W=0,needC=0;
339
340   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
341   size = pic14_getDataSize(result);
342
343   same = ((left == result) || (AOP(left) == AOP(result)));
344
345   if(same) {
346
347     /* Handle special cases first */
348     if(size == 1) 
349       genAddLit2byte (result, 0, lit);
350      
351     else if(size == 2) {
352       int hi = 0xff & (lit >> 8);
353       int lo = lit & 0xff;
354
355       switch(hi) {
356       case 0: 
357
358         /* lit = 0x00LL */
359         DEBUGpic14_emitcode ("; hi = 0","%s  %d",__FUNCTION__,__LINE__);
360         switch(lo) {
361         case 0:
362           break;
363         case 1:
364           emitpcode(POC_INCF, popGet(AOP(result),0,FALSE,FALSE));
365           emitSKPNZ;
366           emitpcode(POC_INCF, popGet(AOP(result),MSB16,FALSE,FALSE));   
367           break;
368         case 0xff:
369           emitpcode(POC_DECF, popGet(AOP(result),0,FALSE,FALSE));
370           emitpcode(POC_INCFSZW, popGet(AOP(result),0,FALSE,FALSE));
371           emitpcode(POC_INCF, popGet(AOP(result),MSB16,FALSE,FALSE));   
372
373           break;
374         default:
375           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
376           emitpcode(POC_ADDWF,popGet(AOP(result),0,FALSE,FALSE));
377           emitSKPNC;
378           emitpcode(POC_INCF, popGet(AOP(result),MSB16,FALSE,FALSE));   
379
380
381         }
382         break;
383
384       case 1:
385         /* lit = 0x01LL */
386         DEBUGpic14_emitcode ("; hi = 1","%s  %d",__FUNCTION__,__LINE__);
387         switch(lo) {
388         case 0:  /* 0x0100 */
389           emitpcode(POC_INCF, popGet(AOP(result),MSB16,FALSE,FALSE));   
390           break;
391         case 1:  /* 0x0101  */
392           emitpcode(POC_INCF, popGet(AOP(result),MSB16,FALSE,FALSE));
393           emitpcode(POC_INCF, popGet(AOP(result),0,FALSE,FALSE));
394           emitSKPNZ;
395           emitpcode(POC_INCF, popGet(AOP(result),MSB16,FALSE,FALSE));   
396           break;
397         case 0xff: /* 0x01ff */
398           emitpcode(POC_DECF, popGet(AOP(result),0,FALSE,FALSE));
399           emitpcode(POC_INCFSZW, popGet(AOP(result),0,FALSE,FALSE));
400           emitpcode(POC_INCF, popGet(AOP(result),MSB16,FALSE,FALSE));   
401           emitpcode(POC_INCF, popGet(AOP(result),MSB16,FALSE,FALSE));   
402         }         
403         break;
404
405       case 0xff:
406         DEBUGpic14_emitcode ("; hi = ff","%s  %d",__FUNCTION__,__LINE__);
407         /* lit = 0xffLL */
408         switch(lo) {
409         case 0:  /* 0xff00 */
410           emitpcode(POC_DECF, popGet(AOP(result),MSB16,FALSE,FALSE));
411           break;
412         case 1:  /*0xff01 */
413           emitpcode(POC_INCFSZ, popGet(AOP(result),0,FALSE,FALSE));
414           emitpcode(POC_DECF, popGet(AOP(result),MSB16,FALSE,FALSE));
415           break;
416 /*      case 0xff: * 0xffff *
417           emitpcode(POC_INCFSZW, popGet(AOP(result),0,FALSE,FALSE));
418           emitpcode(POC_INCF, popGet(AOP(result),MSB16,FALSE,FALSE));
419           emitpcode(POC_DECF, popGet(AOP(result),0,FALSE,FALSE));
420           break;
421 */
422         default:
423           emitpcode(POC_MOVLW,popGetLit(lo));
424           emitpcode(POC_ADDWF,popGet(AOP(result),0,FALSE,FALSE));
425           emitSKPC;
426           emitpcode(POC_DECF, popGet(AOP(result),MSB16,FALSE,FALSE));
427           
428         }
429
430         break;
431         
432       default:
433         DEBUGpic14_emitcode ("; hi is generic","%d   %s  %d",hi,__FUNCTION__,__LINE__);
434
435         /* lit = 0xHHLL */
436         switch(lo) {
437         case 0:  /* 0xHH00 */
438           genAddLit2byte (result, MSB16, hi);
439           break;
440         case 1:  /* 0xHH01 */
441           emitpcode(POC_MOVLW,popGetLit((hi+1)&0xff));
442           emitpcode(POC_INCFSZ, popGet(AOP(result),0,FALSE,FALSE));
443           emitpcode(POC_MOVLW,popGetLit(hi));
444           emitpcode(POC_ADDWF,popGet(AOP(result),MSB16,FALSE,FALSE));
445           break;
446 /*      case 0xff: * 0xHHff *
447           emitpcode(POC_MOVFW, popGet(AOP(result),0,FALSE,FALSE));
448           emitpcode(POC_DECF, popGet(AOP(result),MSB16,FALSE,FALSE));
449           emitpcode(POC_MOVLW,popGetLit(hi));
450           emitpcode(POC_ADDWF,popGet(AOP(result),MSB16,FALSE,FALSE));
451           break;
452 */      default:  /* 0xHHLL */
453           emitpcode(POC_MOVLW,popGetLit(lo));
454           emitpcode(POC_ADDWF, popGet(AOP(result),0,FALSE,FALSE));
455           emitpcode(POC_MOVLW,popGetLit(hi));
456           emitSKPNC;
457           emitpcode(POC_MOVLW,popGetLit((hi+1) & 0xff));
458           emitpcode(POC_ADDWF,popGet(AOP(result),MSB16,FALSE,FALSE));
459           break;
460         }
461
462       }
463     }
464   } else {
465     int offset = 1;
466     DEBUGpic14_emitcode (";  left and result aren't same","%s  %d",__FUNCTION__,__LINE__);
467
468     if(size == 1) {
469
470       switch(lit & 0xff) {
471       case 0:
472         emitpcode(POC_MOVFW, popGet(AOP(left),0,FALSE,FALSE));
473         emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
474         break;
475       case 1:
476         emitpcode(POC_INCFW, popGet(AOP(left),0,FALSE,FALSE));
477         emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
478         break;
479       case 0xff:
480         emitpcode(POC_DECFW, popGet(AOP(left),0,FALSE,FALSE));
481         emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
482         break;
483       default:
484         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
485         emitpcode(POC_ADDFW, popGet(AOP(left),0,FALSE,FALSE));
486         emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
487       }
488     } else {
489
490       if(lit & 0xff) {
491         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
492         emitpcode(POC_ADDFW, popGet(AOP(left),0,FALSE,FALSE));
493       } else
494         emitpcode(POC_MOVFW, popGet(AOP(left),0,FALSE,FALSE));
495
496       emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
497       lit >>= 8;
498       while(--size) {
499       
500         if(lit & 0xff) {
501           emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
502           emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
503           emitpcode(POC_MOVFW, popGet(AOP(left),offset,FALSE,FALSE));
504           emitSKPNC;
505           emitpcode(POC_INCFSZW,popGet(AOP(left),offset,FALSE,FALSE));
506           emitpcode(POC_ADDWF,  popGet(AOP(result),offset,FALSE,FALSE));
507         } else {
508           emitpcode(POC_CLRF,  popGet(AOP(result),offset,FALSE,FALSE));
509           emitpcode(POC_RLF,   popGet(AOP(result),offset,FALSE,FALSE));
510           emitpcode(POC_MOVFW, popGet(AOP(left),offset,FALSE,FALSE));
511           emitpcode(POC_ADDWF, popGet(AOP(result),offset,FALSE,FALSE));
512         }
513       offset++;
514       }
515     }
516   }
517 }
518
519 /*-----------------------------------------------------------------*/
520 /* genPlus - generates code for addition                           */
521 /*-----------------------------------------------------------------*/
522 void genPlus (iCode *ic)
523 {
524   int size, offset = 0;
525
526   /* special cases :- */
527   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
528
529   aopOp (IC_LEFT(ic),ic,FALSE);
530   aopOp (IC_RIGHT(ic),ic,FALSE);
531   aopOp (IC_RESULT(ic),ic,TRUE);
532
533   /* if literal, literal on the right or
534      if left requires ACC or right is already
535      in ACC */
536
537   if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
538     operand *t = IC_RIGHT(ic);
539     IC_RIGHT(ic) = IC_LEFT(ic);
540     IC_LEFT(ic) = t;
541   }
542
543   /* if both left & right are in bit space */
544   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
545       AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
546     genPlusBits (ic);
547     goto release ;
548   }
549
550   /* if left in bit space & right literal */
551   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
552       AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
553     /* if result in bit space */
554     if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
555       if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
556         emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
557         if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
558           emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
559         emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
560       }
561     } else {
562       size = pic14_getDataSize(IC_RESULT(ic));
563       while (size--) {
564         MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
565         pic14_emitcode("addc","a,#00  ;%d",__LINE__);
566         aopPut(AOP(IC_RESULT(ic)),"a",offset++);
567       }
568     }
569     goto release ;
570   }
571
572   /* if I can do an increment instead
573      of add then GOOD for ME */
574   if (genPlusIncr (ic) == TRUE)
575     goto release;   
576
577   size = pic14_getDataSize(IC_RESULT(ic));
578
579   if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
580     /* Add a literal to something else */
581     //bool know_W=0;
582     unsigned lit = (unsigned) floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
583     //      unsigned l1=0;
584
585     //      offset = 0;
586     DEBUGpic14_emitcode(";","adding lit to something. size %d",size);
587
588     genAddLit ( IC_RESULT(ic),IC_LEFT(ic),  lit);
589 #if 0
590     while(size--){
591
592       DEBUGpic14_emitcode(";","size %d",size);
593
594       switch (lit & 0xff) {
595       case 0:
596         break;
597       case 1:
598         if(pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
599           emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
600         else {
601           know_W = 0;
602           emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
603           if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
604             emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
605         }
606         break;
607       case 0xff:
608         if(pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))))
609           emitpcode(POC_DECF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
610         else {
611           know_W = 0;
612           emitpcode(POC_DECFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
613           if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
614             emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
615         }
616         break;
617       default:
618         if( !know_W || ( (lit&0xff) != l1)  ) {
619           know_W = 1;
620           emitpcode(POC_MOVLW,popGetLit(lit&0xff));
621         }
622         if(pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
623           emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
624           if(size) {
625             emitSKPNC;
626             emitpcode(POC_INCF, popGet(AOP(IC_LEFT(ic)),offset+1,FALSE,FALSE));
627           }
628
629         } else {
630           know_W = 0;
631           emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
632           emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
633           if(size) {
634             emitSKPNC;
635             emitpcode(POC_INCFW, popGet(AOP(IC_RESULT(ic)),offset+1,FALSE,FALSE));
636           }
637         }
638       }
639
640       l1 = lit & 0xff;
641       lit >>= 8;
642       offset++;
643     }
644 #endif
645
646   } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
647
648     pic14_emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
649     pic14_emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
650     pic14_emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
651
652     /* here we are adding a bit to a char or int */
653     if(size == 1) {
654       if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
655
656         emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
657         emitpcode(POC_INCF ,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
658
659         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
660                        AOP(IC_RIGHT(ic))->aopu.aop_dir,
661                        AOP(IC_RIGHT(ic))->aopu.aop_dir);
662         pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
663       } else {
664
665         if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
666           emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
667           emitpcode(POC_XORLW , popGetLit(1));
668
669           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
670                          AOP(IC_RIGHT(ic))->aopu.aop_dir,
671                          AOP(IC_RIGHT(ic))->aopu.aop_dir);
672           pic14_emitcode(" xorlw","1");
673         } else {
674           emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
675           emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
676           emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
677
678           pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
679           pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
680                          AOP(IC_RIGHT(ic))->aopu.aop_dir,
681                          AOP(IC_RIGHT(ic))->aopu.aop_dir);
682           pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
683         }
684           
685         if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
686             
687           if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
688             emitpcode(POC_ANDLW , popGetLit(1));
689             emitpcode(POC_BCF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
690             emitSKPZ;
691             emitpcode(POC_BSF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
692           } else {
693             emitpcode(POC_MOVWF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
694             pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
695           }
696         }
697       }
698
699     } else {
700       int offset = 1;
701
702       if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
703         emitCLRZ;
704         emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
705         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
706
707         pic14_emitcode("clrz","");
708
709         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
710                        AOP(IC_RIGHT(ic))->aopu.aop_dir,
711                        AOP(IC_RIGHT(ic))->aopu.aop_dir);
712         pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
713
714       } else {
715
716         emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
717         emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
718         emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
719         emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
720
721
722         pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
723         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
724                        AOP(IC_RIGHT(ic))->aopu.aop_dir,
725                        AOP(IC_RIGHT(ic))->aopu.aop_dir);
726         pic14_emitcode(" incf","%s,w", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
727         pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
728
729       }
730
731       while(--size){
732         emitSKPZ;
733         emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
734         //pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
735       }
736
737     }
738       
739   } else {
740     
741     if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
742       emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
743       emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
744     } else {
745
746       if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
747         emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
748         if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
749           emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
750       } else {
751
752         emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
753
754         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
755           emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
756         else {
757           if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
758               (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
759             emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
760           } else {
761             emitpcode(POC_ADDFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
762             if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
763               emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
764           }
765         }
766       }
767     }
768
769     offset = 1;
770     size--;
771
772     while(size--){
773       if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
774         emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
775         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
776
777         pic14_emitcode("movf","%s,w",  aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
778         pic14_emitcode("movwf","%s",  aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
779       }
780
781       emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
782       emitSKPNC;
783       emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
784       emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
785
786       /*
787         pic14_emitcode("movf","%s,w",  aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
788         emitSKPNC;
789         pic14_emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
790         pic14_emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
791       */
792
793       offset++;
794     }
795
796   }
797
798   //adjustArithmeticResult(ic);
799
800  release:
801   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
802   freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
803   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
804 }
805
806 /*-----------------------------------------------------------------*/
807 /* genMinusDec :- does subtraction with decrement if possible     */
808 /*-----------------------------------------------------------------*/
809 bool genMinusDec (iCode *ic)
810 {
811     unsigned int icount ;
812     unsigned int size = pic14_getDataSize(IC_RESULT(ic));
813
814     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
815     /* will try to generate an increment */
816     /* if the right side is not a literal 
817     we cannot */
818     if ((AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) || 
819         (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) || 
820         (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) )
821         return FALSE ;
822
823     DEBUGpic14_emitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
824
825     /* if the literal value of the right hand side
826     is greater than 4 then it is not worth it */
827     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
828         return FALSE ;
829
830     /* if decrement 16 bits in register */
831     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
832         (size > 1) &&
833         (icount == 1)) {
834
835       if(size == 2) { 
836         emitpcode(POC_DECF,    popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
837         emitpcode(POC_INCFSZW, popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
838         emitpcode(POC_INCF,    popGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
839         emitpcode(POC_DECF,    popGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
840
841         pic14_emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
842         pic14_emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
843         pic14_emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
844       } else {
845         /* size is 3 or 4 */
846         emitpcode(POC_MOVLW,  popGetLit(0xff));
847         emitpcode(POC_ADDWF,  popGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
848         emitSKPNC;
849         emitpcode(POC_ADDWF,  popGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
850         emitSKPNC;
851         emitpcode(POC_ADDWF,  popGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
852
853         pic14_emitcode("movlw","0xff");
854         pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
855
856         emitSKPNC;
857         pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
858         emitSKPNC;
859         pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
860
861         if(size > 3) {
862           emitSKPNC;
863           emitpcode(POC_ADDWF,  popGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
864
865           pic14_emitcode("skpnc","");
866           emitSKPNC;
867           pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
868         }
869
870       }
871
872       return TRUE;
873
874     }
875
876     /* if the sizes are greater than 1 then we cannot */
877     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
878         AOP_SIZE(IC_LEFT(ic)) > 1   )
879         return FALSE ;
880
881     /* we can if the aops of the left & result match or
882     if they are in registers and the registers are the
883     same */
884     if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
885
886       while (icount--) 
887         emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
888
889         //pic14_emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
890
891         return TRUE ;
892     }
893
894     DEBUGpic14_emitcode ("; returning"," result=%s, left=%s",
895                    aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
896                    aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
897     if(size==1) {
898
899       pic14_emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
900       pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
901
902       emitpcode(POC_DECFW,  popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
903       emitpcode(POC_MOVWF,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
904
905       return TRUE;
906     }
907
908     return FALSE ;
909 }
910
911 /*-----------------------------------------------------------------*/
912 /* addSign - complete with sign                                    */
913 /*-----------------------------------------------------------------*/
914 void addSign(operand *result, int offset, int sign)
915 {
916     int size = (pic14_getDataSize(result) - offset);
917     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
918     if(size > 0){
919         if(sign){
920             pic14_emitcode("rlc","a");
921             pic14_emitcode("subb","a,acc");
922             while(size--)
923                 aopPut(AOP(result),"a",offset++); 
924         } else
925             while(size--)
926                 aopPut(AOP(result),"#0",offset++);
927     }
928 }
929
930 /*-----------------------------------------------------------------*/
931 /* genMinusBits - generates code for subtraction  of two bits      */
932 /*-----------------------------------------------------------------*/
933 void genMinusBits (iCode *ic)
934 {
935     symbol *lbl = newiTempLabel(NULL);
936     DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
937     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
938         pic14_emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
939         pic14_emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
940         pic14_emitcode("cpl","c");
941         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
942         pic14_outBitC(IC_RESULT(ic));
943     }
944     else{
945         pic14_emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
946         pic14_emitcode("subb","a,acc");
947         pic14_emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
948         pic14_emitcode("inc","a");
949         pic14_emitcode("","%05d_DS_:",(lbl->key+100));
950         aopPut(AOP(IC_RESULT(ic)),"a",0);
951         addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
952     }
953 }
954
955 /*-----------------------------------------------------------------*/
956 /* genMinus - generates code for subtraction                       */
957 /*-----------------------------------------------------------------*/
958 void genMinus (iCode *ic)
959 {
960   int size, offset = 0;
961   unsigned long lit = 0L;
962
963   DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
964   aopOp (IC_LEFT(ic),ic,FALSE);
965   aopOp (IC_RIGHT(ic),ic,FALSE);
966   aopOp (IC_RESULT(ic),ic,TRUE);
967
968   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY  &&
969       AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
970     operand *t = IC_RIGHT(ic);
971     IC_RIGHT(ic) = IC_LEFT(ic);
972     IC_LEFT(ic) = t;
973   }
974
975   /* special cases :- */
976   /* if both left & right are in bit space */
977   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
978       AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
979     genPlusBits (ic);
980     goto release ;
981   }
982
983   /* if I can do an decrement instead
984      of subtract then GOOD for ME */
985   //  if (genMinusDec (ic) == TRUE)
986   //    goto release;   
987
988   size = pic14_getDataSize(IC_RESULT(ic));   
989
990   if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
991     /* Add a literal to something else */
992
993     lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
994     lit = - (long)lit;
995
996     genAddLit ( IC_RESULT(ic),IC_LEFT(ic),  lit);
997     
998 #if 0
999     /* add the first byte: */
1000     pic14_emitcode("movlw","0x%x", lit & 0xff);
1001     pic14_emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1002     emitpcode(POC_MOVLW,  popGetLit(lit & 0xff));
1003     emitpcode(POC_ADDWF,  popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1004
1005
1006     offset = 1;
1007     size--;
1008
1009     while(size-- > 0) {
1010
1011       lit >>= 8;
1012
1013       if(lit & 0xff) {
1014
1015         if((lit & 0xff) == 0xff) {
1016           emitpcode(POC_MOVLW,  popGetLit(0xff));
1017           emitSKPC;
1018           emitpcode(POC_ADDWF,  popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
1019         } else {
1020           emitpcode(POC_MOVLW,  popGetLit(lit & 0xff));
1021           emitSKPNC;
1022           emitpcode(POC_MOVLW,  popGetLit((lit+1) & 0xff));
1023           emitpcode(POC_ADDWF,  popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
1024         }
1025
1026       } else {
1027         /* do the rlf known zero trick here */
1028         emitpcode(POC_MOVLW,  popGetLit(1));
1029         emitSKPNC;
1030         emitpcode(POC_ADDWF,  popGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
1031       }
1032       offset++;
1033     }
1034 #endif
1035   } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1036     // bit subtraction
1037
1038     pic14_emitcode(";bitsub","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1039     pic14_emitcode(";bitsub","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1040     pic14_emitcode(";bitsub","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1041
1042     /* here we are subtracting a bit from a char or int */
1043     if(size == 1) {
1044       if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1045
1046         emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1047         emitpcode(POC_DECF ,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1048
1049         pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
1050                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
1051                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
1052         pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1053       } else {
1054
1055         if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1056           emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1057           emitpcode(POC_XORLW , popGetLit(1));
1058         }else  if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
1059               (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1060
1061           lit = (unsigned long)floatFromVal(AOP(IC_LEFT(ic))->aopu.aop_lit);
1062
1063           if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1064             if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
1065               if(lit & 1) {
1066                 emitpcode(POC_MOVLW , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1067                 emitpcode(POC_XORWF , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1068               }
1069             }else{
1070               emitpcode(POC_BCF ,     popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1071               if(lit & 1) 
1072                 emitpcode(POC_BTFSS , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1073               else
1074                 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1075               emitpcode(POC_BSF ,     popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1076             }
1077             goto release;
1078           } else {
1079             emitpcode(POC_MOVLW , popGetLit(lit & 0xff));
1080             emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1081             emitpcode(POC_MOVLW , popGetLit((lit-1) & 0xff));
1082             emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1083
1084           }
1085
1086         } else {
1087           emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1088           emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1089           emitpcode(POC_DECFW , popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1090         }
1091           
1092         if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
1093             
1094           emitpcode(POC_MOVWF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1095
1096         } else  {
1097           emitpcode(POC_ANDLW , popGetLit(1));
1098 /*
1099           emitpcode(POC_BCF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1100           emitSKPZ;
1101           emitpcode(POC_BSF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1102 */
1103         }
1104
1105       }
1106
1107     }
1108   } else {
1109
1110     if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
1111       DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1112       emitpcode(POC_SUBFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1113       emitpcode(POC_SUBLW, popGetLit(0));
1114       emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1115     } else {
1116
1117       if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1118         emitpcode(POC_SUBFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1119         emitpcode(POC_SUBLW, popGetLit(0));
1120         if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
1121           emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1122       } else {
1123
1124         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1125         if(AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC) 
1126           emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1127
1128         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1129           emitpcode(POC_SUBWF, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1130         else {
1131           if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
1132               (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1133             emitpcode(POC_SUBLW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1134           } else {
1135             emitpcode(POC_SUBFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1136           }
1137           if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
1138             if ( AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1139               emitpcode(POC_BCF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1140               emitSKPZ;
1141               emitpcode(POC_BSF ,   popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1142             }else
1143               emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1144           }
1145         }
1146       }
1147     }
1148
1149     /*
1150       emitpcode(POC_MOVFW,  popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1151
1152       if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1153       emitpcode(POC_SUBFW,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1154       } else {
1155       emitpcode(POC_SUBFW,  popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1156       emitpcode(POC_MOVWF,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1157       }
1158     */
1159     offset = 1;
1160     size--;
1161
1162     while(size--){
1163       if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1164         emitpcode(POC_MOVFW,  popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1165         emitpcode(POC_MOVWF,  popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1166       }
1167       emitpcode(POC_MOVFW,  popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
1168       emitSKPNC;
1169       emitpcode(POC_INCFSZW,popGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
1170       emitpcode(POC_SUBWF,  popGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
1171
1172       offset++;
1173     }
1174
1175   }
1176
1177
1178   //    adjustArithmeticResult(ic);
1179         
1180  release:
1181   freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1182   freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1183   freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1184 }
1185
1186