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