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