* device/include/asm/pic16/features.h,
[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 /*-----------------------------------------------------------------*/
420 /* genAddlit - generates code for addition                         */
421 /*-----------------------------------------------------------------*/
422 static void genAddLit2byte (operand *result, int offr, int lit)
423 {
424   FENTRY;
425   
426   switch(lit & 0xff) {
427   case 0:
428     break;
429   case 1:
430     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offr));
431     break;
432   case 0xff:
433     pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr));
434     break;
435   default:
436     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
437     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
438   }
439
440 }
441
442 static void emitMOVWF(operand *reg, int offset)
443 {
444   if(!reg)
445     return;
446
447   if (AOP_TYPE(reg) == AOP_ACC) {
448     DEBUGpic16_emitcode ("; ***","%s  %d ignoring mov into W",__FUNCTION__,__LINE__);
449     return;
450   }
451
452   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(reg),offset));
453
454 }
455
456 static void genAddLit (iCode *ic, int lit)
457 {
458
459   int size,same;
460   int lo;
461
462   operand *result;
463   operand *left;
464
465     FENTRY;
466
467
468   left = IC_LEFT(ic);
469   result = IC_RESULT(ic);
470   same = pic16_sameRegs(AOP(left), AOP(result));
471   size = pic16_getDataSize(result);
472
473   if(same) {
474
475     /* Handle special cases first */
476     if(size == 1) 
477       genAddLit2byte (result, 0, lit);
478      
479     else if(size == 2) {
480       int hi = 0xff & (lit >> 8);
481       lo = lit & 0xff;
482
483       switch(hi) {
484       case 0: 
485
486         /* lit = 0x00LL */
487         DEBUGpic16_emitcode ("; hi = 0","%s  %d",__FUNCTION__,__LINE__);
488         switch(lo) {
489         case 0:
490           break;
491         case 1:
492           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
493           emitSKPNZ;
494           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
495           break;
496         case 0xff:
497           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0));
498           pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
499           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
500
501           break;
502         default:
503           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
504           pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
505           emitSKPNC;
506           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
507
508
509         }
510         break;
511
512       case 1:
513         /* lit = 0x01LL */
514         DEBUGpic16_emitcode ("; hi = 1","%s  %d",__FUNCTION__,__LINE__);
515         switch(lo) {
516         case 0:  /* 0x0100 */
517           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
518           break;
519         case 1:  /* 0x0101  */
520           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
521           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
522           emitSKPNZ;
523           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
524           break;
525         case 0xff: /* 0x01ff */
526           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0));
527           pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0));
528           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
529           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
530           break;
531         default: /* 0x01LL */
532           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
533           pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
534           emitSKPNC;
535           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
536           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16));
537         }         
538         break;
539
540       case 0xff:
541         DEBUGpic16_emitcode ("; hi = ff","%s  %d",__FUNCTION__,__LINE__);
542         /* lit = 0xffLL */
543         switch(lo) {
544         case 0:  /* 0xff00 */
545           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
546           break;
547         case 1:  /*0xff01 */
548           pic16_emitpcode(POC_INCFSZ, pic16_popGet(AOP(result),0));
549           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
550           break;
551 /*      case 0xff: * 0xffff *
552           pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(result),0,FALSE,FALSE));
553           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
554           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),0,FALSE,FALSE));
555           break;
556 */
557         default:
558           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
559           pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),0));
560           emitSKPC;
561           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
562           
563         }
564
565         break;
566         
567       default:
568         DEBUGpic16_emitcode ("; hi is generic","%d   %s  %d",hi,__FUNCTION__,__LINE__);
569
570         /* lit = 0xHHLL */
571         switch(lo) {
572         case 0:  /* 0xHH00 */
573           genAddLit2byte (result, MSB16, hi);
574           break;
575         case 1:  /* 0xHH01 */
576           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
577           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
578           pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
579           break;
580 /*      case 0xff: * 0xHHff *
581           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0,FALSE,FALSE));
582           pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
583           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
584           pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),MSB16,FALSE,FALSE));
585           break;
586 */      default:  /* 0xHHLL */
587           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
588           pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
589           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(hi));
590           pic16_emitpcode(POC_ADDWFC,pic16_popGet(AOP(result),MSB16));
591           break;
592         }
593
594       }
595     } else {
596       int carry_info = 0;
597       int offset = 0;
598       /* size > 2 */
599       DEBUGpic16_emitcode (";  add lit to long","%s  %d",__FUNCTION__,__LINE__);
600
601       while(size--) {
602         lo = BYTEofLONG(lit,0);
603
604         if(carry_info) {
605           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
606           pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset));
607         }else {
608           /* no carry info from previous step */
609           /* this means this is the first time to add */
610           switch(lo) {
611           case 0:
612             break;
613           case 1:
614             pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),offset));
615             carry_info=1;
616             break;
617           default:
618             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
619             pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offset));
620             if(lit <0x100) 
621               carry_info = 3;  /* Were adding only one byte and propogating the carry */
622             else
623               carry_info = 2;
624             break;
625           }
626         }
627         offset++;
628         lit >>= 8;
629       }
630     
631 /*
632       lo = BYTEofLONG(lit,0);
633
634       if(lit < 0x100) {
635         if(lo) {
636           if(lo == 1) {
637             pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0,FALSE,FALSE));
638             emitSKPNZ;
639           } else {
640             pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lo));
641             pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
642             emitSKPNC;
643           }
644           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),1,FALSE,FALSE));
645           emitSKPNZ;
646           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),2,FALSE,FALSE));
647           emitSKPNZ;
648           pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),3,FALSE,FALSE));
649
650         } 
651       } 
652     }
653
654 */
655     }
656   } else {
657     int offset = 1;
658     DEBUGpic16_emitcode (";  left and result aren't same","%s  %d",__FUNCTION__,__LINE__);
659
660     if(size == 1) {
661
662       if(AOP_TYPE(left) == AOP_ACC) {
663         /* left addend is already in accumulator */
664         switch(lit & 0xff) {
665         case 0:
666           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
667           emitMOVWF(result,0);
668           break;
669         default:
670           pic16_emitpcode(POC_ADDLW, pic16_popGetLit(lit & 0xff));
671           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
672           emitMOVWF(result,0);
673         }
674       } else {
675         /* left addend is in a register */
676         switch(lit & 0xff) {
677         case 0:
678           pic16_mov2w(AOP(left),0);
679           emitMOVWF(result, 0);
680           break;
681         case 1:
682           pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0));
683           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
684           emitMOVWF(result,0);
685           break;
686         case 0xff:
687           pic16_emitpcode(POC_DECFW, pic16_popGet(AOP(left),0));
688           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
689           emitMOVWF(result,0);
690           break;
691         default:
692           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
693           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
694           //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
695           emitMOVWF(result,0);
696         }
697       }
698
699     } else {
700       int clear_carry=0;
701
702       /* left is not the accumulator */
703       if(lit & 0xff) {
704         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
705         pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
706       } else {
707         pic16_mov2w(AOP(left),0);
708         /* We don't know the state of the carry bit at this point */
709         clear_carry = 1;
710       }
711       //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0,FALSE,FALSE));
712       emitMOVWF(result,0);
713       while(--size) {
714       
715         lit >>= 8;
716         if(lit & 0xff) {
717           if(clear_carry) {
718             /* The ls byte of the lit must've been zero - that 
719                means we don't have to deal with carry */
720
721             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
722             pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(left),offset));
723             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
724
725             clear_carry = 0;
726
727           } else {
728             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
729             pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),offset));
730             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
731           }
732
733         } else {
734           pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offset));
735           pic16_mov2w(AOP(left),offset);
736           pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),offset));
737         }
738         offset++;
739       }
740     }
741   }
742 }
743
744 /*-----------------------------------------------------------------*/
745 /* pic16_genPlus - generates code for addition                     */
746 /*-----------------------------------------------------------------*/
747 void pic16_genPlus (iCode *ic)
748 {
749   int i, size, offset = 0;
750   operand *result, *left, *right;
751
752     FENTRY;
753     
754     /* special cases :- */
755         result = IC_RESULT(ic);
756         left = IC_LEFT(ic);
757         right = IC_RIGHT(ic);
758         pic16_aopOp (left,ic,FALSE);
759         pic16_aopOp (right,ic,FALSE);
760         pic16_aopOp (result,ic,TRUE);
761         DEBUGpic16_pic16_AopType(__LINE__,left, right, result);
762         // pic16_DumpOp("(left)",left);
763
764         /* if literal, literal on the right or
765         if left requires ACC or right is already
766         in ACC */
767
768         if ( (AOP_TYPE(left) == AOP_LIT) || (pic16_sameRegs(AOP(right), AOP(result))) ) {
769                 operand *t = right;
770                 right = IC_RIGHT(ic) = left;
771                 left = IC_LEFT(ic) = t;
772         }
773
774         /* if both left & right are in bit space */
775         if (AOP_TYPE(left) == AOP_CRY &&
776                 AOP_TYPE(right) == AOP_CRY) {
777                 pic16_genPlusBits (ic);
778                 goto release ;
779         }
780
781         /* if left in bit space & right literal */
782         if (AOP_TYPE(left) == AOP_CRY &&
783                 AOP_TYPE(right) == AOP_LIT) {
784                 /* if result in bit space */
785                 if(AOP_TYPE(result) == AOP_CRY){
786                         if((unsigned long)floatFromVal(AOP(right)->aopu.aop_lit) != 0L) {
787                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),0));
788                                 if (!pic16_sameRegs(AOP(left), AOP(result)) )
789                                         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
790                                 pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),0));
791                         }
792                 } else {
793                         unsigned long lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
794                         size = pic16_getDataSize(result);
795                         while (size--) {
796                                 pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), offset));
797                                 pic16_emitpcode (POC_MOVLW, pic16_popGetLit ((lit >> (8*offset)) & 0xFF));
798                                 pic16_emitpcode (POC_ADDWFC, pic16_popGet(AOP(result), offset++));
799                                 //MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));  
800                                 //pic16_emitcode("addc","a,#00  ;%d",__LINE__);
801                                 //pic16_aopPut(AOP(result),"a",offset++);
802                         }
803                 }
804         goto release ;
805         } // left == CRY
806
807         /* if I can do an increment instead
808         of add then GOOD for ME */
809         if (pic16_genPlusIncr (ic) == TRUE)
810                 goto release;   
811
812         size = pic16_getDataSize(result);
813
814         if(AOP(right)->type == AOP_LIT) {
815                 /* Add a literal to something else */
816                 //bool know_W=0;
817                 unsigned lit = (unsigned) floatFromVal(AOP(right)->aopu.aop_lit);
818                 //unsigned l1=0;
819
820                 //offset = 0;
821                 DEBUGpic16_emitcode(";","adding lit to something. size %d",size);
822
823                 genAddLit (ic,  lit);
824                 goto release;
825
826         } else if(AOP_TYPE(right) == AOP_CRY) {
827
828                 pic16_emitcode(";bitadd","right is bit: %s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
829                 pic16_emitcode(";bitadd","left is bit: %s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
830                 pic16_emitcode(";bitadd","result is bit: %s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
831
832                 /* here we are adding a bit to a char or int */
833                 if(size == 1) {
834                         if (pic16_sameRegs(AOP(left), AOP(result)) ) {
835
836                                 pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0));
837                                 pic16_emitpcode(POC_INCF ,  pic16_popGet(AOP(result),0));
838
839                                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
840                                                 AOP(right)->aopu.aop_dir,
841                                                 AOP(right)->aopu.aop_dir);
842                                 pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(result),0,FALSE,FALSE));
843                         } else { // not same
844
845                                 if(AOP_TYPE(left) == AOP_ACC) {
846                                         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0));
847                                         pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
848
849                                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
850                                         AOP(right)->aopu.aop_dir,
851                                         AOP(right)->aopu.aop_dir);
852                                         pic16_emitcode(" xorlw","1");
853                                 } else {
854                                         pic16_mov2w(AOP(left),0);
855                                         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(right),0));
856                                         pic16_emitpcode(POC_INCFW , pic16_popGet(AOP(left),0));
857
858                                         pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(left),0,FALSE,FALSE));
859                                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
860                                         AOP(right)->aopu.aop_dir,
861                                         AOP(right)->aopu.aop_dir);
862                                         pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(left),0,FALSE,FALSE));
863                                 }
864           
865                                 if(AOP_TYPE(result) != AOP_ACC) {
866             
867                                         if(AOP_TYPE(result) == AOP_CRY) {
868                                                 pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
869                                                 pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(result),0));
870                                                 emitSKPZ;
871                                                 pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(result),0));
872                                         } else {
873                                                 pic16_emitpcode(POC_MOVWF ,   pic16_popGet(AOP(result),0));
874                                                 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(result),0,FALSE,FALSE));
875                                         }
876                                 }
877                         }
878
879                 } else {
880                         int offset = 1;
881                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
882                         if (pic16_sameRegs(AOP(left), AOP(result)) ) {
883                                 emitCLRZ;
884                                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
885                                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(result),0));
886
887                                 pic16_emitcode("clrz","");
888
889                                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
890                                                 AOP(right)->aopu.aop_dir,
891                                                 AOP(right)->aopu.aop_dir);
892                                 pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(result),0,FALSE,FALSE));
893
894                         } else {
895                                 emitCLRZ; // needed here as well: INCFW is not always executed, Z is undefined then
896                                 pic16_mov2w(AOP(left),0);
897                                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
898                                 pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(left),0));
899                                 //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(right),0,FALSE,FALSE));
900                                 emitMOVWF(right,0);
901
902                                 pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(left),0,FALSE,FALSE));
903                                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
904                                                 AOP(right)->aopu.aop_dir,
905                                                 AOP(right)->aopu.aop_dir);
906                                 pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(left),0,FALSE,FALSE));
907                                 pic16_emitcode("movwf","%s", pic16_aopGet(AOP(result),0,FALSE,FALSE));
908
909                         }
910
911                         while(--size){
912                                 emitSKPZ;
913                                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(result),offset++));
914                                 //pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(right),offset++,FALSE,FALSE));
915                         }
916
917                 }
918       
919         } else {
920                 // add bytes
921
922                 // Note: the following is an example of WISC code, eg.
923                 // it's supposed to run on a Weird Instruction Set Computer :o)
924
925                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
926
927                 if ( AOP_TYPE(left) == AOP_ACC) {
928                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
929                         pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right),0));
930                         if ( AOP_TYPE(result) != AOP_ACC)
931                                 pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
932                         goto release; // we're done, since WREG is 1 byte
933                 }
934
935
936                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
937
938                 size = min( AOP_SIZE(result), AOP_SIZE(right) );
939                 size = min( size, AOP_SIZE(left) );
940                 offset = 0;
941
942                 if(pic16_debug_verbose) {
943 //                      fprintf(stderr, "%s:%d result: %d\tleft: %d\tright: %d\n", __FILE__, __LINE__,
944 //                              AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
945 //                      fprintf(stderr, "%s:%d size of operands: %d\n", __FILE__, __LINE__, size);
946                 }
947
948
949
950                 if ((AOP_TYPE(left) == AOP_PCODE) && (
951                                 (AOP(left)->aopu.pcop->type == PO_LITERAL) || 
952 //                              (AOP(left)->aopu.pcop->type == PO_DIR) ||   // patch 9
953                                 (AOP(left)->aopu.pcop->type == PO_IMMEDIATE)))
954                 {
955                         // add to literal operand
956
957                         // add first bytes
958                         for(i=0; i<size; i++) {
959                                 if (AOP_TYPE(right) == AOP_ACC) {
960                                         pic16_emitpcode(POC_ADDLW, pic16_popGet(AOP(left),i));
961                                 } else {
962                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
963                                         if(i) { // add with carry
964                                                 pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(right),i));
965                                         } else { // add without
966                                                 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right),i));
967                                         }
968                                 }
969                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
970                         }
971                         
972                         DEBUGpic16_pic16_AopTypeSign(__LINE__, NULL, right, NULL);
973
974                         // add leftover bytes
975                         if (SPEC_USIGN(getSpec(operandType(right)))) {
976                                 // right is unsigned
977                                 for(i=size; i< AOP_SIZE(result); i++) {
978                                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
979                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
980                                         pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
981                                 }
982
983                         } else {
984                                 // right is signed, oh dear ...
985                                 for(i=size; i< AOP_SIZE(result); i++) {
986                                         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
987                                         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
988                                         pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result),i));
989                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
990                                         pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
991                                 }
992
993                         }
994                         goto release;
995
996                 } else {
997                         // add regs
998
999                         // add first bytes
1000                         for(i=0; i<size; i++) {
1001                                 if (AOP_TYPE(right) != AOP_ACC)
1002                                   pic16_mov2w(AOP(right),i);
1003                                 if (pic16_sameRegs(AOP(left), AOP(result)))
1004                                 {
1005                                         if(i) { // add with carry
1006                                                 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
1007                                         } else { // add without
1008                                                 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),i));
1009                                         }
1010                                 } else { // not same
1011                                         if(i) { // add with carry
1012                                                 pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i));
1013                                         } else { // add without
1014                                                 pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),i));
1015                                         }
1016                                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
1017                                 }
1018                         }
1019
1020                         // add leftover bytes
1021                         // either left or right is too short
1022                         for (i=size; i < AOP_SIZE(result); i++) {
1023                           // get right operand into WREG
1024                           if (i < AOP_SIZE(right)) {
1025                             pic16_mov2w (AOP(right), i);
1026                           } else {
1027                             // right is too short
1028                             pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
1029                             if (!SPEC_USIGN(getSpec(operandType(right)))) {
1030                               // right operand is signed
1031                               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),AOP_SIZE(right)-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1032                               pic16_emitpcode(POC_COMF, pic16_popCopyReg (&pic16_pc_wreg));
1033                             }
1034                           }
1035
1036                           // get left+WREG+CARRY into result
1037                           if (i < AOP_SIZE(left)) {
1038                             if (pic16_sameRegs (AOP(left), AOP(result))) {
1039                               pic16_emitpcode (POC_ADDWFC, pic16_popGet (AOP(result), i));
1040                             } else {
1041                               pic16_emitpcode (POC_ADDFWC, pic16_popGet (AOP(left), i));
1042                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
1043                             }
1044                           } else {
1045                             // left is too short
1046                             pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), i));
1047                             if (!SPEC_USIGN(getSpec(operandType(left)))) {
1048                               // left operand is signed
1049                               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),AOP_SIZE(left)-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1050                               pic16_emitpcode(POC_COMF, pic16_popGet (AOP(result), i));
1051                             }
1052                             pic16_emitpcode (POC_ADDWFC, pic16_popGet (AOP(result), i));
1053                           }
1054                         } // for i
1055                         goto release;
1056                         
1057 #if 0
1058                         // add leftover bytes
1059                         if (SPEC_USIGN(getSpec(operandType(right)))) {
1060                                 // right is unsigned
1061                                 for(i=size; i< AOP_SIZE(result); i++) {
1062                                         if (pic16_sameRegs(AOP(left), AOP(result)))
1063                                         {
1064                                                 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
1065                                                 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
1066                                         } else { // not same
1067                                                 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
1068                                                 pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i));
1069                                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
1070                                         }
1071                                 }
1072                         } else {
1073                                 // right is signed
1074                                 for(i=size; i< AOP_SIZE(result); i++) {
1075                                         if(size < AOP_SIZE(left)) {
1076                                                 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
1077                                                 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1078                                                 pic16_emitpcode(POC_COMFW, pic16_popCopyReg(&pic16_pc_wreg));
1079                                                 if (pic16_sameRegs(AOP(left), AOP(result)))
1080                                                 {
1081                                                         pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
1082                                                 } else { // not same
1083                                                         pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i));
1084                                                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
1085                                                 }
1086                                         } else {
1087                                                 pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
1088                                                 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), i));
1089                                         }
1090                                 }
1091                         }
1092                         goto release;
1093 #endif
1094                 }
1095
1096         }
1097
1098         assert( 0 );
1099         // TODO:        anything from here to before "release:" is probably obsolete and should be removed
1100         //              when the regression tests are stable
1101
1102         if (AOP_SIZE(result) > AOP_SIZE(right)) {
1103                 int sign =  !(SPEC_USIGN(getSpec(operandType(left))) |
1104                                 SPEC_USIGN(getSpec(operandType(right))) );
1105
1106
1107                 /* Need to extend result to higher bytes */
1108                 size = AOP_SIZE(result) - AOP_SIZE(right) - 1;
1109
1110                 /* First grab the carry from the lower bytes */
1111                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
1112                 pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offset));
1113
1114
1115                 if(sign) {
1116                         /* Now this is really horrid. Gotta check the sign of the addends and propogate
1117                         * to the result */
1118
1119                         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1120                         pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offset));
1121                         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1122                         pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offset));
1123
1124                         /* if chars or ints or being signed extended to longs: */
1125                         if(size) {
1126                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
1127                                 pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1128                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
1129                         }
1130                 }
1131
1132                 offset++;
1133                 while(size--) {
1134       
1135                         if(sign)
1136                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
1137                         else
1138                                 pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offset));
1139
1140                         offset++;
1141                 }
1142         }
1143
1144
1145         //adjustArithmeticResult(ic);
1146
1147         release:
1148         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1149         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1150         pic16_freeAsmop(result,NULL,ic,TRUE);
1151 }
1152
1153 /*-----------------------------------------------------------------*/
1154 /* pic16_genMinusDec :- does subtraction with decrement if possible     */
1155 /*-----------------------------------------------------------------*/
1156 bool pic16_genMinusDec (iCode *ic)
1157 {
1158     unsigned int icount ;
1159     unsigned int size = pic16_getDataSize(IC_RESULT(ic));
1160
1161     FENTRY;
1162     /* will try to generate an increment */
1163     /* if the right side is not a literal 
1164     we cannot */
1165     if ((AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) || 
1166         (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) || 
1167         (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) )
1168         return FALSE ;
1169
1170     DEBUGpic16_emitcode ("; lit val","%d",(unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
1171
1172     /* if the literal value of the right hand side
1173     is greater than 4 then it is not worth it */
1174     if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1175         return FALSE ;
1176
1177     /* if decrement 16 bits in register */
1178     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1179         (size > 1) &&
1180         (icount == 1)) {
1181
1182       if(size == 2) { 
1183         pic16_emitpcode(POC_DECF,    pic16_popGet(AOP(IC_RESULT(ic)),LSB));
1184         emitSKPC;
1185         pic16_emitpcode(POC_DECF,    pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
1186
1187         pic16_emitcode("decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1188         pic16_emitcode("incfsz","%s,w",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1189         pic16_emitcode(" decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
1190       } else {
1191         /* size is 3 or 4 */
1192         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(IC_RESULT(ic)),LSB));
1193         pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_wreg));
1194         pic16_emitpcode(POC_SUBWFB_D1,   pic16_popGet(AOP(IC_RESULT(ic)),MSB16));
1195         pic16_emitpcode(POC_SUBWFB_D1,   pic16_popGet(AOP(IC_RESULT(ic)),MSB24));
1196
1197         pic16_emitcode("movlw","0xff");
1198         pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1199
1200         //emitSKPNC;
1201         pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
1202         //emitSKPNC;
1203         pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
1204
1205         if(size > 3) {
1206           pic16_emitpcode(POC_SUBWFB_D1,   pic16_popGet(AOP(IC_RESULT(ic)),MSB32));
1207
1208           pic16_emitcode("skpnc","");
1209           //emitSKPNC;
1210           pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
1211         }
1212
1213       }
1214
1215       return TRUE;
1216
1217     }
1218
1219     /* if the sizes are greater than 1 then we cannot */
1220     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1221         AOP_SIZE(IC_LEFT(ic)) > 1   )
1222         return FALSE ;
1223
1224     /* we can if the aops of the left & result match or
1225     if they are in registers and the registers are the
1226     same */
1227     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1228
1229       while (icount--) 
1230         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(IC_RESULT(ic)),0));
1231
1232         //pic16_emitcode ("decf","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1233
1234         return TRUE ;
1235     }
1236
1237     DEBUGpic16_emitcode ("; returning"," result=%s, left=%s",
1238                    pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
1239                    pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1240     if(size==1) {
1241
1242       pic16_emitcode("decf","%s,w",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1243       pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1244
1245       pic16_emitpcode(POC_DECFW,  pic16_popGet(AOP(IC_LEFT(ic)),0));
1246       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
1247
1248       return TRUE;
1249     }
1250
1251     return FALSE ;
1252 }
1253
1254 /*-----------------------------------------------------------------*/
1255 /* pic16_addSign - propogate sign bit to higher bytes                    */
1256 /*-----------------------------------------------------------------*/
1257 void pic16_addSign(operand *result, int offset, int sign)
1258 {
1259   int size = (pic16_getDataSize(result) - offset);
1260   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1261
1262   if(size > 0){
1263     if(sign && offset) {
1264
1265       if(size == 1) {
1266         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
1267         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1268         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offset));
1269       } else {
1270
1271         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
1272         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0, PO_GPR_REGISTER));
1273         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
1274         while(size--)
1275           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset+size));
1276
1277       }
1278     } else
1279       while(size--)
1280         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1281   }
1282 }
1283
1284 /*-----------------------------------------------------------------*/
1285 /* pic16_genMinusBits - generates code for subtraction  of two bits      */
1286 /*-----------------------------------------------------------------*/
1287 void pic16_genMinusBits (iCode *ic)
1288 {
1289     symbol *lbl = newiTempLabel(NULL);
1290
1291     FENTRY;
1292     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
1293         pic16_emitcode("mov","c,%s",AOP(IC_LEFT(ic))->aopu.aop_dir);
1294         pic16_emitcode("jnb","%s,%05d_DS_",AOP(IC_RIGHT(ic))->aopu.aop_dir,(lbl->key+100));
1295         pic16_emitcode("cpl","c");
1296         pic16_emitcode("","%05d_DS_:",(lbl->key+100));
1297         pic16_outBitC(IC_RESULT(ic));
1298     }
1299     else{
1300         pic16_emitcode("mov","c,%s",AOP(IC_RIGHT(ic))->aopu.aop_dir);
1301         pic16_emitcode("subb","a,acc");
1302         pic16_emitcode("jnb","%s,%05d_DS_",AOP(IC_LEFT(ic))->aopu.aop_dir,(lbl->key+100));
1303         pic16_emitcode("inc","a");
1304         pic16_emitcode("","%05d_DS_:",(lbl->key+100));
1305         pic16_aopPut(AOP(IC_RESULT(ic)),"a",0);
1306         pic16_addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
1307     }
1308 }
1309
1310 /*-----------------------------------------------------------------*/
1311 /* pic16_genMinus - generates code for subtraction                       */
1312 /*-----------------------------------------------------------------*/
1313 void pic16_genMinus (iCode *ic)
1314 {
1315   int size, offset = 0, same=0;
1316   unsigned long lit = 0L;
1317
1318     FENTRY;
1319   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1320   pic16_aopOp (IC_RIGHT(ic),ic,FALSE);
1321   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1322
1323   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY  &&
1324       AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1325     operand *t = IC_RIGHT(ic);
1326     IC_RIGHT(ic) = IC_LEFT(ic);
1327     IC_LEFT(ic) = t;
1328   }
1329
1330   DEBUGpic16_emitcode ("; ","result %s, left %s, right %s",
1331                    pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
1332                    pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
1333                    pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
1334
1335   /* special cases :- */
1336   /* if both left & right are in bit space */
1337   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1338       AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1339     pic16_genPlusBits (ic);
1340     goto release ;
1341   }
1342
1343   /* if I can do an decrement instead
1344      of subtract then GOOD for ME */
1345 //  if (pic16_genMinusDec (ic) == TRUE)
1346 //    goto release;   
1347
1348   size = pic16_getDataSize(IC_RESULT(ic));   
1349   same = pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)));
1350
1351   if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
1352     /* Add a literal to something else */
1353
1354     lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1355     lit = - (long)lit;
1356
1357     genAddLit ( ic,  lit);
1358     
1359 #if 0
1360     /* add the first byte: */
1361     pic16_emitcode("movlw","0x%x", lit & 0xff);
1362     pic16_emitcode("addwf","%s,f", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1363     pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(lit & 0xff));
1364     pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_LEFT(ic)),0));
1365
1366
1367     offset = 1;
1368     size--;
1369
1370     while(size-- > 0) {
1371
1372       lit >>= 8;
1373
1374       if(lit & 0xff) {
1375
1376         if((lit & 0xff) == 0xff) {
1377           pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(0xff));
1378           emitSKPC;
1379           pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
1380         } else {
1381           pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(lit & 0xff));
1382           emitSKPNC;
1383           pic16_emitpcode(POC_MOVLW,  pic16_popGetLit((lit+1) & 0xff));
1384           pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
1385         }
1386
1387       } else {
1388         /* do the rlf known zero trick here */
1389         pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(1));
1390         emitSKPNC;
1391         pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
1392       }
1393       offset++;
1394     }
1395 #endif
1396   } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1397     // bit subtraction
1398
1399     pic16_emitcode(";bitsub","right is bit: %s",pic16_aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1400     pic16_emitcode(";bitsub","left is bit: %s",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1401     pic16_emitcode(";bitsub","result is bit: %s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1402
1403     /* here we are subtracting a bit from a char or int */
1404     if(size == 1) {
1405       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1406
1407         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1408         pic16_emitpcode(POC_DECF ,  pic16_popGet(AOP(IC_RESULT(ic)),0));
1409
1410         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
1411                  AOP(IC_RIGHT(ic))->aopu.aop_dir,
1412                  AOP(IC_RIGHT(ic))->aopu.aop_dir);
1413         pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1414       } else {
1415
1416         if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1417           pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1418           pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
1419         }else  if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
1420               (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1421
1422           lit = (unsigned long)floatFromVal(AOP(IC_LEFT(ic))->aopu.aop_lit);
1423
1424           if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1425             if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
1426               if(lit & 1) {
1427                 pic16_emitpcode(POC_MOVLW , pic16_popGetLit(1));
1428                 pic16_emitpcode(POC_XORWF , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1429               }
1430             }else{
1431               pic16_emitpcode(POC_BCF ,     pic16_popGet(AOP(IC_RESULT(ic)),0));
1432               if(lit & 1) 
1433                 pic16_emitpcode(POC_BTFSS , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1434               else
1435                 pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1436               pic16_emitpcode(POC_BSF ,     pic16_popGet(AOP(IC_RESULT(ic)),0));
1437             }
1438             goto release;
1439           } else {
1440             pic16_emitpcode(POC_MOVLW , pic16_popGetLit(lit & 0xff));
1441             pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1442             pic16_emitpcode(POC_MOVLW , pic16_popGetLit((lit-1) & 0xff));
1443             //pic16_emitpcode(POC_MOVWF , pic16_popGet(AOP(IC_RESULT(ic)),0));
1444
1445           }
1446
1447         } else {
1448           pic16_mov2w(AOP(IC_LEFT(ic)),0);
1449           pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
1450           pic16_emitpcode(POC_DECFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
1451         }
1452           
1453         if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
1454             
1455           pic16_emitpcode(POC_MOVWF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
1456
1457         } else  {
1458           pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
1459 /*
1460           pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1461           emitSKPZ;
1462           pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1463 */
1464         }
1465
1466       }
1467
1468     }
1469   } else   if(// (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) || 
1470               (AOP(IC_LEFT(ic))->type == AOP_LIT) &&
1471               (AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC)) {
1472
1473     lit = (unsigned long)floatFromVal(AOP(IC_LEFT(ic))->aopu.aop_lit);
1474     DEBUGpic16_emitcode ("; left is lit","line %d result %s, left %s, right %s",__LINE__,
1475                    pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
1476                    pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
1477                    pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
1478
1479
1480     if( (size == 1) && ((lit & 0xff) == 0) ) {
1481       /* res = 0 - right */
1482       if (pic16_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
1483         pic16_emitpcode(POC_NEGF,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
1484       } else { 
1485         pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(IC_RIGHT(ic)),0));
1486         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
1487         pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
1488       }
1489       goto release;
1490     }
1491
1492     pic16_mov2w(AOP(IC_RIGHT(ic)),0);
1493     pic16_emitpcode(POC_SUBLW, pic16_popGetLit(lit & 0xff));    
1494     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1495
1496
1497     offset = 0;
1498     while(--size) {
1499       lit >>= 8;
1500       offset++;
1501       if(same) {
1502         // here we have x = lit - x   for sizeof(x)>1
1503         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1504         pic16_emitpcode(POC_SUBFWB_D1,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
1505       } else {
1506         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
1507         pic16_emitpcode(POC_SUBFWB_D0,  pic16_popGet(AOP(IC_RIGHT(ic)),offset));
1508         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
1509       }
1510     }
1511   
1512
1513   } else {
1514
1515     DEBUGpic16_emitcode ("; ","line %d result %s, left %s, right %s",__LINE__,
1516                    pic16_AopType(AOP_TYPE(IC_RESULT(ic))),
1517                    pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
1518                    pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
1519
1520     if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1521       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1522       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
1523       pic16_emitpcode(POC_SUBLW, pic16_popGetLit(0));
1524       if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
1525         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1526     } else {
1527
1528         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1529         if(AOP_TYPE(IC_RIGHT(ic)) != AOP_ACC) 
1530           pic16_mov2w(AOP(IC_RIGHT(ic)),0);
1531
1532         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
1533           pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(IC_LEFT(ic)),0));
1534         else {
1535           if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
1536               (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1537             pic16_emitpcode(POC_SUBLW, pic16_popGet(AOP(IC_LEFT(ic)),0));
1538           } else {
1539             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
1540           }
1541           if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
1542             if ( AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1543               pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
1544               emitSKPZ;
1545               pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
1546             }else
1547               pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1548           }
1549         }
1550     }
1551
1552     /*
1553       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1554
1555       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1556       pic16_emitpcode(POC_SUBFW,  pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1557       } else {
1558       pic16_emitpcode(POC_SUBFW,  pic16_popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1559       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1560       }
1561     */
1562     offset = 1;
1563     size--;
1564
1565     while(size--){
1566       if (offset < AOP_SIZE(IC_RIGHT(ic)))
1567         pic16_mov2w(AOP(IC_RIGHT(ic)),offset);
1568       else {
1569         pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
1570         if (!SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1571           // signed -- sign extend the right operand
1572           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));
1573           pic16_emitpcode (POC_COMF, pic16_popCopyReg (&pic16_pc_wreg));
1574         }
1575       }
1576       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1577         pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1578       } else {
1579         if (offset < AOP_SIZE(IC_LEFT(ic))) {
1580           pic16_emitpcode(POC_SUBWFB_D0,  pic16_popGet(AOP(IC_LEFT(ic)),offset));
1581           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
1582         } else {
1583           // zero extend the left operand
1584           pic16_emitpcode (POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)), offset));
1585           if (!SPEC_USIGN(operandType(IC_LEFT(ic)))) {
1586             // signed -- sign extend the left operand
1587             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));
1588             pic16_emitpcode (POC_COMF, pic16_popGet(AOP(IC_RESULT(ic)), offset)); // keep CARRY/#BORROW bit intact!
1589           }
1590           pic16_emitpcode(POC_SUBWFB_D1, pic16_popGet(AOP(IC_RESULT(ic)),offset));
1591         }
1592       } 
1593       offset++;
1594     }
1595
1596   }
1597
1598
1599   //    adjustArithmeticResult(ic);
1600         
1601  release:
1602   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1603   pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1604   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1605 }
1606
1607
1608 /*-----------------------------------------------------------------*
1609  * pic_genUMult8XLit_8 - unsigned multiplication of two 8-bit numbers.
1610  * 
1611  * 
1612  *-----------------------------------------------------------------*/
1613 void pic16_genUMult8XLit_8 (operand *left,
1614                              operand *right,
1615                              operand *result)
1616 {
1617   unsigned int lit;
1618   int same;
1619   int size = AOP_SIZE(result);
1620   int i;
1621
1622     FENTRY;
1623         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
1624
1625         if (AOP_TYPE(right) != AOP_LIT){
1626                 fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
1627                 exit(1);
1628         }
1629
1630         lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
1631         lit &= 0xff;
1632         pic16_emitpcomment("Unrolled 8 X 8 multiplication");
1633         pic16_emitpcomment("FIXME: the function does not support result==WREG");
1634         
1635         same = pic16_sameRegs(AOP(left), AOP(result));
1636         if(same) {
1637                 switch(lit) {
1638                         case 0:
1639                                 while (size--) {
1640                                   pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),size));
1641                                 } // while
1642                                 return;
1643                         case 2:
1644                                 // its faster to left shift
1645                                 for (i=1; i < size; i++) {
1646                                   pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
1647                                 } // for
1648                                 emitCLRC;
1649                                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
1650                                 if (size > 1)
1651                                   pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1));
1652                                 return;
1653
1654                         default:
1655                                 if(AOP_TYPE(left) != AOP_ACC)
1656                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
1657                                 pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit));
1658                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
1659                                         pic16_popGet(AOP(result), 0)));
1660                                 if (size > 1) {
1661                                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
1662                                                                             pic16_popGet(AOP(result), 1)));
1663                                   for (i=2; i < size; i++) {
1664                                     pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
1665                                   } // for
1666                                 } // if
1667                                 return;
1668                 }
1669         } else {
1670                 // operands different
1671                 switch(lit) {
1672                         case 0:
1673                                 while (size--) {
1674                                   pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),size));
1675                                 } // while
1676                                 return;
1677                         case 2:
1678                                 for (i=1; i < size; i++) {
1679                                   pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
1680                                 } // for
1681                                 emitCLRC;
1682                                 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
1683                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
1684                                 if (size > 1)
1685                                   pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1));
1686                                 return;
1687                         default:
1688                                 if(AOP_TYPE(left) != AOP_ACC)
1689                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
1690                                 pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit));
1691                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
1692                                         pic16_popGet(AOP(result), 0)));
1693
1694                                 if (size > 1) {
1695                                   pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
1696                                                                             pic16_popGet(AOP(result), 1)));
1697                                   for (i=2; i < size; i++) {
1698                                     pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
1699                                   } // for
1700                                 } // if
1701                                 return;
1702                 }
1703         }
1704 }
1705
1706 /*-----------------------------------------------------------------------*
1707  * pic_genUMult16XLit_16 - unsigned multiplication of two 16-bit numbers *
1708  *-----------------------------------------------------------------------*/
1709 void pic16_genUMult16XLit_16 (operand *left,
1710                              operand *right,
1711                              operand *result)
1712 {
1713   pCodeOp *pct1, *pct2, *pct3, *pct4;
1714   unsigned int lit;
1715   int same;
1716
1717
1718     FENTRY;
1719     
1720         if (AOP_TYPE(right) != AOP_LIT){
1721                 fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
1722                 exit(1);
1723         }
1724
1725         lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
1726         lit &= 0xffff;
1727
1728         same = pic16_sameRegs(AOP(left), AOP(result));
1729         if(same) {
1730                 switch(lit) {
1731                         case 0:
1732                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
1733                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),1));
1734                                 return;
1735                         case 2:
1736                                 // its faster to left shift
1737                                 emitCLRC;
1738                                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
1739                                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),1));
1740                                 return;
1741
1742                         default: {
1743                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1744
1745                                 pct1 = pic16_popGetTempReg(1);
1746                                 pct2 = pic16_popGetTempReg(1);
1747                                 pct3 = pic16_popGetTempReg(1);
1748                                 pct4 = pic16_popGetTempReg(1);
1749
1750                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
1751                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
1752                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1753                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
1754                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1755                                         pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
1756                                         
1757                                 /* WREG still holds the low literal */
1758                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
1759                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1760                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
1761                                         
1762                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
1763                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
1764                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1765                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
1766                                         
1767                                 /* load result */
1768                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1769                                         pct1, pic16_popGet(AOP(result), 0)));
1770                                 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct2));
1771                                 pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
1772                                 pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
1773                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
1774
1775                                 pic16_popReleaseTempReg(pct4,1);
1776                                 pic16_popReleaseTempReg(pct3,1);
1777                                 pic16_popReleaseTempReg(pct2,1);
1778                                 pic16_popReleaseTempReg(pct1,1);
1779                         }; return;
1780                 }
1781         } else {
1782                 // operands different
1783                 switch(lit) {
1784                         case 0:
1785                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0));
1786                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
1787                                 return;
1788                         case 2:
1789                                 emitCLRC;
1790                                 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
1791                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
1792                                 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 1));
1793                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
1794                                 return;
1795                         default: {
1796                                         
1797                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
1798                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
1799                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1800                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
1801                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1802                                         pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
1803                                         
1804                                 /* WREG still holds the low literal */
1805                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
1806                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
1807                                 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
1808                                         
1809                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
1810                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
1811                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
1812                                 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
1813
1814                         }; return;
1815                 }
1816         }
1817 }
1818
1819
1820 /*-----------------------------------------------------------------*
1821  * genUMult8X8_8 - unsigned multiplication of two 8-bit numbers.
1822  * 
1823  * 
1824  *-----------------------------------------------------------------*/
1825 void pic16_genUMult8X8_8 (operand *left,
1826                            operand *right,
1827                            operand *result)
1828
1829 {
1830   FENTRY;
1831   
1832
1833         if (AOP_TYPE(right) == AOP_LIT) {
1834                 pic16_genUMult8XLit_8(left,right,result);
1835           return;
1836         }
1837
1838         /* cases:
1839                 A = A x B       B = A x B
1840                 A = B x C
1841                 W = A x B
1842                 W = W x B       W = B x W
1843         */
1844         /* if result == right then exchange left and right */
1845         if(pic16_sameRegs(AOP(result), AOP(right))) {
1846           operand *tmp;
1847                 tmp = left;
1848                 left = right;
1849                 right = tmp;
1850         }
1851                 
1852         if(AOP_TYPE(left) != AOP_ACC) {
1853                 // left is not WREG
1854                 if(AOP_TYPE(right) != AOP_ACC) {
1855                         pic16_mov2w(AOP(left), 0);
1856                         pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
1857                 } else {
1858                         pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
1859                 }
1860         } else {
1861                 // left is WREG, right cannot be WREG (or can?!)
1862                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(right), 0));
1863         }
1864         
1865         /* result is in PRODL:PRODH */
1866         if(AOP_TYPE(result) != AOP_ACC) {
1867                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
1868                         pic16_popGet(AOP(result), 0)));
1869
1870
1871                 if(AOP_SIZE(result)>1) {
1872                   int i;
1873
1874                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
1875                         pic16_popGet(AOP(result), 1)));
1876                         
1877                         for(i=2;i<AOP_SIZE(result);i++)
1878                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
1879                 }
1880         } else {
1881                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
1882         }
1883 }
1884
1885 /*------------------------------------------------------------------*
1886  * genUMult16X16_16 - unsigned multiplication of two 16-bit numbers *
1887  *------------------------------------------------------------------*/
1888 void pic16_genUMult16X16_16 (operand *left,
1889                            operand *right,
1890                            operand *result)
1891
1892 {
1893   pCodeOp *pct1, *pct2, *pct3, *pct4;
1894
1895     FENTRY;
1896
1897
1898         if (AOP_TYPE(right) == AOP_LIT) {
1899                 pic16_genUMult8XLit_8(left,right,result);
1900           return;
1901         }
1902
1903         /* cases:
1904                 A = A x B       B = A x B
1905                 A = B x C
1906         */
1907         /* if result == right then exchange left and right */
1908         if(pic16_sameRegs(AOP(result), AOP(right))) {
1909           operand *tmp;
1910                 tmp = left;
1911                 left = right;
1912                 right = tmp;
1913         }
1914
1915
1916         if(pic16_sameRegs(AOP(result), AOP(left))) {
1917
1918                 pct1 = pic16_popGetTempReg(1);
1919                 pct2 = pic16_popGetTempReg(1);
1920                 pct3 = pic16_popGetTempReg(1);
1921                 pct4 = pic16_popGetTempReg(1);
1922
1923                 pic16_mov2w(AOP(left), 0);
1924                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
1925                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1926                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
1927                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1928                         pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
1929                                         
1930                 /* WREG still holds the lower left */
1931                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
1932                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1933                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
1934                 
1935                 pic16_mov2w(AOP(left), 1);
1936                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
1937                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1938                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
1939                                         
1940                 /* load result */
1941                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1942                         pic16_pCodeOpCopy( pct1 ), pic16_popGet(AOP(result), 0)));
1943                 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy( pct2 ));
1944                 pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
1945                 pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
1946                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
1947
1948                 pic16_popReleaseTempReg( pct4, 1 );
1949                 pic16_popReleaseTempReg( pct3, 1 );
1950                 pic16_popReleaseTempReg( pct2, 1 );
1951                 pic16_popReleaseTempReg( pct1, 1 );
1952
1953         } else {
1954
1955                 pic16_mov2w(AOP(left), 0);
1956                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
1957                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1958                         pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
1959                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
1960                         pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
1961
1962                 /* WREG still holds the lower left */
1963                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
1964                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
1965                 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
1966                 
1967                 pic16_mov2w(AOP(left), 1);
1968                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
1969                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
1970                 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
1971         }       
1972 }
1973
1974
1975 void pic16_genSMult16X16_16(operand *left,
1976                         operand *right,
1977                         operand *result)
1978 {
1979
1980 }
1981
1982 #if 0
1983 /*-----------------------------------------------------------------*
1984  * pic16_genSMult8X8_16 - signed multiplication of two 8-bit numbers
1985  *
1986  *  this routine will call the unsigned multiply routine and then
1987  * post-fix the sign bit.
1988  *-----------------------------------------------------------------*/
1989 void pic16_genSMult8X8_8 (operand *left,
1990                            operand *right,
1991                            operand *result,
1992                            pCodeOpReg *result_hi)
1993 {
1994         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1995
1996
1997   if(!result_hi) {
1998     result_hi = PCOR(pic16_popGet(AOP(result),1));
1999   }
2000
2001
2002   pic16_genUMult8X8_8(left,right,result);
2003
2004   
2005 #if 0
2006   pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),7,0, PO_GPR_REGISTER));
2007   pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(result_hi));
2008   pic16_mov2w(AOP(left),0);
2009   pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),7,0, PO_GPR_REGISTER));
2010   pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(result),1));
2011 #endif
2012 }
2013 #endif
2014
2015 /*-----------------------------------------------------------------*
2016  * pic16_genMult8X8_8 - multiplication of two 8-bit numbers        *
2017  *-----------------------------------------------------------------*/
2018 void pic16_genMult8X8_8 (operand *left,
2019                          operand *right,
2020                          operand *result)
2021 {
2022   FENTRY;
2023   
2024   if(AOP_TYPE(right) == AOP_LIT)
2025     pic16_genUMult8XLit_8(left,right,result);
2026   else
2027     pic16_genUMult8X8_8(left,right,result);
2028 }
2029
2030
2031 /*-----------------------------------------------------------------*
2032  * pic16_genMult16X16_16 - multiplication of two 16-bit numbers    *
2033  *-----------------------------------------------------------------*/
2034 void pic16_genMult16X16_16 (operand *left,
2035                          operand *right,
2036                          operand *result)
2037 {
2038   FENTRY;
2039   
2040   if (AOP_TYPE(right) == AOP_LIT)
2041     pic16_genUMult16XLit_16(left,right,result);
2042   else
2043     pic16_genUMult16X16_16(left,right,result);
2044 }
2045
2046
2047
2048
2049 /*-----------------------------------------------------------------------*
2050  * pic_genUMult32XLit_32 - unsigned multiplication of two 32-bit numbers *
2051  *-----------------------------------------------------------------------*/
2052 void pic16_genUMult32XLit_32 (operand *left,
2053                              operand *right,
2054                              operand *result)
2055 {
2056   pCodeOp *pct1, *pct2, *pct3, *pct4;
2057   unsigned int lit;
2058   int same;
2059
2060
2061     FENTRY;
2062     
2063         if (AOP_TYPE(right) != AOP_LIT){
2064                 fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
2065                 exit(1);
2066         }
2067
2068         lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
2069         lit &= 0xffff;
2070
2071         same = pic16_sameRegs(AOP(left), AOP(result));
2072         if(same) {
2073                 switch(lit) {
2074                         case 0:
2075                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
2076                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),1));
2077                                 return;
2078                         case 2:
2079                                 // its faster to left shift
2080                                 emitCLRC;
2081                                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
2082                                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),1));
2083                                 return;
2084
2085                         default: {
2086                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2087
2088                                 pct1 = pic16_popGetTempReg(1);
2089                                 pct2 = pic16_popGetTempReg(1);
2090                                 pct3 = pic16_popGetTempReg(1);
2091                                 pct4 = pic16_popGetTempReg(1);
2092
2093                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
2094                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
2095                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2096                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
2097                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2098                                         pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
2099                                         
2100                                 /* WREG still holds the low literal */
2101                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
2102                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2103                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
2104                                         
2105                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
2106                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
2107                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2108                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
2109                                         
2110                                 /* load result */
2111                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2112                                         pct1, pic16_popGet(AOP(result), 0)));
2113                                 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct2));
2114                                 pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
2115                                 pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
2116                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
2117
2118                                 pic16_popReleaseTempReg( pct4, 1 );
2119                                 pic16_popReleaseTempReg( pct3, 1 );
2120                                 pic16_popReleaseTempReg( pct2, 1 );
2121                                 pic16_popReleaseTempReg( pct1, 1 );
2122                         }; return;
2123                 }
2124         } else {
2125                 // operands different
2126                 switch(lit) {
2127                         case 0:
2128                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0));
2129                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
2130                                 return;
2131                         case 2:
2132                                 emitCLRC;
2133                                 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
2134                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
2135                                 pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 1));
2136                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
2137                                 return;
2138                         default: {
2139                                         
2140                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
2141                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
2142                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2143                                         pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
2144                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2145                                         pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
2146                                         
2147                                 /* WREG still holds the low literal */
2148                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
2149                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
2150                                 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
2151                                         
2152                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
2153                                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
2154                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
2155                                 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
2156
2157                         }; return;
2158                 }
2159         }
2160 }
2161
2162
2163 /*------------------------------------------------------------------*
2164  * genUMult32X32_32 - unsigned multiplication of two 32-bit numbers *
2165  *------------------------------------------------------------------*/
2166 void pic16_genUMult32X32_32 (operand *left,
2167                            operand *right,
2168                            operand *result)
2169
2170 {
2171   pCodeOp *pct1, *pct2, *pct3, *pct4;
2172
2173     FENTRY;
2174     
2175         if (AOP_TYPE(right) == AOP_LIT) {
2176                 pic16_genUMult8XLit_8(left,right,result);
2177           return;
2178         }
2179
2180         /* cases:
2181                 A = A x B       B = A x B
2182                 A = B x C
2183         */
2184         /* if result == right then exchange left and right */
2185         if(pic16_sameRegs(AOP(result), AOP(right))) {
2186           operand *tmp;
2187                 tmp = left;
2188                 left = right;
2189                 right = tmp;
2190         }
2191
2192
2193         if(pic16_sameRegs(AOP(result), AOP(left))) {
2194
2195                 pct1 = pic16_popGetTempReg(1);
2196                 pct2 = pic16_popGetTempReg(1);
2197                 pct3 = pic16_popGetTempReg(1);
2198                 pct4 = pic16_popGetTempReg(1);
2199
2200                 pic16_mov2w(AOP(left), 0);
2201                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
2202                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2203                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
2204                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2205                         pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
2206                                         
2207                 /* WREG still holds the lower left */
2208                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
2209                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2210                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
2211                 
2212                 pic16_mov2w(AOP(left), 1);
2213                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
2214                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2215                         pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
2216                                         
2217                 /* load result */
2218                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2219                         pic16_pCodeOpCopy( pct1 ), pic16_popGet(AOP(result), 0)));
2220                 pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy( pct2 ));
2221                 pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
2222                 pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
2223                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
2224
2225                 pic16_popReleaseTempReg( pct4, 1 );
2226                 pic16_popReleaseTempReg( pct3, 1 );
2227                 pic16_popReleaseTempReg( pct2, 1 );
2228                 pic16_popReleaseTempReg( pct1, 1 );
2229
2230         } else {
2231
2232                 pic16_mov2w(AOP(left), 0);
2233                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
2234                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2235                         pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
2236                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2237                         pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
2238
2239                 /* WREG still holds the lower left */
2240                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
2241                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
2242                 pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
2243                 
2244                 pic16_mov2w(AOP(left), 1);
2245                 pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
2246                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
2247                 pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
2248         }       
2249 }
2250
2251
2252 /*-----------------------------------------------------------------*
2253  * pic16_genMult32X32_32 - multiplication of two 32-bit numbers    *
2254  *-----------------------------------------------------------------*/
2255 void pic16_genMult32X32_32 (operand *left,
2256                          operand *right,
2257                          operand *result)
2258 {
2259   FENTRY;
2260   
2261   if (AOP_TYPE(right) == AOP_LIT)
2262     pic16_genUMult32XLit_32(left,right,result);
2263   else
2264     pic16_genUMult32X32_32(left,right,result);
2265 }
2266
2267
2268
2269
2270
2271
2272
2273 #if 0
2274 /*-----------------------------------------------------------------*/
2275 /* constMult - generates code for multiplication by a constant     */
2276 /*-----------------------------------------------------------------*/
2277 void genMultConst(unsigned C)
2278 {
2279
2280   unsigned lit;
2281   unsigned sr3; // Shift right 3
2282   unsigned mask;
2283
2284   int size = 1;
2285
2286   /*
2287     Convert a string of 3 binary 1's in the lit into
2288     0111 = 1000 - 1;
2289   */
2290
2291   mask = 7 << ( (size*8) - 3);
2292   lit = C;
2293   sr3 = 0;
2294
2295   while(mask < (1<<size*8)) {
2296
2297     if( (mask & lit) == lit) {
2298       unsigned lsb;
2299
2300       /* We found 3 (or more) consecutive 1's */
2301
2302       lsb = mask & ~(mask & (mask-1));  // lsb of mask.
2303
2304       consecutive_bits = ((lit + lsb) & lit) ^ lit;
2305
2306       lit ^= consecutive_bits;
2307
2308       mask <<= 3;
2309
2310       sr3 |= (consecutive + lsb);
2311
2312     }
2313
2314     mask >>= 1;
2315
2316   }
2317
2318 }
2319
2320 #endif