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