1 /*-------------------------------------------------------------------------
2   genarith.c - source file for code generation - arithmetic
3 
4   Copyright (C) 1998, Sandeep Dutta . sandeep.dutta@usa.net
5   Copyright (C) 1999, Jean-Louis VERN.jlvern@writeme.com
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port:
8   Copyright (C) 2000, Scott Dattalo scott@dattalo.com
9   PIC16 port:
10   Copyright (C) 2002, Martin Dubuc m.dubuc@rogers.com
11 
12   This program is free software; you can redistribute it and/or modify it
13   under the terms of the GNU General Public License as published by the
14   Free Software Foundation; either version 2, or (at your option) any
15   later version.
16 
17   This program is distributed in the hope that it will be useful,
18   but WITHOUT ANY WARRANTY; without even the implied warranty of
19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20   GNU General Public License for more details.
21 
22   You should have received a copy of the GNU General Public License
23   along with this program; if not, write to the Free Software
24   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 -------------------------------------------------------------------------*/
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 #include "common.h"
40 #include "SDCCpeeph.h"
41 #include "ralloc.h"
42 #include "pcode.h"
43 #include "gen.h"
44 
45 #if 1
46 #define pic16_emitcode  DEBUGpic16_emitcode
47 #endif
48 
49 extern void pic16_emitpLabelFORCE(int key);
50 
51 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
52 
53 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result);
54 void pic16_emitpcomment(char *, ...);
55 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst);
pic16_AopType(short type)56 const char *pic16_AopType(short type)
57 {
58   switch(type) {
59   case AOP_LIT:         return "AOP_LIT";
60   case AOP_REG:         return "AOP_REG";
61   case AOP_DIR:         return "AOP_DIR";
62   case AOP_STK:         return "AOP_STK";
63   case AOP_STR:         return "AOP_STR";
64   case AOP_CRY:         return "AOP_CRY";
65   case AOP_ACC:         return "AOP_ACC";
66   case AOP_PCODE:       return "AOP_PCODE";
67   case AOP_STA:         return "AOP_STA";
68   }
69 
70   return "BAD TYPE";
71 }
72 
pic16_pCodeOpType(pCodeOp * pcop)73 const char *pic16_pCodeOpType(pCodeOp *pcop)
74 {
75 
76   if(pcop) {
77 
78     switch(pcop->type) {
79 
80     case PO_NONE:               return "PO_NONE";
81     case PO_W:                  return  "PO_W";
82     case PO_WREG:               return  "PO_WREG";
83     case PO_STATUS:             return  "PO_STATUS";
84     case PO_BSR:                return  "PO_BSR";
85     case PO_FSR0:               return  "PO_FSR0";
86     case PO_INDF0:              return  "PO_INDF0";
87     case PO_INTCON:             return  "PO_INTCON";
88     case PO_GPR_REGISTER:       return  "PO_GPR_REGISTER";
89     case PO_GPR_BIT:            return  "PO_GPR_BIT";
90     case PO_GPR_TEMP:           return  "PO_GPR_TEMP";
91     case PO_SFR_REGISTER:       return  "PO_SFR_REGISTER";
92     case PO_PCL:                return  "PO_PCL";
93     case PO_PCLATH:             return  "PO_PCLATH";
94     case PO_PCLATU:             return  "PO_PCLATU";
95     case PO_PRODL:              return  "PO_PRODL";
96     case PO_PRODH:              return  "PO_PRODH";
97     case PO_LITERAL:            return  "PO_LITERAL";
98     case PO_REL_ADDR:           return "PO_REL_ADDR";
99     case PO_IMMEDIATE:          return  "PO_IMMEDIATE";
100     case PO_DIR:                return  "PO_DIR";
101     case PO_CRY:                return  "PO_CRY";
102     case PO_BIT:                return  "PO_BIT";
103     case PO_STR:                return  "PO_STR";
104     case PO_LABEL:              return  "PO_LABEL";
105     case PO_WILD:               return  "PO_WILD";
106     case PO_TWO_OPS:            return  "PO_TWO_OPS";
107     }
108   }
109 
110   return "BAD PO_TYPE";
111 }
112 
pic16_pCodeOpSubType(pCodeOp * pcop)113 const char *pic16_pCodeOpSubType(pCodeOp *pcop)
114 {
115 
116   if(pcop && (pcop->type == PO_GPR_BIT)) {
117 
118     switch(PCORB(pcop)->subtype) {
119 
120     case PO_NONE:               return "PO_NONE";
121     case PO_W:                  return  "PO_W";
122     case PO_WREG:               return  "PO_WREG";
123     case PO_STATUS:             return  "PO_STATUS";
124     case PO_BSR:                return  "PO_BSR";
125     case PO_FSR0:               return  "PO_FSR0";
126     case PO_INDF0:              return  "PO_INDF0";
127     case PO_INTCON:             return  "PO_INTCON";
128     case PO_GPR_REGISTER:       return  "PO_GPR_REGISTER";
129     case PO_GPR_BIT:            return  "PO_GPR_BIT";
130     case PO_GPR_TEMP:           return  "PO_GPR_TEMP";
131     case PO_SFR_REGISTER:       return  "PO_SFR_REGISTER";
132     case PO_PCL:                return  "PO_PCL";
133     case PO_PCLATH:             return  "PO_PCLATH";
134     case PO_PCLATU:             return  "PO_PCLATU";
135     case PO_PRODL:              return  "PO_PRODL";
136     case PO_PRODH:              return  "PO_PRODH";
137     case PO_LITERAL:            return  "PO_LITERAL";
138     case PO_REL_ADDR:           return "PO_REL_ADDR";
139     case PO_IMMEDIATE:          return  "PO_IMMEDIATE";
140     case PO_DIR:                return  "PO_DIR";
141     case PO_CRY:                return  "PO_CRY";
142     case PO_BIT:                return  "PO_BIT";
143     case PO_STR:                return  "PO_STR";
144     case PO_LABEL:              return  "PO_LABEL";
145     case PO_WILD:               return  "PO_WILD";
146     case PO_TWO_OPS:            return  "PO_TWO_OPS";
147     }
148   }
149 
150   return "BAD PO_TYPE";
151 }
152 
153 /*-----------------------------------------------------------------*/
154 /* pic16_genPlusIncr :- does addition with increment if possible         */
155 /*-----------------------------------------------------------------*/
pic16_genPlusIncr(iCode * ic)156 bool pic16_genPlusIncr (iCode *ic)
157 {
158   unsigned int icount;
159   unsigned int size = pic16_getDataSize(IC_RESULT(ic));
160 
161     FENTRY;
162 
163     DEBUGpic16_emitcode ("; ","result %s, left %s, right %s",
164                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
165                          pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
166                          pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
167 
168     /* will try to generate an increment */
169     /* if the right side is not a literal
170        we cannot */
171     if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
172       {
173         return FALSE;
174       }
175 
176     DEBUGpic16_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
177     /* if the literal value of the right hand side
178        is greater than 2 then it is faster to add */
179     if ((icount = (unsigned int)ulFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
180       {
181         return FALSE;
182       }
183 
184     /* if increment 16 bits in register */
185     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) && icount == 1)
186       {
187         int offset = LSB;
188 
189         switch (size)
190           {
191           case 2:
192             pic16_emitpcode(POC_INFSNZ, pic16_popGet(AOP(IC_RESULT(ic)), offset++));
193           case 1:
194             pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), offset));
195             break;
196 
197           default:
198             {
199               symbol *inclbl = newiTempLabel(NULL);
200               pCodeOp *pcop_lbl = pic16_popGetLabel(inclbl->key);
201               int label_use = 0;
202 
203               size -= 2;
204               if (size)
205                 {
206                   label_use = 1;
207                 }
208 
209               while (size--)
210                 {
211                   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), offset++));
212                   pic16_emitpcode(POC_BNC, pcop_lbl);
213                 }
214 
215               pic16_emitpcode(POC_INFSNZ, pic16_popGet(AOP(IC_RESULT(ic)), offset++));
216               pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)), offset));
217 
218               if (label_use)
219                 {
220                   pic16_emitpLabelFORCE(inclbl->key);
221                 }
222             }
223         } // switch (size)
224 
225       return TRUE;
226     }
227 
228 //    DEBUGpic16_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
229     /* if left is in accumulator  - probably a bit operation*/                          // VR - why this is a bit operation?!
230     if( (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) &&
231         (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
232 
233       pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
234       if(icount)
235         pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
236       //pic16_emitcode("xorlw","1");
237       else
238         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
239       //pic16_emitcode("andlw","1");
240 
241       emitSKPZ;
242       pic16_emitpcode(POC_BSF, pic16_popGet(AOP(IC_RESULT(ic)),0));
243 
244       return TRUE;
245     }
246 
247 
248     /* if the sizes are greater than 1 then we cannot */
249     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
250         AOP_SIZE(IC_LEFT(ic)) > 1   )
251         return FALSE ;
252 
253     /* If we are incrementing the same register by two: */
254 
255     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
256 
257       while (icount--)
258         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
259       //pic16_emitcode("incf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
260 
261       return TRUE ;
262     }
263 
264     DEBUGpic16_emitcode ("; ","couldn't increment ");
265 
266     return FALSE ;
267 }
268 
269 /*-----------------------------------------------------------------*/
270 /* pic16_outBitAcc - output a bit in acc                                 */
271 /*-----------------------------------------------------------------*/
pic16_outBitAcc(operand * result)272 void pic16_outBitAcc(operand *result)
273 {
274     symbol *tlbl = newiTempLabel(NULL);
275     /* if the result is a bit */
276     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
277 
278     assert(0); // not implemented for PIC16?
279 
280     if (AOP_TYPE(result) == AOP_CRY){
281         pic16_aopPut(AOP(result),"a",0);
282     }
283     else {
284         pic16_emitcode("jz","%05d_DS_",tlbl->key+100);
285         pic16_emitcode("mov","a,#01");
286         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
287         pic16_outAcc(result);
288     }
289 }
290 
291 /*-----------------------------------------------------------------*/
292 /* pic16_genPlusBits - generates code for addition of two bits           */
293 /*-----------------------------------------------------------------*/
pic16_genPlusBits(iCode * ic)294 void pic16_genPlusBits (iCode *ic)
295 {
296   FENTRY;
297 
298   DEBUGpic16_emitcode ("; ","result %s, left %s, right %s",
299                        pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
300                        pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
301                        pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
302   /*
303     The following block of code will add two bits.
304     Note that it'll even work if the destination is
305     the carry (C in the status register).
306     It won't work if the 'Z' bit is a source or destination.
307   */
308 
309   /* If the result is stored in the accumulator (w) */
310   //if(strcmp(pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),"a") == 0 ) {
311   switch(AOP_TYPE(IC_RESULT(ic))) {
312   case AOP_ACC:
313     pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
314     pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
315     pic16_emitpcode(POC_XORLW, pic16_popGetLit(1));
316     pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
317     pic16_emitpcode(POC_XORLW, pic16_popGetLit(1));
318     break;
319   case AOP_REG:
320     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
321     pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
322     pic16_emitpcode(POC_XORLW, pic16_popGetLit(1));
323     pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
324     pic16_emitpcode(POC_XORLW, pic16_popGetLit(1));
325     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
326     break;
327   default:
328     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_RESULT(ic)),0));
329     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
330     pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
331     pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
332     pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
333     pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
334     break;
335   }
336 
337 }
338 
339 #if 0
340 /* This is the original version of this code.
341  *
342  * This is being kept around for reference,
343  * because I am not entirely sure I got it right...
344  */
345 static void adjustArithmeticResult(iCode *ic)
346 {
347     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
348         AOP_SIZE(IC_LEFT(ic)) == 3   &&
349         !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
350         pic16_aopPut(AOP(IC_RESULT(ic)),
351                pic16_aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
352                2);
353 
354     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
355         AOP_SIZE(IC_RIGHT(ic)) == 3   &&
356         !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
357         pic16_aopPut(AOP(IC_RESULT(ic)),
358                pic16_aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
359                2);
360 
361     if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
362         AOP_SIZE(IC_LEFT(ic)) < 3    &&
363         AOP_SIZE(IC_RIGHT(ic)) < 3   &&
364         !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
365         !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
366         char buffer[5];
367         SNPRINTF(buffer, sizeof(buffer), "#%d", pointerCode(getSpec(operandType(IC_LEFT(ic)))));
368         pic16_aopPut(AOP(IC_RESULT(ic)),buffer,2);
369     }
370 }
371 //#else
372 /* This is the pure and virtuous version of this code.
373  * I'm pretty certain it's right, but not enough to toss the old
374  * code just yet...
375  */
376 static void adjustArithmeticResult(iCode *ic)
377 {
378     if (opIsGptr(IC_RESULT(ic)) &&
379         opIsGptr(IC_LEFT(ic))   &&
380         !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
381     {
382         pic16_aopPut(AOP(IC_RESULT(ic)),
383                pic16_aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
384                GPTRSIZE - 1);
385     }
386 
387     if (opIsGptr(IC_RESULT(ic)) &&
388         opIsGptr(IC_RIGHT(ic))   &&
389         !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
390     {
391         pic16_aopPut(AOP(IC_RESULT(ic)),
392                pic16_aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
393                GPTRSIZE - 1);
394     }
395 
396     if (opIsGptr(IC_RESULT(ic))            &&
397         AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
398         AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
399          !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
400          !pic16_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
401          char buffer[5];
402 
403          SNPRINTF(buffer, sizeof(buffer), "#%d", pointerCode(getSpec(operandType(IC_LEFT(ic)))));
404          pic16_aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
405      }
406 }
407 #endif
408 
409 #if 1
410 /*-----------------------------------------------------------------*/
411 /* genAddlit - generates code for addition                         */
412 /*-----------------------------------------------------------------*/
genAddLit2byte(operand * result,int offr,int lit)413 static void genAddLit2byte (operand *result, int offr, int lit)
414 {
415   FENTRY;
416 
417   switch(lit & 0xff)
418     {
419     case 0:
420       break;
421 
422     case 1:
423       pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offr));
424       break;
425 
426     case 0xff:
427       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
428       break;
429 
430     default:
431       {
432         int resultIsWREG = (AOP_TYPE(result) != AOP_STA && ! strcmp(pic16_aopGet(AOP(result), 0, TRUE, FALSE), "WREG"));
433 
434         if (resultIsWREG)
435           {
436             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(lit & 0xff));
437           }
438         else
439           {
440             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit & 0xff));
441             pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
442           }
443       }
444     }
445 }
446 #endif
447 
emitMOVWF(operand * reg,int offset)448 static void emitMOVWF(operand *reg, int offset)
449 {
450   if(!reg)
451     return;
452 
453   if (AOP_TYPE(reg) == AOP_ACC) {
454     DEBUGpic16_emitcode ("; ***","%s  %d ignoring mov into W",__FUNCTION__,__LINE__);
455     return;
456   }
457 
458   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(reg),offset));
459 
460 }
461 
462 
463 #if 1
464 
genAddLit(iCode * ic,int lit)465 static void genAddLit (iCode *ic, int lit)
466 {
467 
468   int size,same;
469   int lo, offset;
470 
471   operand *result;
472   operand *left;
473 
474   FENTRY;
475 
476   left = IC_LEFT(ic);
477   result = IC_RESULT(ic);
478   same = pic16_sameRegs(AOP(left), AOP(result));
479   size = pic16_getDataSize(result);
480 
481   if ((AOP_PCODE == AOP_TYPE(left))
482           && (PO_IMMEDIATE == AOP(left)->aopu.pcop->type))
483   {
484       /* see #1888004 for an example case for this */
485       for (offset = 0; offset < size; offset++) {
486           pic16_emitpcode(POC_MOVLW, pic16_newpCodeOpImmd(AOP(left)->aopu.pcop->name,
487                   offset, PCOI(AOP(left)->aopu.pcop)->index + lit, 0));
488           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
489       } // for
490       return;
491   } // if
492 
493   if(same) {
494 
495     /* Handle special cases first */
496     if(size == 1)
497       genAddLit2byte (result, 0, lit);
498 
499     else if(size == 2) {
500       int hi = 0xff & (lit >> 8);
501       lo = lit & 0xff;
502 
503       switch(hi) {
504       case 0:
505 
506         /* lit = 0x00LL */
507         DEBUGpic16_emitcode ("; hi = 0","%s  %d",__FUNCTION__,__LINE__);
508         switch(lo) {
509         case 0:
510           break;
511 
512         case 1:
513           pic16_emitpcode(POC_INFSNZ, pic16_popGet(AOP(result),0));
514           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
515           break;
516 
517         case 0xff:
518           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0));
519           pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
520           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
521 
522           break;
523         default:
524           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
525           pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
526           emitSKPNC;
527           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
528         }
529         break;
530 
531       case 1:
532         /* lit = 0x01LL */
533         DEBUGpic16_emitcode ("; hi = 1","%s  %d",__FUNCTION__,__LINE__);
534         switch(lo) {
535         case 0:  /* 0x0100 */
536           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
537           break;
538         case 1:  /* 0x0101  */
539           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
540           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
541           emitSKPNZ;
542           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
543           break;
544         case 0xff: /* 0x01ff */
545           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0));
546           pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
547           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
548           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
549           break;
550         default: /* 0x01LL */
551           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
552           pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
553           emitSKPNC;
554           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
555           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
556         }
557         break;
558 
559       case 0xff:
560         DEBUGpic16_emitcode ("; hi = ff","%s  %d",__FUNCTION__,__LINE__);
561         /* lit = 0xffLL */
562         switch(lo) {
563         case 0:  /* 0xff00 */
564           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
565           break;
566         case 1:  /*0xff01 */
567           pic16_emitpcode(POC_INCFSZ, pic16_popGet(AOP(result),0));
568           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
569           break;
570 
571         case 0xff: /* 0xffff */
572           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lo));
573           pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
574           pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),MSB16));
575           break;
576 
577         default:
578           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
579           pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
580           emitSKPC;
581           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
582 
583         }
584 
585         break;
586 
587       default:
588         DEBUGpic16_emitcode ("; hi is generic","%d   %s  %d",hi,__FUNCTION__,__LINE__);
589 
590         /* lit = 0xHHLL */
591         switch(lo) {
592         case 0:  /* 0xHH00 */
593           genAddLit2byte (result, MSB16, hi);
594           break;
595         case 1:  /* 0xHH01 */
596           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
597           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
598           pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
599           break;
600 /*      case 0xff: * 0xHHff *
601           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0,FALSE,FALSE));
602           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
603           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
604           pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
605           break;
606 */      default:  /* 0xHHLL */
607           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
608           pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
609           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
610           pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
611           break;
612         }
613 
614       }
615     } else {
616       int carry_info = 0;
617       int prev_W = -1;
618       /* size > 2 */
619       DEBUGpic16_emitcode (";  add lit to long","%s  %d",__FUNCTION__,__LINE__);
620 
621       offset = 0;
622       while (size--)
623         {
624         lo = BYTEofLONG(lit,0);
625 
626         if (carry_info)
627           {
628             if (prev_W != (lo & 0xFF))
629               {
630                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lo));
631                 prev_W = lo & 0xFF;
632               }
633 
634             pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset));
635           }
636         else {
637           /* no carry info from previous step */
638           /* this means this is the first time to add */
639           switch (lo)
640             {
641             case 0:
642               break;
643 
644             case 1:
645               pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset));
646               carry_info = 1;
647               break;
648 
649             default:
650               {
651                 if (prev_W != (lo & 0xFF))
652                   {
653                     pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lo));
654                     prev_W = lo & 0xFF;
655                   }
656 
657                 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
658 
659                 if (lit < 0x100)
660                   carry_info = 3;  /* Were adding only one byte and propogating the carry. */
661                 else
662                   carry_info = 2;
663                 break;
664               }
665             }
666         }
667         offset++;
668         lit >>= 8;
669       }
670 
671 /*
672       lo = BYTEofLONG(lit,0);
673 
674       if(lit < 0x100) {
675         if(lo) {
676           if(lo == 1) {
677             pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0,FALSE,FALSE));
678             emitSKPNZ;
679           } else {
680             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
681             pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
682             emitSKPNC;
683           }
684           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),1,FALSE,FALSE));
685           emitSKPNZ;
686           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),2,FALSE,FALSE));
687           emitSKPNZ;
688           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),3,FALSE,FALSE));
689 
690         }
691       }
692 
693 */
694     }
695   } else {
696     int offset = 1;
697     DEBUGpic16_emitcode (";  left and result aren't same","%s  %d",__FUNCTION__,__LINE__);
698 
699     if(size == 1) {
700 
701       if(AOP_TYPE(left) == AOP_ACC) {
702         /* left addend is already in accumulator */
703         switch(lit & 0xff) {
704         case 0:
705           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
706           emitMOVWF(result,0);
707           break;
708         default:
709           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(lit & 0xff));
710           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
711           emitMOVWF(result,0);
712         }
713       } else {
714         /* left addend is in a register */
715         switch(lit & 0xff) {
716         case 0:
717           pic16_mov2w(AOP(left),0);
718           emitMOVWF(result, 0);
719           break;
720         case 1:
721           pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0));
722           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
723           emitMOVWF(result,0);
724           break;
725         case 0xff:
726           pic16_emitpcode(POC_DECFW, pic16_popGet(AOP(left),0));
727           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
728           emitMOVWF(result,0);
729           break;
730         default:
731           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
732           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
733           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
734           emitMOVWF(result,0);
735         }
736       }
737 
738 //    } else if (pic16_isLitAop(AOP(left))) {
739 //      // adding two literals
740 //      assert ( !"adding two literals is not yet supported" );
741     } else {
742       int clear_carry=0;
743 
744       /* left is not the accumulator */
745       if(lit & 0xff) {
746         pic16_mov2w(AOP(left),0);
747         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(lit & 0xff));
748       } else {
749         pic16_mov2w(AOP(left),0);
750         /* We don't know the state of the carry bit at this point */
751         clear_carry = 1;
752       }
753       //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
754       emitMOVWF(result,0);
755       while(--size) {
756         lit >>= 8;
757         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
758         if (offset < AOP_SIZE(left)) {
759           pic16_emitpcode(clear_carry ? POC_ADDFW : POC_ADDFWC, pic16_popGet(AOP(left),offset));
760           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
761         } else {
762           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
763           if (!SPEC_USIGN(operandType(IC_LEFT(ic)))) {
764             /* sign-extend left (in result) */
765             pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left),AOP_SIZE(left)-1,7));
766             pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
767           }
768           pic16_emitpcode(clear_carry ? POC_ADDWF : POC_ADDWFC, pic16_popGet(AOP(result),offset));
769         }
770         clear_carry = 0;
771         offset++;
772       }
773     }
774   }
775 }
776 
777 #else
778     /* this fails when result is an SFR because value is written there
779      * during addition and not at the end */
780 
genAddLit(iCode * ic,int lit)781 static void genAddLit (iCode *ic, int lit)
782 {
783 
784   int size,sizeL,same;
785   int i, llit, prev_W;
786 
787   operand *result;
788   operand *left;
789 
790     FENTRY;
791 
792 
793   left = IC_LEFT(ic);
794   result = IC_RESULT(ic);
795   same = pic16_sameRegs(AOP(left), AOP(result));
796   size = pic16_getDataSize(result);
797   sizeL = pic16_getDataSize(left);
798   llit = lit;
799 
800 #define MIN(a,b)        (((a) < (b)) ? (a) : (b))
801   /* move left to result -- possibly sign extend */
802   for (i=0; i < MIN(size, sizeL); i++) {
803     pic16_mov2f (AOP(result), AOP(left), i);
804   } // for i
805 #undef MIN
806 
807   /* extend to result size */
808   pic16_addSign(result, sizeL, !IS_UNSIGNED(operandType(left)));
809 
810   /* special cases */
811   if (lit == 0) {
812     /* nothing to do */
813   } else if (lit == 1) {
814     switch (size) {
815     case 1:
816       /* handled below */
817       break;
818     case 2:
819       pic16_emitpcode (POC_INFSNZ, pic16_popGet (AOP(result), 0));
820       break;
821     default:
822       assert (size > 2);
823       pic16_emitpcode (POC_INCF, pic16_popGet(AOP(result), 0));
824       for (i=1; i < size-1; i++) {
825         emitSKPNC; /* a jump here saves up to 2(size-2)cycles */
826         pic16_emitpcode (POC_INCF, pic16_popGet(AOP(result), i));
827       } // for i
828       emitSKPNC;
829       break;
830     } // switch
831 
832     pic16_emitpcode (POC_INCF, pic16_popGet (AOP(result), size-1));
833   } else {
834     /* general case */
835 
836     /* add literal to result */
837     prev_W = -1;
838     for (i = 0; i < size; i++)
839       {
840         if (prev_W != (llit & 0xFF))
841           {
842             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(llit));
843             prev_W = llit & 0xFF;
844           }
845 
846         llit >>= 8; /* FIXME: arithmetic right shift for signed literals? */
847         pic16_emitpcode(i == 0 ? POC_ADDWF : POC_ADDWFC, pic16_popGet(AOP(result), i));
848       }
849   }
850 
851 #if 0
852 
853   if(same) {
854 
855     /* Handle special cases first */
856     if(size == 1)
857       genAddLit2byte (result, 0, lit);
858 
859     else if(size == 2) {
860       int hi = 0xff & (lit >> 8);
861       lo = lit & 0xff;
862 
863       switch(hi) {
864       case 0:
865 
866         /* lit = 0x00LL */
867         DEBUGpic16_emitcode ("; hi = 0","%s  %d",__FUNCTION__,__LINE__);
868         switch(lo) {
869         case 0:
870           break;
871         case 1:
872           pic16_emitpcode(POC_INFSNZ, pic16_popGet(AOP(result),0));
873           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
874           break;
875         case 0xff:
876           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0));
877           pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
878           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
879 
880           break;
881         default:
882           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
883           pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
884           emitSKPNC;
885           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
886 
887 
888         }
889         break;
890 
891       case 1:
892         /* lit = 0x01LL */
893         DEBUGpic16_emitcode ("; hi = 1","%s  %d",__FUNCTION__,__LINE__);
894         switch(lo) {
895         case 0:  /* 0x0100 */
896           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
897           break;
898         case 1:  /* 0x0101  */
899           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
900           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
901           emitSKPNZ;
902           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
903           break;
904         case 0xff: /* 0x01ff */
905           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0));
906           pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
907           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
908           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
909           break;
910         default: /* 0x01LL */
911           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
912           pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
913           emitSKPNC;
914           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
915           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
916         }
917         break;
918 
919       case 0xff:
920         DEBUGpic16_emitcode ("; hi = ff","%s  %d",__FUNCTION__,__LINE__);
921         /* lit = 0xffLL */
922         switch(lo) {
923         case 0:  /* 0xff00 */
924           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
925           break;
926         case 1:  /*0xff01 */
927           pic16_emitpcode(POC_INCFSZ, pic16_popGet(AOP(result),0));
928           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
929           break;
930 /*      case 0xff: * 0xffff *
931           pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0,FALSE,FALSE));
932           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
933           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0,FALSE,FALSE));
934           break;
935 */
936         default:
937           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
938           pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
939           emitSKPC;
940           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
941 
942         }
943 
944         break;
945 
946       default:
947         DEBUGpic16_emitcode ("; hi is generic","%d   %s  %d",hi,__FUNCTION__,__LINE__);
948 
949         /* lit = 0xHHLL */
950         switch(lo) {
951         case 0:  /* 0xHH00 */
952           genAddLit2byte (result, MSB16, hi);
953           break;
954         case 1:  /* 0xHH01 */
955           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
956           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
957           pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
958           break;
959 /*      case 0xff: * 0xHHff *
960           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0,FALSE,FALSE));
961           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
962           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
963           pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
964           break;
965 */      default:  /* 0xHHLL */
966           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
967           pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
968           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
969           pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
970           break;
971         }
972 
973       }
974     } else {
975       int carry_info = 0;
976       int offset = 0;
977       /* size > 2 */
978       DEBUGpic16_emitcode (";  add lit to long","%s  %d",__FUNCTION__,__LINE__);
979 
980       while(size--) {
981         lo = BYTEofLONG(lit,0);
982 
983         if(carry_info) {
984           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
985           pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset));
986         }else {
987           /* no carry info from previous step */
988           /* this means this is the first time to add */
989           switch(lo) {
990           case 0:
991             break;
992           case 1:
993             pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset));
994             carry_info=1;
995             break;
996           default:
997             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
998             pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
999             if(lit <0x100)
1000               carry_info = 3;  /* Were adding only one byte and propogating the carry */
1001             else
1002               carry_info = 2;
1003             break;
1004           }
1005         }
1006         offset++;
1007         lit >>= 8;
1008       }
1009 
1010 /*
1011       lo = BYTEofLONG(lit,0);
1012 
1013       if(lit < 0x100) {
1014         if(lo) {
1015           if(lo == 1) {
1016             pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1017             emitSKPNZ;
1018           } else {
1019             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
1020             pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1021             emitSKPNC;
1022           }
1023           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),1,FALSE,FALSE));
1024           emitSKPNZ;
1025           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),2,FALSE,FALSE));
1026           emitSKPNZ;
1027           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),3,FALSE,FALSE));
1028 
1029         }
1030       }
1031 
1032 */
1033     }
1034   } else {
1035     int offset = 1;
1036     DEBUGpic16_emitcode (";  left and result aren't same","%s  %d",__FUNCTION__,__LINE__);
1037 
1038     if(size == 1) {
1039 
1040       if(AOP_TYPE(left) == AOP_ACC) {
1041         /* left addend is already in accumulator */
1042         switch(lit & 0xff) {
1043         case 0:
1044           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1045           emitMOVWF(result,0);
1046           break;
1047         default:
1048           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(lit & 0xff));
1049           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1050           emitMOVWF(result,0);
1051         }
1052       } else {
1053         /* left addend is in a register */
1054         switch(lit & 0xff) {
1055         case 0:
1056           pic16_mov2w(AOP(left),0);
1057           emitMOVWF(result, 0);
1058           break;
1059         case 1:
1060           pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0));
1061           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1062           emitMOVWF(result,0);
1063           break;
1064         case 0xff:
1065           pic16_emitpcode(POC_DECFW, pic16_popGet(AOP(left),0));
1066           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1067           emitMOVWF(result,0);
1068           break;
1069         default:
1070           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1071           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
1072           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1073           emitMOVWF(result,0);
1074         }
1075       }
1076 
1077     } else {
1078       int clear_carry=0;
1079 
1080       /* left is not the accumulator */
1081       if(lit & 0xff) {
1082         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1083         pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
1084       } else {
1085         pic16_mov2w(AOP(left),0);
1086         /* We don't know the state of the carry bit at this point */
1087         clear_carry = 1;
1088       }
1089       //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
1090       emitMOVWF(result,0);
1091       while(--size) {
1092 
1093         lit >>= 8;
1094         if(lit & 0xff) {
1095           if(clear_carry) {
1096             /* The ls byte of the lit must've been zero - that
1097                means we don't have to deal with carry */
1098 
1099             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1100             pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(left),offset));
1101             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
1102 
1103             clear_carry = 0;
1104 
1105           } else {
1106             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1107             pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),offset));
1108             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
1109           }
1110 
1111         } else {
1112           pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offset));
1113           pic16_mov2w(AOP(left),offset);
1114           pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset));
1115         }
1116         offset++;
1117       }
1118     }
1119   }
1120 #endif
1121 }
1122 
1123 #endif
1124 
1125 /*-----------------------------------------------------------------*/
1126 /* pic16_genPlus - generates code for addition                     */
1127 /*-----------------------------------------------------------------*/
pic16_genPlus(iCode * ic)1128 void pic16_genPlus (iCode *ic)
1129 {
1130   int i, size, offset = 0;
1131   operand *result, *left, *right;
1132 
1133     FENTRY;
1134 
1135     /* special cases :- */
1136         result = IC_RESULT(ic);
1137         left = IC_LEFT(ic);
1138         right = IC_RIGHT(ic);
1139         pic16_aopOp (left,ic,FALSE);
1140         pic16_aopOp (right,ic,FALSE);
1141         pic16_aopOp (result,ic,TRUE);
1142         DEBUGpic16_pic16_AopType(__LINE__,left, right, result);
1143         // pic16_DumpOp("(left)",left);
1144 
1145         /* if literal, literal on the right or
1146         if left requires ACC or right is already
1147         in ACC */
1148 
1149         if ( (AOP_TYPE(left) == AOP_LIT) || (pic16_sameRegs(AOP(right), AOP(result))) ) {
1150                 operand *t = right;
1151                 right = IC_RIGHT(ic) = left;
1152                 left = IC_LEFT(ic) = t;
1153         }
1154 
1155         /* if both left & right are in bit space */
1156         if (AOP_TYPE(left) == AOP_CRY &&
1157                 AOP_TYPE(right) == AOP_CRY) {
1158                 pic16_genPlusBits (ic);
1159                 goto release ;
1160         }
1161 
1162         /* if left in bit space & right literal */
1163         if (AOP_TYPE(left) == AOP_CRY &&
1164                 AOP_TYPE(right) == AOP_LIT) {
1165                 /* if result in bit space */
1166                 if(AOP_TYPE(result) == AOP_CRY){
1167                         if(ulFromVal (AOP(right)->aopu.aop_lit) != 0L) {
1168                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),0));
1169                                 if (!pic16_sameRegs(AOP(left), AOP(result)) )
1170                                         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
1171                                 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),0));
1172                         }
1173                 } else {
1174                         unsigned long lit = ulFromVal (AOP(right)->aopu.aop_lit);
1175                         size = pic16_getDataSize(result);
1176                         while (size--) {
1177                                 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
1178                                 pic16_emitpcode (POC_MOVLW, pic16_popGetLit ((lit >> (8*offset)) & 0xFF));
1179                                 pic16_emitpcode (POC_ADDWFC, pic16_popGet(AOP(result), offset++));
1180                                 //MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
1181                                 //pic16_emitcode("addc","a,#00  ;%d",__LINE__);
1182                                 //pic16_aopPut(AOP(result),"a",offset++);
1183                         }
1184                 }
1185         goto release ;
1186         } // left == CRY
1187 
1188         /* if I can do an increment instead
1189         of add then GOOD for ME */
1190         if (pic16_genPlusIncr (ic) == TRUE)
1191                 goto release;
1192 
1193         size = pic16_getDataSize(result);
1194 
1195         if(AOP(right)->type == AOP_LIT) {
1196                 /* Add a literal to something else */
1197                 //bool know_W=0;
1198                 unsigned lit = (unsigned) ulFromVal (AOP(right)->aopu.aop_lit);
1199                 //unsigned l1=0;
1200 
1201                 //offset = 0;
1202                 DEBUGpic16_emitcode(";","adding lit to something. size %d",size);
1203 
1204                 genAddLit (ic,  lit);
1205                 goto release;
1206 
1207         } else if(AOP_TYPE(right) == AOP_CRY) {
1208 
1209                 pic16_emitcode(";bitadd","right is bit: %s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
1210                 pic16_emitcode(";bitadd","left is bit: %s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
1211                 pic16_emitcode(";bitadd","result is bit: %s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
1212 
1213                 /* here we are adding a bit to a char or int */
1214                 if(size == 1) {
1215                         if (pic16_sameRegs(AOP(left), AOP(result)) ) {
1216 
1217                                 pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0));
1218                                 pic16_emitpcode(POC_INCF ,  pic16_popGet(AOP(result),0));
1219                         } else { // not same
1220 
1221                                 if(AOP_TYPE(left) == AOP_ACC) {
1222                                         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0));
1223                                         pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
1224                                 } else {
1225                                         pic16_mov2w(AOP(left),0);
1226                                         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0));
1227                                         pic16_emitpcode(POC_INCFW , pic16_popGet(AOP(left),0));
1228                                 }
1229 
1230                                 if(AOP_TYPE(result) != AOP_ACC) {
1231 
1232                                         if(AOP_TYPE(result) == AOP_CRY) {
1233                                                 pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
1234                                                 pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(result),0));
1235                                                 emitSKPZ;
1236                                                 pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(result),0));
1237                                         } else {
1238                                                 pic16_emitpcode(POC_MOVWF ,   pic16_popGet(AOP(result),0));
1239                                         }
1240                                 }
1241                         }
1242 
1243                 } else {
1244                         int offset = 1;
1245                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1246                         if (pic16_sameRegs(AOP(left), AOP(result)) ) {
1247                                 emitCLRZ;
1248                                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
1249                                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(result),0));
1250                         } else {
1251                                 emitCLRZ; // needed here as well: INCFW is not always executed, Z is undefined then
1252                                 pic16_mov2w(AOP(left),0);
1253                                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
1254                                 pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0));
1255                                 emitMOVWF(right,0);
1256                         }
1257 
1258                         while(--size){
1259                                 emitSKPZ;
1260                                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(result),offset++));
1261                         }
1262 
1263                 }
1264 
1265         } else {
1266                 // add bytes
1267 
1268                 // Note: the following is an example of WISC code, eg.
1269                 // it's supposed to run on a Weird Instruction Set Computer :o)
1270 
1271                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1272 
1273                 if ( AOP_TYPE(left) == AOP_ACC) {
1274                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1275                         pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right),0));
1276                         if ( AOP_TYPE(result) != AOP_ACC)
1277                                 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
1278                         goto release; // we're done, since WREG is 1 byte
1279                 }
1280 
1281 
1282                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1283 
1284                 size = min( AOP_SIZE(result), AOP_SIZE(right) );
1285                 size = min( size, AOP_SIZE(left) );
1286                 offset = 0;
1287 
1288                 if(pic16_debug_verbose) {
1289 //                      fprintf(stderr, "%s:%d result: %d\tleft: %d\tright: %d\n", __FILE__, __LINE__,
1290 //                              AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
1291 //                      fprintf(stderr, "%s:%d size of operands: %d\n", __FILE__, __LINE__, size);
1292                 }
1293 
1294 
1295 
1296                 if ((AOP_TYPE(left) == AOP_PCODE) && (
1297                                 (AOP(left)->aopu.pcop->type == PO_LITERAL) ||
1298 //                              (AOP(left)->aopu.pcop->type == PO_DIR) ||   // patch 9
1299                                 (AOP(left)->aopu.pcop->type == PO_IMMEDIATE)))
1300                 {
1301                         // add to literal operand
1302 
1303                         // add first bytes
1304                         for(i=0; i<size; i++) {
1305                                 if (AOP_TYPE(right) == AOP_ACC) {
1306                                         pic16_emitpcode(POC_ADDLW, pic16_popGet(AOP(left),i));
1307                                 } else {
1308                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
1309                                         if(i) { // add with carry
1310                                                 pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(right),i));
1311                                         } else { // add without
1312                                                 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right),i));
1313                                         }
1314                                 }
1315                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
1316                         }
1317 
1318                         DEBUGpic16_pic16_AopTypeSign(__LINE__, NULL, right, NULL);
1319 
1320                         // add leftover bytes
1321                         if (SPEC_USIGN(getSpec(operandType(right)))) {
1322                                 // right is unsigned
1323                                 for(i=size; i< AOP_SIZE(result); i++) {
1324                                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
1325                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
1326                                         pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
1327                                 }
1328 
1329                         } else {
1330                                 // right is signed, oh dear ...
1331                                 for(i=size; i< AOP_SIZE(result); i++) {
1332                                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
1333                                         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1334                                         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),i));
1335                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
1336                                         pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
1337                                 }
1338 
1339                         }
1340                         goto release;
1341 
1342                 } else {
1343                         // add regs
1344 
1345                         if (pic16_sameRegs(AOP(left), AOP(result))
1346                             && (AOP_SIZE(left) < AOP_SIZE(result)))
1347                         {
1348                             // extend left operand, sign-bit still intact
1349                             pic16_addSign (result, AOP_SIZE(left), !SPEC_USIGN(getSpec(operandType(left))));
1350                         }
1351 
1352                         // add first bytes
1353                         for(i=0; i<size; i++) {
1354                                 if (AOP_TYPE(right) != AOP_ACC)
1355                                   pic16_mov2w(AOP(right),i);
1356                                 if (pic16_sameRegs(AOP(left), AOP(result)))
1357                                 {
1358                                         if(i) { // add with carry
1359                                                 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
1360                                         } else { // add without
1361                                                 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),i));
1362                                         }
1363                                 } else { // not same
1364                                         if(i) { // add with carry
1365                                                 pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i));
1366                                         } else { // add without
1367                                                 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),i));
1368                                         }
1369                                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
1370                                 }
1371                         }
1372 
1373                         // add leftover bytes
1374                         // either left or right is too short
1375                         for (i=size; i < AOP_SIZE(result); i++) {
1376                           // get right operand into WREG
1377                           if (i < AOP_SIZE(right)) {
1378                             pic16_mov2w (AOP(right), i);
1379                           } else {
1380                             // right is too short, not overwritten with result
1381                             pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
1382                             if (!SPEC_USIGN(getSpec(operandType(right)))) {
1383                               // right operand is signed
1384                               // Make sure that right's sign is not yet overwritten
1385                               assert (!pic16_sameRegs (AOP(right), AOP(result)));
1386                               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),AOP_SIZE(right)-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1387                               pic16_emitpcode(POC_SETF, pic16_popCopyReg (&pic16_pc_wreg));
1388                             }
1389                           }
1390 
1391                           // get left+WREG+CARRY into result
1392                           if (pic16_sameRegs (AOP(left), AOP(result))) {
1393                             // left might have been extended in result above
1394                             pic16_emitpcode (POC_ADDWFC, pic16_popGet (AOP(result), i));
1395                           } else if (i < AOP_SIZE(left)) {
1396                             pic16_emitpcode (POC_ADDFWC, pic16_popGet (AOP(left), i));
1397                             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
1398                           } else {
1399                             // left is too short, not overwritten with result
1400                             pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), i));
1401                             if (!SPEC_USIGN(getSpec(operandType(left)))) {
1402                               // left operand is signed
1403                               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1404                               pic16_emitpcode(POC_SETF, pic16_popGet (AOP(result), i));
1405                             }
1406                             pic16_emitpcode (POC_ADDWFC, pic16_popGet (AOP(result), i));
1407                           }
1408                         } // for i
1409                         goto release;
1410                 }
1411 
1412         }
1413 
1414         assert( 0 );
1415 
1416 release:
1417         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1418         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1419         pic16_freeAsmop(result,NULL,ic,TRUE);
1420 }
1421 
1422 /*-----------------------------------------------------------------*/
1423 /* pic16_genMinusDec :- does subtraction with decrement if possible     */
1424 /*-----------------------------------------------------------------*/
pic16_genMinusDec(iCode * ic)1425 bool pic16_genMinusDec (iCode *ic)
1426 {
1427     unsigned int icount ;
1428     unsigned int size = pic16_getDataSize(IC_RESULT(ic));
1429 
1430     FENTRY;
1431     /* will try to generate an increment */
1432     /* if the right side is not a literal
1433     we cannot */
1434     if ((AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) ||
1435         (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) ||
1436         (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) )
1437         return FALSE ;
1438 
1439     DEBUGpic16_emitcode ("; lit val","%d",(unsigned int) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1440 
1441     /* if the literal value of the right hand side
1442     is greater than 4 then it is not worth it */
1443     if ((icount = (unsigned int) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1444         return FALSE ;
1445 
1446     /* if decrement 16 bits in register */
1447     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1448         (size > 1) &&
1449         (icount == 1)) {
1450 
1451       if(size == 2) {
1452         pic16_emitpcode(POC_DECF,    pic16_popGet(AOP(IC_RESULT(ic)),LSB));
1453         emitSKPC;
1454         pic16_emitpcode(POC_DECF,    pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
1455 
1456         pic16_emitcode("decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1457         pic16_emitcode("incfsz","%s,w",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1458         pic16_emitcode(" decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
1459       } else {
1460         /* size is 3 or 4 */
1461         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(IC_RESULT(ic)),LSB));
1462         pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_wreg));
1463         pic16_emitpcode(POC_SUBWFB_D1,   pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
1464         pic16_emitpcode(POC_SUBWFB_D1,   pic16_popGet(AOP(IC_RESULT(ic)),MSB24));
1465 
1466         pic16_emitcode("movlw","0xff");
1467         pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1468 
1469         //emitSKPNC;
1470         pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
1471         //emitSKPNC;
1472         pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
1473 
1474         if(size > 3) {
1475           pic16_emitpcode(POC_SUBWFB_D1,   pic16_popGet(AOP(IC_RESULT(ic)),MSB32));
1476 
1477           pic16_emitcode("skpnc","");
1478           //emitSKPNC;
1479           pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
1480         }
1481 
1482       }
1483 
1484       return TRUE;
1485 
1486     }
1487 
1488     /* if the sizes are greater than 1 then we cannot */
1489     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1490         AOP_SIZE(IC_LEFT(ic)) > 1   )
1491         return FALSE ;
1492 
1493     /* we can if the aops of the left & result match or
1494     if they are in registers and the registers are the
1495     same */
1496     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1497 
1498       while (icount--)
1499         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),0));
1500 
1501         //pic16_emitcode ("decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1502 
1503         return TRUE ;
1504     }
1505 
1506     DEBUGpic16_emitcode ("; returning"," result=%s, left=%s",
1507                    pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
1508                    pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1509     if(size==1) {
1510 
1511       pic16_emitcode("decf","%s,w",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1512       pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1513 
1514       pic16_emitpcode(POC_DECFW,  pic16_popGet(AOP(IC_LEFT(ic)),0));
1515       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
1516 
1517       return TRUE;
1518     }
1519 
1520     return FALSE ;
1521 }
1522 
1523 /*-----------------------------------------------------------------*/
1524 /* pic16_addSign - propogate sign bit to higher bytes                    */
1525 /*-----------------------------------------------------------------*/
pic16_addSign(operand * result,int offset,int sign)1526 void pic16_addSign(operand *result, int offset, int sign)
1527 {
1528   int size = (pic16_getDataSize(result) - offset);
1529   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1530 
1531   if(size > 0){
1532     if(sign && offset) {
1533 
1534       if(size == 1) {
1535         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
1536         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1537         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
1538       } else {
1539 
1540         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
1541         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1542         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
1543         while(size--)
1544           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset+size));
1545 
1546       }
1547     } else
1548       while(size--)
1549         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1550   }
1551 }
1552 
1553 /*-----------------------------------------------------------------*/
1554 /* pic16_genMinus - generates code for subtraction                       */
1555 /*-----------------------------------------------------------------*/
pic16_genMinus(iCode * ic)1556 void pic16_genMinus (iCode *ic)
1557 {
1558   int size, offset = 0, same=0;
1559   unsigned long lit = 0L;
1560 
1561     FENTRY;
1562   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1563   pic16_aopOp (IC_RIGHT(ic),ic,FALSE);
1564   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1565 
1566   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY  &&
1567       AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1568     operand *t = IC_RIGHT(ic);
1569     IC_RIGHT(ic) = IC_LEFT(ic);
1570     IC_LEFT(ic) = t;
1571   }
1572 
1573   DEBUGpic16_emitcode ("; ","result %s, left %s, right %s",
1574                    pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
1575                    pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
1576                    pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
1577 
1578   /* special cases :- */
1579   /* if both left & right are in bit space */
1580   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1581       AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1582     pic16_genPlusBits (ic);
1583     goto release ;
1584   }
1585 
1586   /* if I can do an decrement instead
1587      of subtract then GOOD for ME */
1588 //  if (pic16_genMinusDec (ic) == TRUE)
1589 //    goto release;
1590 
1591   size = pic16_getDataSize(IC_RESULT(ic));
1592   same = pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)));
1593 
1594   if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
1595     /* Add a literal to something else */
1596 
1597     lit = ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1598     lit = - (long)lit;
1599 
1600     genAddLit ( ic,  lit);
1601   } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1602     // bit subtraction
1603 
1604     pic16_emitcode(";bitsub","right is bit: %s",pic16_aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1605     pic16_emitcode(";bitsub","left is bit: %s",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1606     pic16_emitcode(";bitsub","result is bit: %s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1607 
1608     /* here we are subtracting a bit from a char or int */
1609     if(size == 1) {
1610       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1611 
1612         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1613         pic16_emitpcode(POC_DECF ,  pic16_popGet(AOP(IC_RESULT(ic)),0));
1614       } else {
1615 
1616         if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1617           pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1618           pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
1619         }else  if( (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1620 
1621           lit = ulFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit);
1622 
1623           if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1624             if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
1625               if(lit & 1) {
1626                 pic16_emitpcode(POC_MOVLW , pic16_popGetLit(1));
1627                 pic16_emitpcode(POC_XORWF , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1628               }
1629             }else{
1630               pic16_emitpcode(POC_BCF ,     pic16_popGet(AOP(IC_RESULT(ic)),0));
1631               if(lit & 1)
1632                 pic16_emitpcode(POC_BTFSS , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1633               else
1634                 pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1635               pic16_emitpcode(POC_BSF ,     pic16_popGet(AOP(IC_RESULT(ic)),0));
1636             }
1637             goto release;
1638           } else {
1639             pic16_emitpcode(POC_MOVLW , pic16_popGetLit(lit & 0xff));
1640             pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1641             pic16_emitpcode(POC_MOVLW , pic16_popGetLit((lit-1) & 0xff));
1642             //pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(IC_RESULT(ic)),0));
1643 
1644           }
1645 
1646         } else {
1647           pic16_mov2w(AOP(IC_LEFT(ic)),0);
1648           pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1649           pic16_emitpcode(POC_DECFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
1650         }
1651 
1652         if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
1653 
1654           pic16_emitpcode(POC_MOVWF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
1655 
1656         } else  {
1657           pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
1658 /*
1659           pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1660           emitSKPZ;
1661           pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1662 */
1663         }
1664 
1665       }
1666 
1667     }
1668   } else   if((AOP(IC_LEFT(ic))->type == AOP_LIT) &&
1669               (AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC)) {
1670 
1671     lit = ulFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit);
1672     DEBUGpic16_emitcode ("; left is lit","line %d result %s, left %s, right %s",__LINE__,
1673                    pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
1674                    pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
1675                    pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
1676 
1677 
1678     if( (size == 1) && ((lit & 0xff) == 0) ) {
1679       /* res = 0 - right */
1680       if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
1681         pic16_emitpcode(POC_NEGF,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
1682       } else {
1683         pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
1684         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
1685         pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
1686       }
1687       goto release;
1688     }
1689 
1690     pic16_mov2w(AOP(IC_RIGHT(ic)),0);
1691     pic16_emitpcode(POC_SUBLW, pic16_popGetLit(lit & 0xff));
1692     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1693 
1694 
1695     offset = 0;
1696     while(--size) {
1697       lit >>= 8;
1698       offset++;
1699       if(same) {
1700         // here we have x = lit - x   for sizeof(x)>1
1701         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1702         pic16_emitpcode(POC_SUBFWB_D1,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
1703       } else {
1704         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1705         pic16_emitpcode(POC_SUBFWB_D0,  pic16_popGet(AOP(IC_RIGHT(ic)),offset));
1706         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
1707       }
1708     }
1709 
1710 
1711   } else {
1712 
1713     DEBUGpic16_emitcode ("; ","line %d result %s, left %s, right %s",__LINE__,
1714                    pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
1715                    pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
1716                    pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
1717 
1718     if ((AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RESULT(ic)))
1719             && pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1720         // extend left in result
1721         pic16_addSign (IC_RESULT(ic), AOP_SIZE(IC_LEFT(ic)), !SPEC_USIGN(getSpec(operandType(IC_LEFT(ic)))));
1722     }
1723 
1724     if ((AOP_SIZE(IC_RIGHT(ic)) < AOP_SIZE(IC_RESULT(ic)))
1725             && pic16_sameRegs (AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) {
1726         // extend right in result---fails if left resides in result as well...
1727         assert ((IC_LEFT(ic) == IC_RIGHT(ic)) || !pic16_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))));
1728         pic16_addSign (IC_RESULT(ic), AOP_SIZE(IC_RIGHT(ic)), !SPEC_USIGN(getSpec(operandType(IC_RIGHT(ic)))));
1729     }
1730 
1731     if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1732       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1733       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
1734       pic16_emitpcode(POC_SUBLW, pic16_popGetLit(0));
1735       if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
1736         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1737     } else {
1738 
1739         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1740         if(AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC)
1741           pic16_mov2w(AOP(IC_RIGHT(ic)),0);
1742 
1743         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1744           pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(IC_LEFT(ic)),0));
1745         else {
1746           if( (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1747             pic16_emitpcode(POC_SUBLW, pic16_popGet(AOP(IC_LEFT(ic)),0));
1748           } else {
1749             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
1750           }
1751           if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
1752             if ( AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1753               pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
1754               emitSKPZ;
1755               pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
1756             }else
1757               pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1758           }
1759         }
1760     }
1761 
1762     /*
1763       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1764 
1765       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1766       pic16_emitpcode(POC_SUBFW,  pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1767       } else {
1768       pic16_emitpcode(POC_SUBFW,  pic16_popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1769       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1770       }
1771     */
1772     offset = 1;
1773     size--;
1774 
1775     while (size--) {
1776       if (pic16_sameRegs (AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) {
1777         pic16_mov2w (AOP(IC_RESULT(ic)), offset);
1778       } else if (offset < AOP_SIZE(IC_RIGHT(ic)))
1779         pic16_mov2w(AOP(IC_RIGHT(ic)),offset);
1780       else {
1781         // right operand is too short, not overwritten with result
1782         pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
1783         if (!SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1784           // signed -- sign extend the right operand
1785           pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RIGHT(ic)),AOP_SIZE(IC_RIGHT(ic))-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1786           pic16_emitpcode (POC_SETF, pic16_popCopyReg (&pic16_pc_wreg));
1787         }
1788       }
1789       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1790         pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1791       } else if (offset < AOP_SIZE(IC_LEFT(ic))) {
1792         pic16_emitpcode(POC_SUBWFB_D0,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
1793         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
1794       } else {
1795         // left operand is too short, not overwritten with result
1796         pic16_emitpcode (POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)), offset));
1797         if (!SPEC_USIGN(operandType(IC_LEFT(ic)))) {
1798           // signed -- sign extend the left operand
1799           pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_LEFT(ic)),AOP_SIZE(IC_LEFT(ic))-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1800           pic16_emitpcode (POC_SETF, pic16_popGet(AOP(IC_RESULT(ic)), offset)); // keep CARRY/#BORROW bit intact!
1801         }
1802         pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1803       }
1804       offset++;
1805     }
1806   }
1807 
1808   //    adjustArithmeticResult(ic);
1809 
1810  release:
1811   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1812   pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1813   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1814 }
1815 
1816 
1817 /*-----------------------------------------------------------------*
1818  * pic_genMult8XLit_n - multiplication of two 8-bit numbers.
1819  *
1820  *
1821  *-----------------------------------------------------------------*/
1822 static void
pic16_genMult8XLit_n(operand * left,operand * right,operand * result)1823 pic16_genMult8XLit_n (operand *left, operand *right, operand *result)
1824 {
1825   int lit;
1826   int size = AOP_SIZE (result);
1827 
1828   FENTRY;
1829   DEBUGpic16_pic16_AopType (__LINE__, left, right, result);
1830 
1831   if (AOP_TYPE (right) != AOP_LIT)
1832     {
1833       fprintf (stderr, "%s %d - right operand is not a literal\n", __FILE__, __LINE__);
1834       exit (1);
1835     }
1836 
1837   lit = (int) ulFromVal (AOP (right)->aopu.aop_lit);
1838   assert ((lit >= -128) && (lit < 256) );
1839 
1840   /* We need to adjust the high byte of the result (in PRODH) if
1841    * (a) literals < 0 or
1842    * (b) signed register operands < 0.
1843    *
1844    * If lit >= 0 and val is unsigned, MULLW will do the trick.
1845    *
1846    * If val is signed and 8 bit:
1847    * val = -2^7 * v_7 + SUM(2^i * v_i, i=0..6)
1848    *     = -2^7 * v_7 + -2^7 * v_7 + SUM(2^i * v_i, i=0..7)
1849    *     = -2^8 * v_7 + SUM(2^i * v_i, i=0..7)
1850    *     = -2^8 * v_7 + UNSIGNED(val)
1851    *
1852    * For lit >= 0:
1853    * lit * val = lit * UNSIGNED(val) - 2^8 * v_7 * lit
1854    *
1855    * For lit < 0, lit = l_7 .. l_0:
1856    *
1857    * lit * val = (-2^8 * l_7 + UNSIGNED(lit)) * (-2^8 * v_7 + UNSIGNED(val))
1858    *           = 2^8 * l_7 * 2^8 * v_7
1859    *             - 2^8 * l_7 * UNSIGNED(val)
1860    *             - 2^8 * v_7 * UNSIGNED(lit)
1861    *             + UNSIGNED(lit) * UNSIGNED(val)
1862    *           = 2^16 * l_7 * v_7
1863    *             - 2^8 * (l_7 * UNSIGNED(val) + v_7 * UNSIGNED(lit))
1864    *             + UNSIGNED(lit) * UNSIGNED(val)
1865    *
1866    * '2^16 * X' is only of interest if the result is larger than 16 * bit
1867    * ==> ignored.
1868    * '-2^8 * X' requires subtracting the original values of 'val'
1869    * respectively 'lit' from the high byte of the result.
1870    * UNSIGNED(lit) * UNSIGNED(val) can be computed via a MUL instruction.
1871    *
1872    * So, we do:
1873    * MOVF val, W
1874    * MULLW lit
1875    * # Now, PRODH:PRODL hold UNSIGNED(val) * UNSIGNED(lit)
1876    * if result > 8 bit:
1877    *     if lit < 0:
1878    *         SUBWF PRODH, F         # -2^8 * l_7 * UNSIGNED(val)
1879    *     MOVF PRODH, W
1880    *     BTFSC val, 7
1881    *     SUBLW lit                  # -2^8 * v_7 * UNSIGNED(lit)
1882    *     MOVWF result[1]            # this might overwrite val!
1883    * MOVFF PRODL, result[0]         # this might overwrite val!
1884    */
1885 
1886   pic16_mov2w (AOP (left), 0);
1887   pic16_emitpcode (POC_MULLW, pic16_popGetLit (lit & 0x00ff));
1888 
1889   if (size > 1)
1890     {
1891       /* Adjust PRODH for signed operands. */
1892       if (lit < 0)
1893         {
1894           /* left is still in WREG */
1895           pic16_emitpcode (POC_SUBWF, pic16_popCopyReg (&pic16_pc_prodh));
1896         } // if
1897 
1898       pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (&pic16_pc_prodh));
1899       if (!SPEC_USIGN (operandType (left)))
1900         {
1901           pic16_emitpcode (POC_BTFSC,
1902                            pic16_newpCodeOpBit (pic16_aopGet (AOP (left), 0, FALSE, FALSE),
1903                                                 7, 0, PO_GPR_REGISTER));
1904           pic16_emitpcode (POC_SUBLW, pic16_popGetLit (lit & 0x00ff));
1905         } // if
1906 
1907       /* Assign result (high byte) -- this may overwrite val. */
1908       pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP (result), 1));
1909     } // if
1910 
1911   /* Assign result (low byte) -- this may overwrite val. */
1912   pic16_emitpcode (POC_MOVFF,
1913                    pic16_popGet2p (pic16_popCopyReg (&pic16_pc_prodl),
1914                                    pic16_popGet (AOP (result), 0)));
1915 
1916   /* Must sign/zero-extend here if size > 2. */
1917   if (size > 2)
1918     {
1919       pic16_addSign (result, 2, !IS_UNSIGNED (operandType (left)));
1920     } // if
1921 }
1922 
1923 /*-----------------------------------------------------------------*
1924  * genMult8X8_n - multiplication of two 8-bit numbers.
1925  *
1926  *
1927  *-----------------------------------------------------------------*/
1928 void
pic16_genMult8X8_n(operand * left,operand * right,operand * result)1929 pic16_genMult8X8_n (operand *left, operand *right, operand *result)
1930 {
1931   FENTRY;
1932 
1933   /* Special case: multiply by literal. */
1934   if (AOP_TYPE (right) == AOP_LIT)
1935     {
1936       pic16_genMult8XLit_n (left, right, result);
1937       return;
1938     }
1939   else if (AOP_TYPE (left) == AOP_LIT)
1940     {
1941       pic16_genMult8XLit_n (right, left, result);
1942       return;
1943     } // if
1944 
1945   /* cases:
1946      A = A x B  B = A x B
1947      A = B x C
1948      W = A x B
1949      W = W x B  W = B x W
1950    */
1951   /* if result == right then exchange left and right */
1952   if (pic16_sameRegs (AOP (result), AOP (right)))
1953     {
1954       operand *tmp;
1955       tmp = left;
1956       left = right;
1957       right = tmp;
1958     } // if
1959 
1960   if (AOP_TYPE (left) != AOP_ACC)
1961     {
1962       // left is not WREG
1963       if (AOP_TYPE (right) != AOP_ACC)
1964         {
1965           pic16_mov2w (AOP (left), 0);
1966           pic16_emitpcode (POC_MULWF, pic16_popGet (AOP (right), 0));
1967         }
1968       else
1969         {
1970           pic16_emitpcode (POC_MULWF, pic16_popGet (AOP (left), 0));
1971         } // if
1972     }
1973   else
1974     {
1975       pic16_emitpcode (POC_MULWF, pic16_popGet (AOP (right), 0));
1976     } // if
1977 
1978   /* result is in PRODL:PRODH */
1979   if (AOP_TYPE (result) != AOP_ACC)
1980     {
1981       int isPRODL = (AOP (result)->type != AOP_STA && ! strcmp (pic16_aopGet (AOP (result), 0, TRUE, FALSE), "_PRODL"));
1982 
1983       if (AOP_SIZE (result) > 1)
1984         {
1985           /* If s8 x s8 --> s16 multiplication was called for, fixup high byte.
1986            * (left=a1a0, right=b1b0, X1: high byte, X0: low byte)
1987            *
1988            *    a1a0 * b1b0
1989            * --------------
1990            *      a1b0 a0b0
1991            * a1b1 a0b1
1992            * ---------------
1993            *           a0b0  a1= 0, b1= 0 (both unsigned)
1994            *       -b0 a0b0  a1=-1, b1= 0 (a signed and < 0, b unsigned or >= 0)
1995            *       -a0 a0b0  a1= 0, b1=-1 (b signed and < 0, a unsigned or >= 0)
1996            *  -(a0+b0) a0b0  a1=-1, b1=-1 (a and b signed and < 0)
1997            *
1998            *  Currently, PRODH:PRODL holds a0b0 as 16 bit value; we need to
1999            *  subtract a0 and/or b0 from PRODH. */
2000           if (!IS_UNSIGNED (operandType (right)))
2001             {
2002               /* right operand (b1) signed and < 0, then subtract left op (a0) */
2003               pic16_mov2w (AOP (left), 0);
2004               pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP (right), 0, 7));
2005               pic16_emitpcode (POC_SUBWF, pic16_popCopyReg (&pic16_pc_prodh));
2006             } // if
2007 
2008           if (!IS_UNSIGNED (getSpec (operandType (left))))
2009             {
2010               /* left operand (a1) signed and < 0, then subtract right op (b0) */
2011               pic16_mov2w (AOP (right), 0 );
2012               pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP (left), 0, 7));
2013               pic16_emitpcode (POC_SUBWF, pic16_popCopyReg (&pic16_pc_prodh));
2014             } // if
2015 
2016           /* Assing high byte of result -- this may overwrite one of the operands. */
2017           pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet (AOP (result), 1)));
2018         } // if
2019 
2020       /* Assign low byte of result -- this may overwrite one of the operands. */
2021       if (!isPRODL)
2022         {
2023           pic16_emitpcode (POC_MOVFF, pic16_popGet2p (pic16_popCopyReg (&pic16_pc_prodl), pic16_popGet (AOP (result), 0)));
2024         } // if
2025 
2026       /* Must sign/zero-extend here if size > 2. */
2027       if (AOP_SIZE (result) > 2)
2028         {
2029           pic16_addSign (result, 2, !IS_UNSIGNED (operandType (left)));
2030         } // if
2031     }
2032   else
2033     {
2034       pic16_emitpcode (POC_MOVFW, pic16_popCopyReg (&pic16_pc_prodl));
2035     }
2036 }
2037