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