* src/pic16/{gen.c,genarith.c}: replaced sign-extension
[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_SETF, 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_SETF, 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_SETF, 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
1132         }
1133
1134         assert( 0 );
1135         
1136 release:
1137         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1138         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1139         pic16_freeAsmop(result,NULL,ic,TRUE);
1140 }
1141
1142 /*-----------------------------------------------------------------*/
1143 /* pic16_genMinusDec :- does subtraction with decrement if possible     */
1144 /*-----------------------------------------------------------------*/
1145 bool pic16_genMinusDec (iCode *ic)
1146 {
1147     unsigned int icount ;
1148     unsigned int size = pic16_getDataSize(IC_RESULT(ic));
1149
1150     FENTRY;
1151     /* will try to generate an increment */
1152     /* if the right side is not a literal 
1153     we cannot */
1154     if ((AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) || 
1155         (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) || 
1156         (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) )
1157         return FALSE ;
1158
1159     DEBUGpic16_emitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1160
1161     /* if the literal value of the right hand side
1162     is greater than 4 then it is not worth it */
1163     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1164         return FALSE ;
1165
1166     /* if decrement 16 bits in register */
1167     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1168         (size > 1) &&
1169         (icount == 1)) {
1170
1171       if(size == 2) { 
1172         pic16_emitpcode(POC_DECF,    pic16_popGet(AOP(IC_RESULT(ic)),LSB));
1173         emitSKPC;
1174         pic16_emitpcode(POC_DECF,    pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
1175
1176         pic16_emitcode("decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1177         pic16_emitcode("incfsz","%s,w",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1178         pic16_emitcode(" decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
1179       } else {
1180         /* size is 3 or 4 */
1181         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(IC_RESULT(ic)),LSB));
1182         pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_wreg));
1183         pic16_emitpcode(POC_SUBWFB_D1,   pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
1184         pic16_emitpcode(POC_SUBWFB_D1,   pic16_popGet(AOP(IC_RESULT(ic)),MSB24));
1185
1186         pic16_emitcode("movlw","0xff");
1187         pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1188
1189         //emitSKPNC;
1190         pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
1191         //emitSKPNC;
1192         pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
1193
1194         if(size > 3) {
1195           pic16_emitpcode(POC_SUBWFB_D1,   pic16_popGet(AOP(IC_RESULT(ic)),MSB32));
1196
1197           pic16_emitcode("skpnc","");
1198           //emitSKPNC;
1199           pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
1200         }
1201
1202       }
1203
1204       return TRUE;
1205
1206     }
1207
1208     /* if the sizes are greater than 1 then we cannot */
1209     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1210         AOP_SIZE(IC_LEFT(ic)) > 1   )
1211         return FALSE ;
1212
1213     /* we can if the aops of the left & result match or
1214     if they are in registers and the registers are the
1215     same */
1216     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1217
1218       while (icount--) 
1219         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),0));
1220
1221         //pic16_emitcode ("decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1222
1223         return TRUE ;
1224     }
1225
1226     DEBUGpic16_emitcode ("; returning"," result=%s, left=%s",
1227                    pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
1228                    pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1229     if(size==1) {
1230
1231       pic16_emitcode("decf","%s,w",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1232       pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1233
1234       pic16_emitpcode(POC_DECFW,  pic16_popGet(AOP(IC_LEFT(ic)),0));
1235       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
1236
1237       return TRUE;
1238     }
1239
1240     return FALSE ;
1241 }
1242
1243 /*-----------------------------------------------------------------*/
1244 /* pic16_addSign - propogate sign bit to higher bytes                    */
1245 /*-----------------------------------------------------------------*/
1246 void pic16_addSign(operand *result, int offset, int sign)
1247 {
1248   int size = (pic16_getDataSize(result) - offset);
1249   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1250
1251   if(size > 0){
1252     if(sign && offset) {
1253
1254       if(size == 1) {
1255         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
1256         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1257         pic16_emitpcode(POC_SETF, pic16_popGet(AOP(result),offset));
1258       } else {
1259
1260         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
1261         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1262         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
1263         while(size--)
1264           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset+size));
1265
1266       }
1267     } else
1268       while(size--)
1269         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1270   }
1271 }
1272
1273 /*-----------------------------------------------------------------*/
1274 /* pic16_genMinusBits - generates code for subtraction  of two bits      */
1275 /*-----------------------------------------------------------------*/
1276 void pic16_genMinusBits (iCode *ic)
1277 {
1278     symbol *lbl = newiTempLabel(NULL);
1279
1280     FENTRY;
1281     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
1282         pic16_emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
1283         pic16_emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
1284         pic16_emitcode("cpl","c");
1285         pic16_emitcode("","%05d_DS_:",(lbl->key+100));
1286         pic16_outBitC(IC_RESULT(ic));
1287     }
1288     else{
1289         pic16_emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
1290         pic16_emitcode("subb","a,acc");
1291         pic16_emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
1292         pic16_emitcode("inc","a");
1293         pic16_emitcode("","%05d_DS_:",(lbl->key+100));
1294         pic16_aopPut(AOP(IC_RESULT(ic)),"a",0);
1295         pic16_addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
1296     }
1297 }
1298
1299 /*-----------------------------------------------------------------*/
1300 /* pic16_genMinus - generates code for subtraction                       */
1301 /*-----------------------------------------------------------------*/
1302 void pic16_genMinus (iCode *ic)
1303 {
1304   int size, offset = 0, same=0;
1305   unsigned long lit = 0L;
1306
1307     FENTRY;
1308   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1309   pic16_aopOp (IC_RIGHT(ic),ic,FALSE);
1310   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1311
1312   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY  &&
1313       AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1314     operand *t = IC_RIGHT(ic);
1315     IC_RIGHT(ic) = IC_LEFT(ic);
1316     IC_LEFT(ic) = t;
1317   }
1318
1319   DEBUGpic16_emitcode ("; ","result %s, left %s, right %s",
1320                    pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
1321                    pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
1322                    pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
1323
1324   /* special cases :- */
1325   /* if both left & right are in bit space */
1326   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1327       AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1328     pic16_genPlusBits (ic);
1329     goto release ;
1330   }
1331
1332   /* if I can do an decrement instead
1333      of subtract then GOOD for ME */
1334 //  if (pic16_genMinusDec (ic) == TRUE)
1335 //    goto release;   
1336
1337   size = pic16_getDataSize(IC_RESULT(ic));   
1338   same = pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)));
1339
1340   if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
1341     /* Add a literal to something else */
1342
1343     lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1344     lit = - (long)lit;
1345
1346     genAddLit ( ic,  lit);
1347     
1348 #if 0
1349     /* add the first byte: */
1350     pic16_emitcode("movlw","0x%x", lit & 0xff);
1351     pic16_emitcode("addwf","%s,f", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1352     pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(lit & 0xff));
1353     pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_LEFT(ic)),0));
1354
1355
1356     offset = 1;
1357     size--;
1358
1359     while(size-- > 0) {
1360
1361       lit >>= 8;
1362
1363       if(lit & 0xff) {
1364
1365         if((lit & 0xff) == 0xff) {
1366           pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(0xff));
1367           emitSKPC;
1368           pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
1369         } else {
1370           pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(lit & 0xff));
1371           emitSKPNC;
1372           pic16_emitpcode(POC_MOVLW,  pic16_popGetLit((lit+1) & 0xff));
1373           pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
1374         }
1375
1376       } else {
1377         /* do the rlf known zero trick here */
1378         pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(1));
1379         emitSKPNC;
1380         pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
1381       }
1382       offset++;
1383     }
1384 #endif
1385   } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1386     // bit subtraction
1387
1388     pic16_emitcode(";bitsub","right is bit: %s",pic16_aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1389     pic16_emitcode(";bitsub","left is bit: %s",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1390     pic16_emitcode(";bitsub","result is bit: %s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1391
1392     /* here we are subtracting a bit from a char or int */
1393     if(size == 1) {
1394       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1395
1396         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1397         pic16_emitpcode(POC_DECF ,  pic16_popGet(AOP(IC_RESULT(ic)),0));
1398
1399         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
1400                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
1401                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
1402         pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1403       } else {
1404
1405         if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1406           pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1407           pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
1408         }else  if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
1409               (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1410
1411           lit = (unsigned long)floatFromVal(AOP(IC_LEFT(ic))->aopu.aop_lit);
1412
1413           if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1414             if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
1415               if(lit & 1) {
1416                 pic16_emitpcode(POC_MOVLW , pic16_popGetLit(1));
1417                 pic16_emitpcode(POC_XORWF , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1418               }
1419             }else{
1420               pic16_emitpcode(POC_BCF ,     pic16_popGet(AOP(IC_RESULT(ic)),0));
1421               if(lit & 1) 
1422                 pic16_emitpcode(POC_BTFSS , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1423               else
1424                 pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1425               pic16_emitpcode(POC_BSF ,     pic16_popGet(AOP(IC_RESULT(ic)),0));
1426             }
1427             goto release;
1428           } else {
1429             pic16_emitpcode(POC_MOVLW , pic16_popGetLit(lit & 0xff));
1430             pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1431             pic16_emitpcode(POC_MOVLW , pic16_popGetLit((lit-1) & 0xff));
1432             //pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(IC_RESULT(ic)),0));
1433
1434           }
1435
1436         } else {
1437           pic16_mov2w(AOP(IC_LEFT(ic)),0);
1438           pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1439           pic16_emitpcode(POC_DECFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
1440         }
1441           
1442         if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
1443             
1444           pic16_emitpcode(POC_MOVWF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
1445
1446         } else  {
1447           pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
1448 /*
1449           pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1450           emitSKPZ;
1451           pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1452 */
1453         }
1454
1455       }
1456
1457     }
1458   } else   if(// (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) || 
1459               (AOP(IC_LEFT(ic))->type == AOP_LIT) &&
1460               (AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC)) {
1461
1462     lit = (unsigned long)floatFromVal(AOP(IC_LEFT(ic))->aopu.aop_lit);
1463     DEBUGpic16_emitcode ("; left is lit","line %d result %s, left %s, right %s",__LINE__,
1464                    pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
1465                    pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
1466                    pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
1467
1468
1469     if( (size == 1) && ((lit & 0xff) == 0) ) {
1470       /* res = 0 - right */
1471       if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
1472         pic16_emitpcode(POC_NEGF,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
1473       } else { 
1474         pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
1475         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
1476         pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
1477       }
1478       goto release;
1479     }
1480
1481     pic16_mov2w(AOP(IC_RIGHT(ic)),0);
1482     pic16_emitpcode(POC_SUBLW, pic16_popGetLit(lit & 0xff));    
1483     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1484
1485
1486     offset = 0;
1487     while(--size) {
1488       lit >>= 8;
1489       offset++;
1490       if(same) {
1491         // here we have x = lit - x   for sizeof(x)>1
1492         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1493         pic16_emitpcode(POC_SUBFWB_D1,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
1494       } else {
1495         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1496         pic16_emitpcode(POC_SUBFWB_D0,  pic16_popGet(AOP(IC_RIGHT(ic)),offset));
1497         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
1498       }
1499     }
1500   
1501
1502   } else {
1503
1504     DEBUGpic16_emitcode ("; ","line %d result %s, left %s, right %s",__LINE__,
1505                    pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
1506                    pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
1507                    pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
1508
1509     if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1510       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1511       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
1512       pic16_emitpcode(POC_SUBLW, pic16_popGetLit(0));
1513       if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
1514         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1515     } else {
1516
1517         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1518         if(AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC) 
1519           pic16_mov2w(AOP(IC_RIGHT(ic)),0);
1520
1521         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1522           pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(IC_LEFT(ic)),0));
1523         else {
1524           if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
1525               (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1526             pic16_emitpcode(POC_SUBLW, pic16_popGet(AOP(IC_LEFT(ic)),0));
1527           } else {
1528             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
1529           }
1530           if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
1531             if ( AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1532               pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
1533               emitSKPZ;
1534               pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
1535             }else
1536               pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1537           }
1538         }
1539     }
1540
1541     /*
1542       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1543
1544       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1545       pic16_emitpcode(POC_SUBFW,  pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1546       } else {
1547       pic16_emitpcode(POC_SUBFW,  pic16_popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1548       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1549       }
1550     */
1551     offset = 1;
1552     size--;
1553
1554     while(size--){
1555       if (offset < AOP_SIZE(IC_RIGHT(ic)))
1556         pic16_mov2w(AOP(IC_RIGHT(ic)),offset);
1557       else {
1558         pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
1559         if (!SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1560           // signed -- sign extend the right operand
1561           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));
1562           pic16_emitpcode (POC_SETF, pic16_popCopyReg (&pic16_pc_wreg));
1563         }
1564       }
1565       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1566         pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1567       } else {
1568         if (offset < AOP_SIZE(IC_LEFT(ic))) {
1569           pic16_emitpcode(POC_SUBWFB_D0,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
1570           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
1571         } else {
1572           // zero extend the left operand
1573           pic16_emitpcode (POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)), offset));
1574           if (!SPEC_USIGN(operandType(IC_LEFT(ic)))) {
1575             // signed -- sign extend the left operand
1576             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));
1577             pic16_emitpcode (POC_SETF, pic16_popGet(AOP(IC_RESULT(ic)), offset)); // keep CARRY/#BORROW bit intact!
1578           }
1579           pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1580         }
1581       } 
1582       offset++;
1583     }
1584
1585   }
1586
1587
1588   //    adjustArithmeticResult(ic);
1589         
1590  release:
1591   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1592   pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1593   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1594 }
1595
1596
1597 /*-----------------------------------------------------------------*
1598  * pic_genUMult8XLit_8 - unsigned multiplication of two 8-bit numbers.
1599  * 
1600  * 
1601  *-----------------------------------------------------------------*/
1602 void pic16_genUMult8XLit_8 (operand *left,
1603                              operand *right,
1604                              operand *result)
1605 {
1606   unsigned int lit;
1607   int same;
1608   int size = AOP_SIZE(result);
1609   int i;
1610
1611     FENTRY;
1612         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
1613
1614         if (AOP_TYPE(right) != AOP_LIT){
1615                 fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
1616                 exit(1);
1617         }
1618
1619         lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
1620         lit &= 0xff;
1621         pic16_emitpcomment("Unrolled 8 X 8 multiplication");
1622         pic16_emitpcomment("FIXME: the function does not support result==WREG");
1623         
1624         same = pic16_sameRegs(AOP(left), AOP(result));
1625         if(same) {
1626                 switch(lit) {
1627                         case 0:
1628                                 while (size--) {
1629                                   pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),size));
1630                                 } // while
1631                                 return;
1632                         case 2:
1633                                 // its faster to left shift
1634                                 for (i=1; i < size; i++) {
1635                                   pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
1636                                 } // for
1637                                 emitCLRC;
1638                                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
1639                                 if (size > 1)
1640                                   pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1));
1641                                 return;
1642
1643                         default:
1644                                 if(AOP_TYPE(left) != AOP_ACC)
1645                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
1646                                 pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit));
1647                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
1648                                         pic16_popGet(AOP(result), 0)));
1649                                 if (size > 1) {
1650                                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
1651                                                                             pic16_popGet(AOP(result), 1)));
1652                                   for (i=2; i < size; i++) {
1653                                     pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
1654                                   } // for
1655                                 } // if
1656                                 return;
1657                 }
1658         } else {
1659                 // operands different
1660                 switch(lit) {
1661                         case 0:
1662                                 while (size--) {
1663                                   pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),size));
1664                                 } // while
1665                                 return;
1666                         case 2:
1667                                 for (i=1; i < size; i++) {
1668                                   pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
1669                                 } // for
1670                                 emitCLRC;
1671                                 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
1672                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
1673                                 if (size > 1)
1674                                   pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1));
1675                                 return;
1676                         default:
1677                                 if(AOP_TYPE(left) != AOP_ACC)
1678                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
1679                                 pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit));
1680                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
1681                                         pic16_popGet(AOP(result), 0)));
1682
1683                                 if (size > 1) {
1684                                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
1685                                                                             pic16_popGet(AOP(result), 1)));
1686                                   for (i=2; i < size; i++) {
1687                                     pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
1688                                   } // for
1689                                 } // if
1690                                 return;
1691                 }
1692         }
1693 }
1694
1695 /*-----------------------------------------------------------------------*
1696  * pic_genUMult16XLit_16 - unsigned multiplication of two 16-bit numbers *
1697  *-----------------------------------------------------------------------*/
1698 void pic16_genUMult16XLit_16 (operand *left,
1699                              operand *right,
1700                              operand *result)
1701 {
1702   pCodeOp *pct1, *pct2, *pct3, *pct4;
1703   unsigned int lit;
1704   int same;
1705
1706
1707     FENTRY;
1708     
1709         if (AOP_TYPE(right) != AOP_LIT){
1710                 fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
1711                 exit(1);
1712         }
1713
1714         lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
1715         lit &= 0xffff;
1716
1717         same = pic16_sameRegs(AOP(left), AOP(result));
1718         if(same) {
1719                 switch(lit) {
1720                         case 0:
1721                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
1722                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),1));
1723                                 return;
1724                         case 2:
1725                                 // its faster to left shift
1726                                 emitCLRC;
1727                                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
1728                                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),1));
1729                                 return;
1730
1731                         default: {
1732                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1733
1734                                 pct1 = pic16_popGetTempReg(1);
1735                                 pct2 = pic16_popGetTempReg(1);
1736                                 pct3 = pic16_popGetTempReg(1);
1737                                 pct4 = pic16_popGetTempReg(1);
1738
1739                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
1740                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
1741                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1742                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
1743                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1744                                         pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
1745                                         
1746                                 /* WREG still holds the low literal */
1747                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
1748                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1749                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
1750                                         
1751                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
1752                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
1753                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1754                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
1755                                         
1756                                 /* load result */
1757                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1758                                         pct1, pic16_popGet(AOP(result), 0)));
1759                                 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct2));
1760                                 pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
1761                                 pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
1762                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
1763
1764                                 pic16_popReleaseTempReg(pct4,1);
1765                                 pic16_popReleaseTempReg(pct3,1);
1766                                 pic16_popReleaseTempReg(pct2,1);
1767                                 pic16_popReleaseTempReg(pct1,1);
1768                         }; return;
1769                 }
1770         } else {
1771                 // operands different
1772                 switch(lit) {
1773                         case 0:
1774                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0));
1775                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
1776                                 return;
1777                         case 2:
1778                                 emitCLRC;
1779                                 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
1780                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
1781                                 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 1));
1782                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
1783                                 return;
1784                         default: {
1785                                         
1786                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
1787                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
1788                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1789                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
1790                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1791                                         pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
1792                                         
1793                                 /* WREG still holds the low literal */
1794                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
1795                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
1796                                 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
1797                                         
1798                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
1799                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
1800                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
1801                                 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
1802
1803                         }; return;
1804                 }
1805         }
1806 }
1807
1808
1809 /*-----------------------------------------------------------------*
1810  * genUMult8X8_8 - unsigned multiplication of two 8-bit numbers.
1811  * 
1812  * 
1813  *-----------------------------------------------------------------*/
1814 void pic16_genUMult8X8_8 (operand *left,
1815                            operand *right,
1816                            operand *result)
1817
1818 {
1819   FENTRY;
1820   
1821
1822         if (AOP_TYPE(right) == AOP_LIT) {
1823                 pic16_genUMult8XLit_8(left,right,result);
1824           return;
1825         }
1826
1827         /* cases:
1828                 A = A x B       B = A x B
1829                 A = B x C
1830                 W = A x B
1831                 W = W x B       W = B x W
1832         */
1833         /* if result == right then exchange left and right */
1834         if(pic16_sameRegs(AOP(result), AOP(right))) {
1835           operand *tmp;
1836                 tmp = left;
1837                 left = right;
1838                 right = tmp;
1839         }
1840                 
1841         if(AOP_TYPE(left) != AOP_ACC) {
1842                 // left is not WREG
1843                 if(AOP_TYPE(right) != AOP_ACC) {
1844                         pic16_mov2w(AOP(left), 0);
1845                         pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
1846                 } else {
1847                         pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
1848                 }
1849         } else {
1850                 // left is WREG, right cannot be WREG (or can?!)
1851                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(right), 0));
1852         }
1853         
1854         /* result is in PRODL:PRODH */
1855         if(AOP_TYPE(result) != AOP_ACC) {
1856                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
1857                         pic16_popGet(AOP(result), 0)));
1858
1859
1860                 if(AOP_SIZE(result)>1) {
1861                   int i;
1862
1863                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
1864                         pic16_popGet(AOP(result), 1)));
1865                         
1866                         for(i=2;i<AOP_SIZE(result);i++)
1867                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
1868                 }
1869         } else {
1870                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
1871         }
1872 }
1873
1874 /*------------------------------------------------------------------*
1875  * genUMult16X16_16 - unsigned multiplication of two 16-bit numbers *
1876  *------------------------------------------------------------------*/
1877 void pic16_genUMult16X16_16 (operand *left,
1878                            operand *right,
1879                            operand *result)
1880
1881 {
1882   pCodeOp *pct1, *pct2, *pct3, *pct4;
1883
1884     FENTRY;
1885
1886
1887         if (AOP_TYPE(right) == AOP_LIT) {
1888                 pic16_genUMult8XLit_8(left,right,result);
1889           return;
1890         }
1891
1892         /* cases:
1893                 A = A x B       B = A x B
1894                 A = B x C
1895         */
1896         /* if result == right then exchange left and right */
1897         if(pic16_sameRegs(AOP(result), AOP(right))) {
1898           operand *tmp;
1899                 tmp = left;
1900                 left = right;
1901                 right = tmp;
1902         }
1903
1904
1905         if(pic16_sameRegs(AOP(result), AOP(left))) {
1906
1907                 pct1 = pic16_popGetTempReg(1);
1908                 pct2 = pic16_popGetTempReg(1);
1909                 pct3 = pic16_popGetTempReg(1);
1910                 pct4 = pic16_popGetTempReg(1);
1911
1912                 pic16_mov2w(AOP(left), 0);
1913                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
1914                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1915                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
1916                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1917                         pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
1918                                         
1919                 /* WREG still holds the lower left */
1920                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
1921                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1922                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
1923                 
1924                 pic16_mov2w(AOP(left), 1);
1925                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
1926                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1927                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
1928                                         
1929                 /* load result */
1930                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1931                         pic16_pCodeOpCopy( pct1 ), pic16_popGet(AOP(result), 0)));
1932                 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy( pct2 ));
1933                 pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
1934                 pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
1935                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
1936
1937                 pic16_popReleaseTempReg( pct4, 1 );
1938                 pic16_popReleaseTempReg( pct3, 1 );
1939                 pic16_popReleaseTempReg( pct2, 1 );
1940                 pic16_popReleaseTempReg( pct1, 1 );
1941
1942         } else {
1943
1944                 pic16_mov2w(AOP(left), 0);
1945                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
1946                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1947                         pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
1948                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1949                         pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
1950
1951                 /* WREG still holds the lower left */
1952                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
1953                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
1954                 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
1955                 
1956                 pic16_mov2w(AOP(left), 1);
1957                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
1958                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
1959                 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
1960         }       
1961 }
1962
1963
1964 void pic16_genSMult16X16_16(operand *left,
1965                         operand *right,
1966                         operand *result)
1967 {
1968
1969 }
1970
1971 #if 0
1972 /*-----------------------------------------------------------------*
1973  * pic16_genSMult8X8_16 - signed multiplication of two 8-bit numbers
1974  *
1975  *  this routine will call the unsigned multiply routine and then
1976  * post-fix the sign bit.
1977  *-----------------------------------------------------------------*/
1978 void pic16_genSMult8X8_8 (operand *left,
1979                            operand *right,
1980                            operand *result,
1981                            pCodeOpReg *result_hi)
1982 {
1983         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1984
1985
1986   if(!result_hi) {
1987     result_hi = PCOR(pic16_popGet(AOP(result),1));
1988   }
1989
1990
1991   pic16_genUMult8X8_8(left,right,result);
1992
1993   
1994 #if 0
1995   pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1996   pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(result_hi));
1997   pic16_mov2w(AOP(left),0);
1998   pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1999   pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(result),1));
2000 #endif
2001 }
2002 #endif
2003
2004 /*-----------------------------------------------------------------*
2005  * pic16_genMult8X8_8 - multiplication of two 8-bit numbers        *
2006  *-----------------------------------------------------------------*/
2007 void pic16_genMult8X8_8 (operand *left,
2008                          operand *right,
2009                          operand *result)
2010 {
2011   FENTRY;
2012   
2013   if(AOP_TYPE(right) == AOP_LIT)
2014     pic16_genUMult8XLit_8(left,right,result);
2015   else
2016     pic16_genUMult8X8_8(left,right,result);
2017 }
2018
2019
2020 /*-----------------------------------------------------------------*
2021  * pic16_genMult16X16_16 - multiplication of two 16-bit numbers    *
2022  *-----------------------------------------------------------------*/
2023 void pic16_genMult16X16_16 (operand *left,
2024                          operand *right,
2025                          operand *result)
2026 {
2027   FENTRY;
2028   
2029   if (AOP_TYPE(right) == AOP_LIT)
2030     pic16_genUMult16XLit_16(left,right,result);
2031   else
2032     pic16_genUMult16X16_16(left,right,result);
2033 }
2034
2035
2036
2037
2038 /*-----------------------------------------------------------------------*
2039  * pic_genUMult32XLit_32 - unsigned multiplication of two 32-bit numbers *
2040  *-----------------------------------------------------------------------*/
2041 void pic16_genUMult32XLit_32 (operand *left,
2042                              operand *right,
2043                              operand *result)
2044 {
2045   pCodeOp *pct1, *pct2, *pct3, *pct4;
2046   unsigned int lit;
2047   int same;
2048
2049
2050     FENTRY;
2051     
2052         if (AOP_TYPE(right) != AOP_LIT){
2053                 fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
2054                 exit(1);
2055         }
2056
2057         lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
2058         lit &= 0xffff;
2059
2060         same = pic16_sameRegs(AOP(left), AOP(result));
2061         if(same) {
2062                 switch(lit) {
2063                         case 0:
2064                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
2065                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),1));
2066                                 return;
2067                         case 2:
2068                                 // its faster to left shift
2069                                 emitCLRC;
2070                                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
2071                                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),1));
2072                                 return;
2073
2074                         default: {
2075                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2076
2077                                 pct1 = pic16_popGetTempReg(1);
2078                                 pct2 = pic16_popGetTempReg(1);
2079                                 pct3 = pic16_popGetTempReg(1);
2080                                 pct4 = pic16_popGetTempReg(1);
2081
2082                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
2083                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
2084                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2085                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
2086                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2087                                         pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
2088                                         
2089                                 /* WREG still holds the low literal */
2090                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
2091                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2092                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
2093                                         
2094                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
2095                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
2096                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2097                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
2098                                         
2099                                 /* load result */
2100                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2101                                         pct1, pic16_popGet(AOP(result), 0)));
2102                                 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct2));
2103                                 pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
2104                                 pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
2105                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
2106
2107                                 pic16_popReleaseTempReg( pct4, 1 );
2108                                 pic16_popReleaseTempReg( pct3, 1 );
2109                                 pic16_popReleaseTempReg( pct2, 1 );
2110                                 pic16_popReleaseTempReg( pct1, 1 );
2111                         }; return;
2112                 }
2113         } else {
2114                 // operands different
2115                 switch(lit) {
2116                         case 0:
2117                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0));
2118                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
2119                                 return;
2120                         case 2:
2121                                 emitCLRC;
2122                                 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
2123                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
2124                                 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 1));
2125                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
2126                                 return;
2127                         default: {
2128                                         
2129                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
2130                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
2131                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2132                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
2133                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2134                                         pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
2135                                         
2136                                 /* WREG still holds the low literal */
2137                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
2138                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
2139                                 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
2140                                         
2141                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
2142                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
2143                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
2144                                 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
2145
2146                         }; return;
2147                 }
2148         }
2149 }
2150
2151
2152 /*------------------------------------------------------------------*
2153  * genUMult32X32_32 - unsigned multiplication of two 32-bit numbers *
2154  *------------------------------------------------------------------*/
2155 void pic16_genUMult32X32_32 (operand *left,
2156                            operand *right,
2157                            operand *result)
2158
2159 {
2160   pCodeOp *pct1, *pct2, *pct3, *pct4;
2161
2162     FENTRY;
2163     
2164         if (AOP_TYPE(right) == AOP_LIT) {
2165                 pic16_genUMult8XLit_8(left,right,result);
2166           return;
2167         }
2168
2169         /* cases:
2170                 A = A x B       B = A x B
2171                 A = B x C
2172         */
2173         /* if result == right then exchange left and right */
2174         if(pic16_sameRegs(AOP(result), AOP(right))) {
2175           operand *tmp;
2176                 tmp = left;
2177                 left = right;
2178                 right = tmp;
2179         }
2180
2181
2182         if(pic16_sameRegs(AOP(result), AOP(left))) {
2183
2184                 pct1 = pic16_popGetTempReg(1);
2185                 pct2 = pic16_popGetTempReg(1);
2186                 pct3 = pic16_popGetTempReg(1);
2187                 pct4 = pic16_popGetTempReg(1);
2188
2189                 pic16_mov2w(AOP(left), 0);
2190                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
2191                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2192                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
2193                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2194                         pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
2195                                         
2196                 /* WREG still holds the lower left */
2197                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
2198                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2199                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
2200                 
2201                 pic16_mov2w(AOP(left), 1);
2202                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
2203                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2204                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
2205                                         
2206                 /* load result */
2207                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2208                         pic16_pCodeOpCopy( pct1 ), pic16_popGet(AOP(result), 0)));
2209                 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy( pct2 ));
2210                 pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
2211                 pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
2212                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
2213
2214                 pic16_popReleaseTempReg( pct4, 1 );
2215                 pic16_popReleaseTempReg( pct3, 1 );
2216                 pic16_popReleaseTempReg( pct2, 1 );
2217                 pic16_popReleaseTempReg( pct1, 1 );
2218
2219         } else {
2220
2221                 pic16_mov2w(AOP(left), 0);
2222                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
2223                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2224                         pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
2225                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2226                         pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
2227
2228                 /* WREG still holds the lower left */
2229                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
2230                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
2231                 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
2232                 
2233                 pic16_mov2w(AOP(left), 1);
2234                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
2235                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
2236                 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
2237         }       
2238 }
2239
2240
2241 /*-----------------------------------------------------------------*
2242  * pic16_genMult32X32_32 - multiplication of two 32-bit numbers    *
2243  *-----------------------------------------------------------------*/
2244 void pic16_genMult32X32_32 (operand *left,
2245                          operand *right,
2246                          operand *result)
2247 {
2248   FENTRY;
2249   
2250   if (AOP_TYPE(right) == AOP_LIT)
2251     pic16_genUMult32XLit_32(left,right,result);
2252   else
2253     pic16_genUMult32X32_32(left,right,result);
2254 }
2255
2256
2257
2258
2259
2260
2261
2262 #if 0
2263 /*-----------------------------------------------------------------*/
2264 /* constMult - generates code for multiplication by a constant     */
2265 /*-----------------------------------------------------------------*/
2266 void genMultConst(unsigned C)
2267 {
2268
2269   unsigned lit;
2270   unsigned sr3; // Shift right 3
2271   unsigned mask;
2272
2273   int size = 1;
2274
2275   /*
2276     Convert a string of 3 binary 1's in the lit into
2277     0111 = 1000 - 1;
2278   */
2279
2280   mask = 7 << ( (size*8) - 3);
2281   lit = C;
2282   sr3 = 0;
2283
2284   while(mask < (1<<size*8)) {
2285
2286     if( (mask & lit) == lit) {
2287       unsigned lsb;
2288
2289       /* We found 3 (or more) consecutive 1's */
2290
2291       lsb = mask & ~(mask & (mask-1));  // lsb of mask.
2292
2293       consecutive_bits = ((lit + lsb) & lit) ^ lit;
2294
2295       lit ^= consecutive_bits;
2296
2297       mask <<= 3;
2298
2299       sr3 |= (consecutive + lsb);
2300
2301     }
2302
2303     mask >>= 1;
2304
2305   }
2306
2307 }
2308
2309 #endif