* src/pic/gen.c,
[fw/sdcc] / src / pic / genarith.c
1 /*-------------------------------------------------------------------------
2   genarith.c - source file for code generation - arithmetic 
3   
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   
9   This program is free software; you can redistribute it and/or modify it
10   under the terms of the GNU General Public License as published by the
11   Free Software Foundation; either version 2, or (at your option) any
12   later version.
13   
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18   
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22   
23   In other words, you are welcome to use, share and improve this program.
24   You are forbidden to forbid anyone else to use, share and improve
25   what you give them.   Help stamp out software-hoarding!
26   
27   Notes:
28   000123 mlh  Moved aopLiteral to SDCCglue.c to help the split
29       Made everything static
30 -------------------------------------------------------------------------*/
31
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "SDCCglobl.h"
37 #include "newalloc.h"
38
39 #if defined(_MSC_VER) && (_MSC_VER < 1300)
40 #define __FUNCTION__    __FILE__
41 #endif
42
43 #include "common.h"
44 #include "SDCCpeeph.h"
45 #include "ralloc.h"
46 #include "pcode.h"
47 #include "gen.h"
48
49
50 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
51 void DEBUGpic14_AopType(int line_no, operand *left, operand *right, operand *result);
52
53 const char *AopType(short type)
54 {
55         switch(type) {
56         case AOP_LIT:
57                 return "AOP_LIT";
58                 break;
59         case AOP_REG:
60                 return "AOP_REG";
61                 break;
62         case AOP_DIR:
63                 return "AOP_DIR";
64                 break;
65         case AOP_STK:
66                 return "AOP_STK";
67                 break;
68         case AOP_IMMD:
69                 return "AOP_IMMD";
70                 break;
71         case AOP_STR:
72                 return "AOP_STR";
73                 break;
74         case AOP_CRY:
75                 return "AOP_CRY";
76                 break;
77         case AOP_PCODE:
78                 return "AOP_PCODE";
79                 break;
80         }
81         
82         return "BAD TYPE";
83 }
84
85 void DebugAop(asmop *aop)
86 {
87         if(!aop)
88                 return;
89         printf("%s\n",AopType(aop->type));
90         printf(" current offset: %d\n",aop->coff);
91         printf("           size: %d\n",aop->size);
92         
93         switch(aop->type) {
94         case AOP_LIT:
95                 printf("          name: %s\n",aop->aopu.aop_lit->name);
96                 break;
97         case AOP_REG:
98                 printf("          name: %s\n",aop->aopu.aop_reg[0]->name);
99                 break;
100         case AOP_CRY:
101         case AOP_DIR:
102                 printf("          name: %s\n",aop->aopu.aop_dir);
103                 break;
104         case AOP_STK:
105                 printf("   Stack offset: %d\n",aop->aopu.aop_stk);
106                 break;
107         case AOP_IMMD:
108                 printf("     immediate: %s\n",aop->aopu.aop_immd);
109                 break;
110         case AOP_STR:
111                 printf("    aop_str[0]: %s\n",aop->aopu.aop_str[0]);
112                 break;
113         case AOP_PCODE:
114                 //printpCode(stdout,aop->aopu.pcop);
115                 break;
116         }
117 }
118
119 const char *pCodeOpType(  pCodeOp *pcop)
120 {
121         
122         if(pcop) {
123                 
124                 switch(pcop->type) {
125                         
126                 case  PO_NONE:
127                         return "PO_NONE";
128                 case  PO_W:
129                         return  "PO_W";
130                 case  PO_STATUS:
131                         return  "PO_STATUS";
132                 case  PO_FSR:
133                         return  "PO_FSR";
134                 case  PO_INDF:
135                         return  "PO_INDF";
136                 case  PO_INTCON:
137                         return  "PO_INTCON";
138                 case  PO_GPR_REGISTER:
139                         return  "PO_GPR_REGISTER";
140                 case  PO_GPR_POINTER:
141                         return  "PO_GPR_POINTER";
142                 case  PO_GPR_BIT:
143                         return  "PO_GPR_BIT";
144                 case  PO_GPR_TEMP:
145                         return  "PO_GPR_TEMP";
146                 case  PO_SFR_REGISTER:
147                         return  "PO_SFR_REGISTER";
148                 case  PO_PCL:
149                         return  "PO_PCL";
150                 case  PO_PCLATH:
151                         return  "PO_PCLATH";
152                 case  PO_LITERAL:
153                         return  "PO_LITERAL";
154                 case  PO_IMMEDIATE:
155                         return  "PO_IMMEDIATE";
156                 case  PO_DIR:
157                         return  "PO_DIR";
158                 case  PO_CRY:
159                         return  "PO_CRY";
160                 case  PO_BIT:
161                         return  "PO_BIT";
162                 case  PO_STR:
163                         return  "PO_STR";
164                 case  PO_LABEL:
165                         return  "PO_LABEL";
166                 case  PO_WILD:
167                         return  "PO_WILD";
168                 }
169         }
170         
171         return "BAD PO_TYPE";
172 }
173
174 /*-----------------------------------------------------------------*/
175 /* genPlusIncr :- does addition with increment if possible         */
176 /*-----------------------------------------------------------------*/
177 bool genPlusIncr (iCode *ic)
178 {
179         unsigned int icount ;
180         unsigned int size = pic14_getDataSize(IC_RESULT(ic));
181         FENTRY;
182         
183         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
184         DEBUGpic14_emitcode ("; ","result %s, left %s, right %s",
185                 AopType(AOP_TYPE(IC_RESULT(ic))),
186                 AopType(AOP_TYPE(IC_LEFT(ic))),
187                 AopType(AOP_TYPE(IC_RIGHT(ic))));
188         
189         /* will try to generate an increment */
190         /* if the right side is not a literal 
191         we cannot */
192         if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
193                 return FALSE ;
194         
195         DEBUGpic14_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
196         /* if the literal value of the right hand side
197         is greater than 1 then it is faster to add */
198         if ((icount = (unsigned int) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
199                 return FALSE ;
200         
201         /* if increment 16 bits in register */
202         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
203                 (icount == 1)) {
204                 
205                 int offset = MSB16;
206                 
207                 emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),LSB));
208                 //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
209                 
210                 while(--size) {
211                         emitSKPNZ;
212                         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset++));
213                         //pic14_emitcode(" incf","%s,f",aopGet(AOP(IC_RESULT(ic)),offset++,FALSE,FALSE));
214                 }
215                 
216                 return TRUE;
217         }
218         
219         DEBUGpic14_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
220         /* if left is in accumulator  - probably a bit operation*/
221         if( strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a")  &&
222                 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
223                 
224                 emitpcode(POC_BCF, popGet(AOP(IC_RESULT(ic)),0));
225                 pic14_emitcode("bcf","(%s >> 3), (%s & 7)",
226                         AOP(IC_RESULT(ic))->aopu.aop_dir,
227                         AOP(IC_RESULT(ic))->aopu.aop_dir);
228                 if(icount)
229                         emitpcode(POC_XORLW,popGetLit(1));
230                 //pic14_emitcode("xorlw","1");
231                 else
232                         emitpcode(POC_ANDLW,popGetLit(1));
233                 //pic14_emitcode("andlw","1");
234                 
235                 emitSKPZ;
236                 emitpcode(POC_BSF, popGet(AOP(IC_RESULT(ic)),0));
237                 pic14_emitcode("bsf","(%s >> 3), (%s & 7)",
238                         AOP(IC_RESULT(ic))->aopu.aop_dir,
239                         AOP(IC_RESULT(ic))->aopu.aop_dir);
240                 
241                 return TRUE;
242         }
243         
244         
245         
246         /* if the sizes are greater than 1 then we cannot */
247         if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
248                 AOP_SIZE(IC_LEFT(ic)) > 1   )
249                 return FALSE ;
250         
251         /* If we are incrementing the same register by two: */
252         
253         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
254                 
255                 while (icount--) 
256                         emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),0));
257                 //pic14_emitcode("incf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
258                 
259                 return TRUE ;
260         }
261         
262         DEBUGpic14_emitcode ("; ","couldn't increment ");
263         
264         return FALSE ;
265 }
266
267 /*-----------------------------------------------------------------*/
268 /* pic14_outBitAcc - output a bit in acc                                 */
269 /*-----------------------------------------------------------------*/
270 void pic14_outBitAcc(operand *result)
271 {
272         symbol *tlbl = newiTempLabel(NULL);
273         /* if the result is a bit */
274         FENTRY;
275         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
276         
277         if (AOP_TYPE(result) == AOP_CRY){
278                 aopPut(AOP(result),"a",0);
279         }
280         else {
281                 pic14_emitcode("jz","%05d_DS_",tlbl->key+100);
282                 pic14_emitcode("mov","a,#01");
283                 pic14_emitcode("","%05d_DS_:",tlbl->key+100);
284                 pic14_outAcc(result);
285         }
286 }
287
288 #if 0
289 /* This is the original version of this code.
290 *
291 * This is being kept around for reference, 
292 * because I am not entirely sure I got it right...
293 */
294 static void adjustArithmeticResult(iCode *ic)
295 {
296         if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
297                 AOP_SIZE(IC_LEFT(ic)) == 3   &&
298                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
299                 aopPut(AOP(IC_RESULT(ic)),
300                 aopGet(AOP(IC_LEFT(ic)),2,FALSE,FALSE),
301                 2);
302         
303         if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
304                 AOP_SIZE(IC_RIGHT(ic)) == 3   &&
305                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
306                 aopPut(AOP(IC_RESULT(ic)),
307                 aopGet(AOP(IC_RIGHT(ic)),2,FALSE,FALSE),
308                 2);
309         
310         if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
311                 AOP_SIZE(IC_LEFT(ic)) < 3    &&
312                 AOP_SIZE(IC_RIGHT(ic)) < 3   &&
313                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
314                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
315                 char buffer[5];
316                 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
317                 aopPut(AOP(IC_RESULT(ic)),buffer,2);
318         }
319 }
320 //#else
321 /* This is the pure and virtuous version of this code.
322 * I'm pretty certain it's right, but not enough to toss the old 
323 * code just yet...
324 */
325 static void adjustArithmeticResult(iCode *ic)
326 {
327         if (opIsGptr(IC_RESULT(ic)) &&
328                 opIsGptr(IC_LEFT(ic))   &&
329                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
330         {
331                 aopPut(AOP(IC_RESULT(ic)),
332                         aopGet(AOP(IC_LEFT(ic)), GPTRSIZE - 1,FALSE,FALSE),
333                         GPTRSIZE - 1);
334         }
335         
336         if (opIsGptr(IC_RESULT(ic)) &&
337                 opIsGptr(IC_RIGHT(ic))   &&
338                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
339         {
340                 aopPut(AOP(IC_RESULT(ic)),
341                         aopGet(AOP(IC_RIGHT(ic)),GPTRSIZE - 1,FALSE,FALSE),
342                         GPTRSIZE - 1);
343         }
344         
345         if (opIsGptr(IC_RESULT(ic))      &&
346                 AOP_SIZE(IC_LEFT(ic)) < GPTRSIZE   &&
347                 AOP_SIZE(IC_RIGHT(ic)) < GPTRSIZE  &&
348                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))) &&
349                 !pic14_sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic)))) {
350                 char buffer[5];
351                 sprintf(buffer,"#%d",pointerCode(getSpec(operandType(IC_LEFT(ic)))));
352                 aopPut(AOP(IC_RESULT(ic)),buffer,GPTRSIZE - 1);
353         }
354 }
355 #endif
356
357 /*-----------------------------------------------------------------*/
358 /* genAddlit - generates code for addition                         */
359 /*-----------------------------------------------------------------*/
360 static void genAddLit2byte (operand *result, int offr, int lit)
361 {
362         FENTRY;
363         
364         switch(lit & 0xff) {
365         case 0:
366                 break;
367         case 1:
368                 emitpcode(POC_INCF, popGet(AOP(result),offr));
369                 break;
370         case 0xff:
371                 emitpcode(POC_DECF, popGet(AOP(result),offr));
372                 break;
373         default:
374                 emitpcode(POC_MOVLW,popGetLit(lit&0xff));
375                 emitpcode(POC_ADDWF,popGet(AOP(result),offr));
376         }
377         
378 }
379
380 static void emitMOVWF(operand *reg, int offset)
381 {
382         FENTRY;
383         if(!reg)
384                 return;
385         
386         emitpcode(POC_MOVWF, popGet(AOP(reg),offset));
387         
388 }
389
390 static void genAddLit (iCode *ic, int lit)
391 {
392         
393         int size,same;
394         int lo;
395         
396         operand *result;
397         operand *left;
398         
399         FENTRY;
400         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
401         
402         
403         left = IC_LEFT(ic);
404         result = IC_RESULT(ic);
405         same = pic14_sameRegs(AOP(left), AOP(result));
406         size = pic14_getDataSize(result);
407         if (size > pic14_getDataSize(left))
408                 size = pic14_getDataSize(left);
409         
410         if(same) {
411                 
412                 /* Handle special cases first */
413                 if(size == 1) 
414                         genAddLit2byte (result, 0, lit);
415                 
416                 else if(size == 2) {
417                         int hi = 0xff & (lit >> 8);
418                         lo = lit & 0xff;
419                         
420                         switch(hi) {
421                         case 0: 
422                                 
423                                 /* lit = 0x00LL */
424                                 DEBUGpic14_emitcode ("; hi = 0","%s  %d",__FUNCTION__,__LINE__);
425                                 switch(lo) {
426                                 case 0:
427                                         break;
428                                 case 1:
429                                         emitpcode(POC_INCF, popGet(AOP(result),0));
430                                         emitSKPNZ;
431                                         emitpcode(POC_INCF, popGet(AOP(result),MSB16));
432                                         break;
433                                 case 0xff:
434                                         emitpcode(POC_DECF, popGet(AOP(result),0));
435                                         emitpcode(POC_INCFSZW, popGet(AOP(result),0));
436                                         emitpcode(POC_INCF, popGet(AOP(result),MSB16));
437                                         
438                                         break;
439                                 default:
440                                         emitpcode(POC_MOVLW,popGetLit(lit&0xff));
441                                         emitpcode(POC_ADDWF,popGet(AOP(result),0));
442                                         emitSKPNC;
443                                         emitpcode(POC_INCF, popGet(AOP(result),MSB16));
444                                         
445                                         
446                                 }
447                                 break;
448                                 
449                                 case 1:
450                                         /* lit = 0x01LL */
451                                         DEBUGpic14_emitcode ("; hi = 1","%s  %d",__FUNCTION__,__LINE__);
452                                         switch(lo) {
453                                         case 0:  /* 0x0100 */
454                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
455                                                 break;
456                                         case 1:  /* 0x0101  */
457                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
458                                                 emitpcode(POC_INCF, popGet(AOP(result),0));
459                                                 emitSKPNZ;
460                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
461                                                 break;
462                                         case 0xff: /* 0x01ff */
463                                                 emitpcode(POC_DECF, popGet(AOP(result),0));
464                                                 emitpcode(POC_INCFSZW, popGet(AOP(result),0));
465                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
466                                                 emitpcode(POC_INCF, popGet(AOP(result),MSB16));
467                                         }   
468                                         break;
469                                         
470                                         case 0xff:
471                                                 DEBUGpic14_emitcode ("; hi = ff","%s  %d",__FUNCTION__,__LINE__);
472                                                 /* lit = 0xffLL */
473                                                 switch(lo) {
474                                                 case 0:  /* 0xff00 */
475                                                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
476                                                         break;
477                                                 case 1:  /*0xff01 */
478                                                         emitpcode(POC_INCFSZ, popGet(AOP(result),0));
479                                                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
480                                                         break;
481                                                         /*  case 0xff: * 0xffff *
482                                                         emitpcode(POC_INCFSZW, popGet(AOP(result),0,FALSE,FALSE));
483                                                         emitpcode(POC_INCF, popGet(AOP(result),MSB16,FALSE,FALSE));
484                                                         emitpcode(POC_DECF, popGet(AOP(result),0,FALSE,FALSE));
485                                                         break;
486                                                         */
487                                                 default:
488                                                         emitpcode(POC_MOVLW,popGetLit(lo));
489                                                         emitpcode(POC_ADDWF,popGet(AOP(result),0));
490                                                         emitSKPC;
491                                                         emitpcode(POC_DECF, popGet(AOP(result),MSB16));
492                                                         
493                                                 }
494                                                 
495                                                 break;
496                                                 
497                                                 default:
498                                                         DEBUGpic14_emitcode ("; hi is generic","%d   %s  %d",hi,__FUNCTION__,__LINE__);
499                                                         
500                                                         /* lit = 0xHHLL */
501                                                         switch(lo) {
502                                                         case 0:  /* 0xHH00 */
503                                                                 genAddLit2byte (result, MSB16, hi);
504                                                                 break;
505                                                         case 1:  /* 0xHH01 */
506                                                                 emitpcode(POC_MOVLW,popGetLit((hi+1)&0xff));
507                                                                 emitpcode(POC_INCFSZ, popGet(AOP(result),0));
508                                                                 emitpcode(POC_MOVLW,popGetLit(hi));
509                                                                 emitpcode(POC_ADDWF,popGet(AOP(result),MSB16));
510                                                                 break;
511                                                                 /*  case 0xff: * 0xHHff *
512                                                                 emitpcode(POC_MOVFW, popGet(AOP(result),0,FALSE,FALSE));
513                                                                 emitpcode(POC_DECF, popGet(AOP(result),MSB16,FALSE,FALSE));
514                                                                 emitpcode(POC_MOVLW,popGetLit(hi));
515                                                                 emitpcode(POC_ADDWF,popGet(AOP(result),MSB16,FALSE,FALSE));
516                                                                 break;
517                                                                 */  default:  /* 0xHHLL */
518                                                                 emitpcode(POC_MOVLW,popGetLit(lo));
519                                                                 emitpcode(POC_ADDWF, popGet(AOP(result),0));
520                                                                 emitpcode(POC_MOVLW,popGetLit(hi));
521                                                                 emitSKPNC;
522                                                                 emitpcode(POC_MOVLW,popGetLit((hi+1) & 0xff));
523                                                                 emitpcode(POC_ADDWF,popGet(AOP(result),MSB16));
524                                                                 break;
525                                                         }
526                                                         
527                         }
528                 } else {
529                         int carry_info = 0;
530                         int offset = 0;
531                         /* size > 2 */
532                         DEBUGpic14_emitcode (";  add lit to long","%s  %d",__FUNCTION__,__LINE__);
533                         
534                         while(size--) {
535                                 lo = BYTEofLONG(lit,0);
536                                 
537                                 if(carry_info) {
538                                         switch(lo) {
539                                         case 0:
540                                                 switch(carry_info) {
541                                                 case 1:
542                                                         emitSKPNZ;
543                                                         emitpcode(POC_INCF, popGet(AOP(result),offset));
544                                                         break;
545                                                 case 2:
546                                                         emitpcode(POC_RLFW, popGet(AOP(result),offset));
547                                                         emitpcode(POC_ANDLW,popGetLit(1));
548                                                         emitpcode(POC_ADDWF, popGet(AOP(result),offset));
549                                                         break;
550                                                 default: /* carry_info = 3  */
551                                                         emitSKPNC;
552                                                         emitpcode(POC_INCF, popGet(AOP(result),offset));
553                                                         carry_info = 1;
554                                                         break;
555                                                 }
556                                                 break;
557                                                 case 0xff:
558                                                         emitpcode(POC_MOVLW,popGetLit(lo));
559                                                         if(carry_info==1) 
560                                                                 emitSKPZ;
561                                                         else
562                                                                 emitSKPC;
563                                                         emitpcode(POC_ADDWF, popGet(AOP(result),offset));
564                                                         break;
565                                                 default:
566                                                         emitpcode(POC_MOVLW,popGetLit(lo));
567                                                         if(carry_info==1) 
568                                                                 emitSKPNZ;
569                                                         else
570                                                                 emitSKPNC;
571                                                         emitpcode(POC_MOVLW,popGetLit(lo+1));
572                                                         emitpcode(POC_ADDWF, popGet(AOP(result),offset));
573                                                         carry_info=2;
574                                                         break;
575                                         }
576                                 }else {
577                                         /* no carry info from previous step */
578                                         /* this means this is the first time to add */
579                                         switch(lo) {
580                                         case 0:
581                                                 break;
582                                         case 1:
583                                                 emitpcode(POC_INCF, popGet(AOP(result),offset));
584                                                 carry_info=1;
585                                                 break;
586                                         default:
587                                                 emitpcode(POC_MOVLW,popGetLit(lo));
588                                                 emitpcode(POC_ADDWF, popGet(AOP(result),offset));
589                                                 if(lit <0x100) 
590                                                         carry_info = 3;  /* Were adding only one byte and propogating the carry */
591                                                 else
592                                                         carry_info = 2;
593                                                 break;
594                                         }
595                                 }
596                                 offset++;
597                                 lit >>= 8;
598                         }
599                         
600                         /*
601                                 lo = BYTEofLONG(lit,0);
602                         
603                                 if(lit < 0x100) {
604                                         if(lo) {
605                                                 if(lo == 1) {
606                                                         emitpcode(POC_INCF, popGet(AOP(result),0,FALSE,FALSE));
607                                                         emitSKPNZ;
608                                                 } else {
609                                                         emitpcode(POC_MOVLW,popGetLit(lo));
610                                                         emitpcode(POC_ADDWF, popGet(AOP(result),0,FALSE,FALSE));
611                                                         emitSKPNC;
612                                                 }
613                                                 emitpcode(POC_INCF, popGet(AOP(result),1,FALSE,FALSE));
614                                                 emitSKPNZ;
615                                                 emitpcode(POC_INCF, popGet(AOP(result),2,FALSE,FALSE));
616                                                 emitSKPNZ;
617                                                 emitpcode(POC_INCF, popGet(AOP(result),3,FALSE,FALSE));
618                                                 
619                                         } 
620                                 } 
621                                 
622                         */
623                 }
624         } else {
625                 int offset = 1;
626                 DEBUGpic14_emitcode (";  left and result aren't same","%s  %d",__FUNCTION__,__LINE__);
627                 
628                 if(size == 1) {
629                         
630                         /* left addend is in a register */
631                         switch(lit & 0xff) {
632                         case 0:
633                                 emitpcode(POC_MOVFW, popGet(AOP(left),0));
634                                 emitMOVWF(result, 0);
635                                 //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
636                                 emitMOVWF(result,0);
637                                 break;
638                         case 1:
639                                 emitpcode(POC_INCFW, popGet(AOP(left),0));
640                                 //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
641                                 emitMOVWF(result,0);
642                                 break;
643                         case 0xff:
644                                 emitpcode(POC_DECFW, popGet(AOP(left),0));
645                                 //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
646                                 emitMOVWF(result,0);
647                                 break;
648                         default:
649                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
650                                 emitpcode(POC_ADDFW, popGet(AOP(left),0));
651                                 //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
652                                 emitMOVWF(result,0);
653                         }
654                         
655                 } else {
656                         int clear_carry=0;
657                         
658                         /* left is not the accumulator */
659                         if(lit & 0xff) {
660                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
661                                 emitpcode(POC_ADDFW, popGet(AOP(left),0));
662                         } else {
663                                 emitpcode(POC_MOVFW, popGet(AOP(left),0));
664                                 /* We don't know the state of the carry bit at this point */
665                                 clear_carry = 1;
666                         }
667                         //emitpcode(POC_MOVWF, popGet(AOP(result),0,FALSE,FALSE));
668                         emitMOVWF(result,0);
669                         while(--size) {
670                                 
671                                 lit >>= 8;
672                                 if(lit & 0xff) {
673                                         if(clear_carry) {
674                                         /* The ls byte of the lit must've been zero - that 
675                                                 means we don't have to deal with carry */
676                                                 
677                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
678                                                 emitpcode(POC_ADDFW,  popGet(AOP(left),offset));
679                                                 emitpcode(POC_MOVWF, popGet(AOP(left),offset));
680                                                 
681                                                 clear_carry = 0;
682                                                 
683                                         } else {
684                                                 emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
685                                                 //emitpcode(POC_MOVWF, popGet(AOP(result),offset,FALSE,FALSE));
686                                                 emitMOVWF(result,offset);
687                                                 emitpcode(POC_MOVFW, popGet(AOP(left),offset));
688                                                 emitSKPNC;
689                                                 emitpcode(POC_INCFSZW,popGet(AOP(left),offset));
690                                                 emitpcode(POC_ADDWF,  popGet(AOP(result),offset));
691                                         }
692                                         
693                                 } else {
694                                         emitpcode(POC_CLRF,  popGet(AOP(result),offset));
695                                         emitpcode(POC_RLF,   popGet(AOP(result),offset));
696                                         emitpcode(POC_MOVFW, popGet(AOP(left),offset));
697                                         emitpcode(POC_ADDWF, popGet(AOP(result),offset));
698                                 }
699                                 offset++;
700                         }
701                 }
702         }
703
704         size = pic14_getDataSize(result);
705         if (size > pic14_getDataSize(left))
706                 size = pic14_getDataSize(left);
707         addSign(result, size, 0);
708 }
709
710 /*-----------------------------------------------------------------*/
711 /* genPlus - generates code for addition                           */
712 /*-----------------------------------------------------------------*/
713 void genPlus (iCode *ic)
714 {
715         int size, offset = 0;
716         
717         /* special cases :- */
718         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
719         FENTRY;
720         
721         aopOp (IC_LEFT(ic),ic,FALSE);
722         aopOp (IC_RIGHT(ic),ic,FALSE);
723         aopOp (IC_RESULT(ic),ic,TRUE);
724         
725         DEBUGpic14_AopType(__LINE__,IC_LEFT(ic),IC_RIGHT(ic),IC_RESULT(ic));
726         
727         /* if literal, literal on the right or
728         if left requires ACC or right is already
729         in ACC */
730         
731         if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
732                 operand *t = IC_RIGHT(ic);
733                 IC_RIGHT(ic) = IC_LEFT(ic);
734                 IC_LEFT(ic) = t;
735         }
736         
737         /* if left in bit space & right literal */
738         if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
739                 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
740                 /* if result in bit space */
741                 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
742                         if(ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
743                                 emitpcode(POC_MOVLW, popGet(AOP(IC_RESULT(ic)),0));
744                                 if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
745                                         emitpcode(POC_BTFSC, popGet(AOP(IC_LEFT(ic)),0));
746                                 emitpcode(POC_XORWF, popGet(AOP(IC_RESULT(ic)),0));
747                         }
748                 } else {
749                         size = pic14_getDataSize(IC_RESULT(ic));
750                         while (size--) {
751                                 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
752                                 pic14_emitcode("addc","a,#00  ;%d",__LINE__);
753                                 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
754                         }
755                 }
756                 goto release ;
757         }
758         
759         /* if I can do an increment instead
760         of add then GOOD for ME */
761         if (genPlusIncr (ic) == TRUE)
762                 goto release;   
763         
764         size = pic14_getDataSize(IC_RESULT(ic));
765         
766         if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
767                 /* Add a literal to something else */
768                 //bool know_W=0;
769                 unsigned lit = (unsigned) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
770                 //      unsigned l1=0;
771                 
772                 //      offset = 0;
773                 DEBUGpic14_emitcode(";","adding lit to something. size %d",size);
774                 
775                 genAddLit (ic,  lit);
776                 goto release;
777                 
778         } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
779                 
780                 pic14_emitcode(";bitadd","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
781                 pic14_emitcode(";bitadd","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
782                 pic14_emitcode(";bitadd","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
783                 
784                 /* here we are adding a bit to a char or int */
785                 if(size == 1) {
786                         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
787                                 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
788                                 emitpcode(POC_INCF ,  popGet(AOP(IC_RESULT(ic)),0));
789                         } else {
790                                 
791                                 emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0));
792                                 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
793                                 emitpcode(POC_INCFW , popGet(AOP(IC_LEFT(ic)),0));
794                                 
795                                 if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
796                                         emitpcode(POC_ANDLW , popGetLit(1));
797                                         emitpcode(POC_BCF ,   popGet(AOP(IC_RESULT(ic)),0));
798                                         emitSKPZ;
799                                         emitpcode(POC_BSF ,   popGet(AOP(IC_RESULT(ic)),0));
800                                 } else {
801                                         emitpcode(POC_MOVWF ,   popGet(AOP(IC_RESULT(ic)),0));
802                                 }
803                         }
804                         
805                 } else {
806                         int offset = 1;
807                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
808                         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
809                                 emitCLRZ;
810                                 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0));
811                                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),0));
812                         } else {
813                                 
814                                 emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),0));
815                                 emitpcode(POC_BTFSC, popGet(AOP(IC_RIGHT(ic)),0));
816                                 emitpcode(POC_INCFW, popGet(AOP(IC_LEFT(ic)),0));
817                                 //emitpcode(POC_MOVWF, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
818                                 emitMOVWF(IC_RIGHT(ic),0);
819                         }
820                         
821                         while(--size){
822                                 emitSKPZ;
823                                 emitpcode(POC_INCF,  popGet(AOP(IC_RESULT(ic)),offset++));
824                         }
825                         
826                 }
827                 
828         } else {
829                 DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
830                 
831                 /* Add the first bytes */
832                 
833                 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
834                         emitpcode(POC_ADDFW, popGet(AOP(IC_RIGHT(ic)),0));
835                         emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
836                 } else {
837                         
838                         emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0));
839
840                         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
841                                 emitpcode(POC_ADDWF, popGet(AOP(IC_LEFT(ic)),0));
842                         else {
843                                 PIC_OPCODE poc = POC_ADDFW;
844                                 
845                                 if (op_isLitLike (IC_LEFT (ic)))
846                                         poc = POC_ADDLW;
847                                 emitpcode(poc, popGetAddr(AOP(IC_LEFT(ic)),0,0));
848                                 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
849                         }
850                 }
851                 
852                 size = min( AOP_SIZE(IC_RESULT(ic)), AOP_SIZE(IC_RIGHT(ic))) - 1;
853                 offset = 1;
854                 
855                 
856                 if(size){
857                         if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) {
858                                 if (op_isLitLike (IC_LEFT(ic)))
859                                 {
860                                         while(size--){
861                                                 emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset));
862                                                 emitSKPNC;
863                                                 emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset));
864                                                 emitpcode(POC_ADDLW,   popGetAddr(AOP(IC_LEFT(ic)),offset,0));
865                                                 emitpcode(POC_MOVWF,   popGet(AOP(IC_RESULT(ic)),offset));
866                                                 offset++;
867                                         }
868                                 } else {
869                                         while(size--){
870                                                 emitpcode(POC_MOVFW,   popGet(AOP(IC_LEFT(ic)),offset));
871                                                 emitSKPNC;
872                                                 emitpcode(POC_INCFSZW, popGet(AOP(IC_LEFT(ic)),offset));
873                                                 emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset));
874                                                 offset++;
875                                         }
876                                 }
877                         } else {
878                                 PIC_OPCODE poc = POC_MOVFW;
879                                 if (op_isLitLike (IC_LEFT(ic)))
880                                         poc = POC_MOVLW;
881                                 while(size--){
882                                         if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
883                                                 emitpcode(poc, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
884                                                 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
885                                         }
886                                         emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset));
887                                         emitSKPNC;
888                                         emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset));
889                                         emitpcode(POC_ADDWF,   popGet(AOP(IC_RESULT(ic)),offset));
890                                         offset++;
891                                 }
892                         }
893                 }
894         }
895         
896         if (AOP_SIZE(IC_RESULT(ic)) > AOP_SIZE(IC_RIGHT(ic))) {
897                 int sign =  !(SPEC_USIGN(getSpec(operandType(IC_LEFT(ic)))) |
898                         SPEC_USIGN(getSpec(operandType(IC_RIGHT(ic)))) );
899                 
900                 
901                 /* Need to extend result to higher bytes */
902                 size = AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_RIGHT(ic)) - 1;
903                 
904                 /* First grab the carry from the lower bytes */
905                 if (AOP_SIZE(IC_LEFT(ic)) > AOP_SIZE(IC_RIGHT(ic))) { 
906                         int leftsize = AOP_SIZE(IC_LEFT(ic)) - AOP_SIZE(IC_RIGHT(ic));
907                         PIC_OPCODE poc = POC_MOVFW;
908                         if (op_isLitLike (IC_LEFT(ic)))
909                                 poc = POC_MOVLW;
910                         while(leftsize-- > 0) {
911                                 emitpcode(poc, popGetAddr(AOP(IC_LEFT(ic)),offset,0));
912                                 emitSKPNC;
913                                 emitpcode(POC_ADDLW, popGetLit(0x01));
914                                 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
915                                 //emitSKPNC;
916                                 //emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset)); /* INCF does not update Carry! */
917                                 offset++;
918                                 if (size)
919                                         size--;
920                                 else
921                                         break;
922                         }
923                 } else {
924                         emitpcode(POC_CLRF, popGet(AOP(IC_RESULT(ic)),offset));
925                         emitpcode(POC_RLF,  popGet(AOP(IC_RESULT(ic)),offset));
926                 }
927                 
928                 
929                 if(sign && offset > 0 && offset < AOP_SIZE(IC_RESULT(ic))) {
930                 /* Now this is really horrid. Gotta check the sign of the addends and propogate
931                         * to the result */
932                         
933                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(IC_LEFT(ic)),offset-1,FALSE,FALSE),7,0));
934                         emitpcode(POC_DECF,  popGet(AOP(IC_RESULT(ic)),offset));
935                         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(IC_RIGHT(ic)),offset-1,FALSE,FALSE),7,0));
936                         emitpcode(POC_DECF,  popGet(AOP(IC_RESULT(ic)),offset));
937                         
938                         /* if chars or ints or being signed extended to longs: */
939                         if(size) {
940                                 emitpcode(POC_MOVLW, popGetLit(0));
941                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE),7,0));
942                                 emitpcode(POC_MOVLW, popGetLit(0xff));
943                         }
944                 }
945                 
946                 offset++;
947                 while(size--) {
948                         
949                         if(sign)
950                                 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
951                         else
952                                 emitpcode(POC_CLRF,  popGet(AOP(IC_RESULT(ic)),offset));
953                         
954                         offset++;
955                 }
956         }
957         
958         
959         //adjustArithmeticResult(ic);
960         
961 release:
962         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
963         freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
964         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
965 }
966
967 /*-----------------------------------------------------------------*/
968 /* genMinusDec :- does subtraction with decrement if possible     */
969 /*-----------------------------------------------------------------*/
970 bool genMinusDec (iCode *ic)
971 {
972         unsigned int icount ;
973         unsigned int size = pic14_getDataSize(IC_RESULT(ic));
974         FENTRY;
975         
976         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
977         /* will try to generate an increment */
978         /* if the right side is not a literal 
979         we cannot */
980         if ((AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) || 
981                 (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) || 
982                 (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) )
983                 return FALSE ;
984         
985         DEBUGpic14_emitcode ("; lit val","%d",(unsigned int) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit));
986         
987         /* if the literal value of the right hand side
988         is greater than 4 then it is not worth it */
989         if ((icount = (unsigned int) ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
990                 return FALSE ;
991         
992         /* if decrement 16 bits in register */
993         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
994                 (size > 1) &&
995                 (icount == 1)) {
996                 
997                 if(size == 2) { 
998                         emitpcode(POC_DECF,    popGet(AOP(IC_RESULT(ic)),LSB));
999                         emitpcode(POC_INCFSZW, popGet(AOP(IC_RESULT(ic)),LSB));
1000                         emitpcode(POC_INCF,    popGet(AOP(IC_RESULT(ic)),MSB16));
1001                         emitpcode(POC_DECF,    popGet(AOP(IC_RESULT(ic)),MSB16));
1002                         
1003                         pic14_emitcode("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1004                         pic14_emitcode("incfsz","%s,w",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1005                         pic14_emitcode(" decf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
1006                 } else {
1007                         /* size is 3 or 4 */
1008                         emitpcode(POC_MOVLW,  popGetLit(0xff));
1009                         emitpcode(POC_ADDWF,  popGet(AOP(IC_RESULT(ic)),LSB));
1010                         emitSKPNC;
1011                         emitpcode(POC_ADDWF,  popGet(AOP(IC_RESULT(ic)),MSB16));
1012                         emitSKPNC;
1013                         emitpcode(POC_ADDWF,  popGet(AOP(IC_RESULT(ic)),MSB24));
1014                         
1015                         pic14_emitcode("movlw","0xff");
1016                         pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE,FALSE));
1017                         
1018                         emitSKPNC;
1019                         pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE,FALSE));
1020                         emitSKPNC;
1021                         pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB24,FALSE,FALSE));
1022                         
1023                         if(size > 3) {
1024                                 emitSKPNC;
1025                                 emitpcode(POC_ADDWF,  popGet(AOP(IC_RESULT(ic)),MSB32));
1026                                 
1027                                 pic14_emitcode("skpnc","");
1028                                 emitSKPNC;
1029                                 pic14_emitcode("addwf","%s,f",aopGet(AOP(IC_RESULT(ic)),MSB32,FALSE,FALSE));
1030                         }
1031                         
1032                 }
1033                 
1034                 return TRUE;
1035                 
1036         }
1037         
1038         /* if the sizes are greater than 1 then we cannot */
1039         if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1040                 AOP_SIZE(IC_LEFT(ic)) > 1   )
1041                 return FALSE ;
1042         
1043         /* we can if the aops of the left & result match or
1044         if they are in registers and the registers are the
1045         same */
1046         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1047                 
1048                 while (icount--) 
1049                         emitpcode(POC_DECF, popGet(AOP(IC_RESULT(ic)),0));
1050                 
1051                 //pic14_emitcode ("decf","%s,f",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1052                 
1053                 return TRUE ;
1054         }
1055         
1056         DEBUGpic14_emitcode ("; returning"," result=%s, left=%s",
1057                 aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE),
1058                 aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1059         if(size==1) {
1060                 
1061                 pic14_emitcode("decf","%s,w",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1062                 pic14_emitcode("movwf","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1063                 
1064                 emitpcode(POC_DECFW,  popGet(AOP(IC_LEFT(ic)),0));
1065                 emitpcode(POC_MOVWF,  popGet(AOP(IC_RESULT(ic)),0));
1066                 
1067                 return TRUE;
1068         }
1069         
1070         return FALSE ;
1071 }
1072
1073 /*-----------------------------------------------------------------*/
1074 /* addSign - propogate sign bit to higher bytes                    */
1075 /*-----------------------------------------------------------------*/
1076 void addSign(operand *result, int offset, int sign)
1077 {
1078         int size = (pic14_getDataSize(result) - offset);
1079         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1080         FENTRY;
1081         
1082         if(size > 0){
1083                 if(sign && offset) {
1084                         
1085                         if(size == 1) {
1086                                 emitpcode(POC_CLRF,popGet(AOP(result),offset));
1087                                 emitpcode(POC_BTFSC,newpCodeOpBit(aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
1088                                 emitpcode(POC_DECF, popGet(AOP(result),offset));
1089                         } else {
1090                                 
1091                                 emitpcode(POC_MOVLW, popGetLit(0));
1092                                 emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
1093                                 emitpcode(POC_MOVLW, popGetLit(0xff));
1094                                 while(size--)
1095                                         emitpcode(POC_MOVWF, popGet(AOP(result),offset+size));
1096                         }
1097                 } else
1098                         while(size--)
1099                                 emitpcode(POC_CLRF,popGet(AOP(result),offset++));
1100         }
1101 }
1102
1103 /*-----------------------------------------------------------------*/
1104 /* genMinus - generates code for subtraction                       */
1105 /*-----------------------------------------------------------------*/
1106 void genMinus (iCode *ic)
1107 {
1108         int size, offset = 0, same=0;
1109         unsigned long lit = 0L;
1110         
1111         FENTRY;
1112         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1113         aopOp (IC_LEFT(ic),ic,FALSE);
1114         aopOp (IC_RIGHT(ic),ic,FALSE);
1115         aopOp (IC_RESULT(ic),ic,TRUE);
1116         
1117         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY  &&
1118                 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1119                 operand *t = IC_RIGHT(ic);
1120                 IC_RIGHT(ic) = IC_LEFT(ic);
1121                 IC_LEFT(ic) = t;
1122         }
1123         
1124         DEBUGpic14_emitcode ("; ","result %s, left %s, right %s",
1125                 AopType(AOP_TYPE(IC_RESULT(ic))),
1126                 AopType(AOP_TYPE(IC_LEFT(ic))),
1127                 AopType(AOP_TYPE(IC_RIGHT(ic))));
1128         
1129         /* if I can do an decrement instead
1130         of subtract then GOOD for ME */
1131         //  if (genMinusDec (ic) == TRUE)
1132         //    goto release;   
1133         
1134         size = pic14_getDataSize(IC_RESULT(ic));   
1135         same = pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)));
1136         
1137         if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
1138                 /* Add a literal to something else */
1139                 
1140                 lit = ulFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
1141                 lit = - (long)lit;
1142                 
1143                 genAddLit ( ic,  lit);
1144                 
1145 #if 0
1146                 /* add the first byte: */
1147                 pic14_emitcode("movlw","0x%x", lit & 0xff);
1148                 pic14_emitcode("addwf","%s,f", aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1149                 emitpcode(POC_MOVLW,  popGetLit(lit & 0xff));
1150                 emitpcode(POC_ADDWF,  popGet(AOP(IC_LEFT(ic)),0));
1151                 
1152                 
1153                 offset = 1;
1154                 size--;
1155                 
1156                 while(size-- > 0) {
1157                         
1158                         lit >>= 8;
1159                         
1160                         if(lit & 0xff) {
1161                                 
1162                                 if((lit & 0xff) == 0xff) {
1163                                         emitpcode(POC_MOVLW,  popGetLit(0xff));
1164                                         emitSKPC;
1165                                         emitpcode(POC_ADDWF,  popGet(AOP(IC_LEFT(ic)),offset));
1166                                 } else {
1167                                         emitpcode(POC_MOVLW,  popGetLit(lit & 0xff));
1168                                         emitSKPNC;
1169                                         emitpcode(POC_MOVLW,  popGetLit((lit+1) & 0xff));
1170                                         emitpcode(POC_ADDWF,  popGet(AOP(IC_LEFT(ic)),offset));
1171                                 }
1172                                 
1173                         } else {
1174                                 /* do the rlf known zero trick here */
1175                                 emitpcode(POC_MOVLW,  popGetLit(1));
1176                                 emitSKPNC;
1177                                 emitpcode(POC_ADDWF,  popGet(AOP(IC_LEFT(ic)),offset));
1178                         }
1179                         offset++;
1180                 }
1181 #endif
1182         } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1183                 // bit subtraction
1184                 
1185                 pic14_emitcode(";bitsub","right is bit: %s",aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
1186                 pic14_emitcode(";bitsub","left is bit: %s",aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
1187                 pic14_emitcode(";bitsub","result is bit: %s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1188                 
1189                 /* here we are subtracting a bit from a char or int */
1190                 if(size == 1) {
1191                         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1192                                 
1193                                 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
1194                                 emitpcode(POC_DECF ,  popGet(AOP(IC_RESULT(ic)),0));
1195                                 
1196                                 pic14_emitcode("btfsc","(%s >> 3), (%s & 7)",
1197                                         AOP(IC_RIGHT(ic))->aopu.aop_dir,
1198                                         AOP(IC_RIGHT(ic))->aopu.aop_dir);
1199                                 pic14_emitcode(" incf","%s,f", aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
1200                         } else {
1201                                 
1202                             if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
1203                                         (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1204                                         
1205                                         lit = ulFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit);
1206                                         
1207                                         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1208                                                 if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
1209                                                         if(lit & 1) {
1210                                                                 emitpcode(POC_MOVLW , popGet(AOP(IC_RIGHT(ic)),0));
1211                                                                 emitpcode(POC_XORWF , popGet(AOP(IC_RIGHT(ic)),0));
1212                                                         }
1213                                                 }else{
1214                                                         emitpcode(POC_BCF ,     popGet(AOP(IC_RESULT(ic)),0));
1215                                                         if(lit & 1) 
1216                                                                 emitpcode(POC_BTFSS , popGet(AOP(IC_RIGHT(ic)),0));
1217                                                         else
1218                                                                 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
1219                                                         emitpcode(POC_BSF ,     popGet(AOP(IC_RESULT(ic)),0));
1220                                                 }
1221                                                 goto release;
1222                                         } else {
1223                                                 emitpcode(POC_MOVLW , popGetLit(lit & 0xff));
1224                                                 emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
1225                                                 emitpcode(POC_MOVLW , popGetLit((lit-1) & 0xff));
1226                                                 emitpcode(POC_MOVWF , popGet(AOP(IC_RESULT(ic)),0));
1227                                                 
1228                                         }
1229                                         
1230                                 } else {
1231                                         emitpcode(POC_MOVFW , popGet(AOP(IC_LEFT(ic)),0));
1232                                         emitpcode(POC_BTFSC , popGet(AOP(IC_RIGHT(ic)),0));
1233                                         emitpcode(POC_DECFW , popGet(AOP(IC_LEFT(ic)),0));
1234                                 }
1235                                 
1236                                 emitpcode(POC_MOVWF ,   popGet(AOP(IC_RESULT(ic)),0));
1237                         }
1238                         
1239                 }
1240         } else   if(// (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) || 
1241                 (AOP(IC_LEFT(ic))->type == AOP_LIT)) {
1242                 
1243                 lit = ulFromVal (AOP(IC_LEFT(ic))->aopu.aop_lit);
1244                 DEBUGpic14_emitcode ("; left is lit","line %d result %s, left %s, right %s",__LINE__,
1245                         AopType(AOP_TYPE(IC_RESULT(ic))),
1246                         AopType(AOP_TYPE(IC_LEFT(ic))),
1247                         AopType(AOP_TYPE(IC_RIGHT(ic))));
1248                 
1249                 
1250                 if( (size == 1) && ((lit & 0xff) == 0) ) {
1251                         /* res = 0 - right */
1252                         if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic))) ) {
1253                                 emitpcode(POC_COMF,  popGet(AOP(IC_RIGHT(ic)),0));
1254                                 emitpcode(POC_INCF,  popGet(AOP(IC_RIGHT(ic)),0));
1255                         } else { 
1256                                 emitpcode(POC_COMFW,  popGet(AOP(IC_RIGHT(ic)),0));
1257                                 emitpcode(POC_MOVWF,  popGet(AOP(IC_RESULT(ic)),0));
1258                                 emitpcode(POC_INCF,   popGet(AOP(IC_RESULT(ic)),0));
1259                         }
1260                         goto release;
1261                 }
1262                 
1263                 emitpcode(POC_MOVFW,  popGet(AOP(IC_RIGHT(ic)),0));
1264                 emitpcode(POC_SUBLW, popGetLit(lit & 0xff));    
1265                 emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1266                 
1267                 
1268                 offset = 1;
1269                 while(--size) {
1270                         lit >>= 8;
1271                         
1272                         if(size == 1) {
1273                         /* This is the last byte in a multibyte subtraction 
1274                         * There are a couple of tricks we can do by not worrying about 
1275                                 * propogating the carry */
1276                                 if(lit == 0xff) {
1277                                         /* 0xff - x == ~x */
1278                                         if(same) {
1279                                                 emitpcode(POC_COMF,  popGet(AOP(IC_RESULT(ic)),offset));
1280                                                 emitSKPC;
1281                                                 emitpcode(POC_DECF,  popGet(AOP(IC_RESULT(ic)),offset));
1282                                         } else {
1283                                                 emitpcode(POC_COMFW, popGet(AOP(IC_RIGHT(ic)),offset));
1284                                                 emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
1285                                                 emitSKPC;
1286                                                 emitpcode(POC_DECF,  popGet(AOP(IC_RESULT(ic)),offset));
1287                                         }
1288                                 } else {
1289                                         emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset));
1290                                         emitSKPC;
1291                                         emitpcode(POC_INCFW, popGet(AOP(IC_RIGHT(ic)),offset));
1292                                         emitpcode(POC_SUBLW, popGetLit(lit & 0xff));
1293                                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
1294                                 }
1295                                 
1296                                 goto release;
1297                         }
1298                         
1299                         if(same) {
1300                                 
1301                                 if(lit & 0xff) {
1302                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
1303                                         emitSKPC;
1304                                         emitpcode(POC_MOVLW, popGetLit((lit & 0xff)-1));
1305                                         emitpcode(POC_SUBWF,  popGet(AOP(IC_RESULT(ic)),offset));
1306                                 } else {
1307                                         emitSKPNC;
1308                                         emitpcode(POC_SUBWF,  popGet(AOP(IC_RESULT(ic)),offset));
1309                                         
1310                                 }
1311                         } else {
1312                                 
1313                                 if(lit & 0xff) {
1314                                         emitpcode(POC_MOVLW, popGetLit(lit & 0xff));
1315                                         emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset));
1316                                 } else
1317                                         emitpcode(POC_CLRF, popGet(AOP(IC_RESULT(ic)),offset));
1318                                 
1319                                 emitpcode(POC_MOVFW,  popGet(AOP(IC_RIGHT(ic)),offset));
1320                                 emitSKPC;
1321                                 emitpcode(POC_INCFSZW,popGet(AOP(IC_RIGHT(ic)),offset));
1322                                 emitpcode(POC_SUBWF,  popGet(AOP(IC_RESULT(ic)),offset));
1323                         }
1324                 }
1325                 
1326                 
1327         } else {
1328                 
1329                 DEBUGpic14_emitcode ("; ","line %d result %s, left %s, right %s",__LINE__,
1330                         AopType(AOP_TYPE(IC_RESULT(ic))),
1331                         AopType(AOP_TYPE(IC_LEFT(ic))),
1332                         AopType(AOP_TYPE(IC_RIGHT(ic))));
1333                 
1334                 if(strcmp(aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
1335                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1336                         emitpcode(POC_SUBFW, popGet(AOP(IC_RIGHT(ic)),0));
1337                         emitpcode(POC_SUBLW, popGetLit(0));
1338                         emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1339                 } else {
1340                         
1341                         DEBUGpic14_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1342                         emitpcode(POC_MOVFW,popGet(AOP(IC_RIGHT(ic)),0));
1343
1344                         if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1345                                 emitpcode(POC_SUBWF, popGet(AOP(IC_LEFT(ic)),0));
1346                         } else {
1347                                 if( (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD) ||
1348                                         (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ) {
1349                                         emitpcode(POC_SUBLW, popGet(AOP(IC_LEFT(ic)),0));
1350                                 } else {
1351                                         emitpcode(POC_SUBFW, popGet(AOP(IC_LEFT(ic)),0));
1352                                 }
1353                                 if ( AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1354                                         emitpcode(POC_BCF ,   popGet(AOP(IC_RESULT(ic)),0));
1355                                         emitSKPZ;
1356                                         emitpcode(POC_BSF ,   popGet(AOP(IC_RESULT(ic)),0));
1357                                 } else {
1358                                         emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
1359                                 }
1360                         }
1361                 }
1362                 
1363                 size = min( AOP_SIZE(IC_RESULT(ic)), AOP_SIZE(IC_RIGHT(ic))) - 1;
1364                 offset = 1;
1365                 
1366                 if(size){
1367                         if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) {
1368                                 int lit = 0;
1369                                 if (op_isLitLike (IC_LEFT(ic)))
1370                                         lit = 1;
1371                                 while(size--){
1372                                         emitpcode(POC_MOVFW,   popGet(AOP(IC_RIGHT(ic)),offset));
1373                                         emitSKPC;
1374                                         emitpcode(POC_INCFW, popGet(AOP(IC_RIGHT(ic)),offset));
1375                                         emitpcode(lit?POC_SUBLW:POC_SUBFW,   popGetAddr(AOP(IC_LEFT(ic)),offset,0));
1376                                         emitpcode(POC_MOVWF,   popGet(AOP(IC_RESULT(ic)),offset));
1377                                         offset++;
1378                                 }
1379                         } else {
1380                                 PIC_OPCODE poc = POC_MOVFW;
1381                                 if (op_isLitLike (IC_LEFT(ic)))
1382                                         poc = POC_MOVLW;
1383                                 while(size--){
1384                                         if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1385                                                 emitpcode(poc,  popGetAddr(AOP(IC_LEFT(ic)),offset,0));
1386                                                 emitpcode(POC_MOVWF,  popGet(AOP(IC_RESULT(ic)),offset));
1387                                         }
1388                                         emitpcode(POC_MOVFW,  popGet(AOP(IC_RIGHT(ic)),offset));
1389                                         emitSKPC;
1390                                         emitpcode(POC_INCFSZW,popGet(AOP(IC_RIGHT(ic)),offset));
1391                                         emitpcode(POC_SUBWF,  popGet(AOP(IC_RESULT(ic)),offset));
1392                                         offset++;
1393                                 }
1394                         }
1395                 }
1396         }
1397         
1398         //    adjustArithmeticResult(ic);
1399         
1400 release:
1401         freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1402         freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
1403         freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1404 }
1405 /*-----------------------------------------------------------------*
1406 * genUMult8XLit_16 - unsigned multiplication of two 8-bit numbers.
1407
1408
1409 *-----------------------------------------------------------------*/
1410 void genUMult8XLit_16 (operand *left,
1411                                            operand *right,
1412                                            operand *result,
1413                                            pCodeOpReg *result_hi)
1414                                            
1415 {
1416         
1417         unsigned int lit;
1418         unsigned int i,have_first_bit;
1419         int same;
1420         pCodeOp *temp;
1421         
1422         FENTRY;
1423         if (AOP_TYPE(right) != AOP_LIT){
1424                 fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
1425                 exit(EXIT_FAILURE);
1426         }
1427         
1428         
1429         if(!result_hi) {
1430                 result_hi = PCOR(popGet(AOP(result),1));
1431         }
1432         
1433         lit = (unsigned int) ulFromVal (AOP(right)->aopu.aop_lit);
1434         lit &= 0xff;
1435         pic14_emitcode(";","Unrolled 8 X 8 multiplication");
1436         
1437         same = pic14_sameRegs(AOP(left), AOP(result));
1438         
1439         if(same) {
1440                 switch(lit) {
1441                 case 0:
1442                         emitpcode(POC_CLRF,  popGet(AOP(left),0));
1443                         return;
1444                 case 2:
1445                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1446                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1447                         return;
1448                 case 3:
1449                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1450                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1451                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1452                         return;
1453                 case 4:
1454                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1455                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1456                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1457                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1458                         return;
1459                 case 5:
1460                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1461                         emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 2*F
1462                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 3*F
1463                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 5*F
1464                         return;
1465                 case 6:
1466                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1467                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1468                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1469                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1470                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1471                         return;
1472                 case 7:
1473                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1474                         emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 2*F
1475                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 3*F
1476                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 5*F
1477                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 7*F
1478                         return;
1479                 case 8:
1480                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1481                         emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 2*F
1482                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 3*F
1483                         emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 5*F
1484                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 8*F
1485                         return;
1486                 case 9:
1487                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1488                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1489                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1490                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1491                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1492                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1493                         return;
1494                 case 10:
1495                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1496                         emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 2*F
1497                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 3*F
1498                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 5*F
1499                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1500                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1501                         return;
1502                 case 11:
1503                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1504                         emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 2*F
1505                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 3*F
1506                         emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 5*F
1507                         emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 8*F
1508                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 11*F
1509                         return;
1510                 case 12:
1511                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1512                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1513                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1514                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1515                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1516                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1517                         emitpcode(POC_ADDWF, popGet(AOP(left),0));
1518                         return;
1519                 case 13:
1520                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1521                         emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 2*F
1522                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 3*F
1523                         emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 5*F
1524                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 8*F
1525                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 13*F
1526                         return;
1527                 case 14:
1528                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1529                         emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 2*F
1530                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 3*F
1531                         emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 5*F
1532                         emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 8*F
1533                         emitpcode(POC_ADDFW, popGet(AOP(left),0));  // W = 11*F
1534                         emitpcode(POC_ADDWF, popGet(AOP(left),0));  // F = 14*F
1535                         return;
1536                 case 15:
1537                         temp = popGetTempReg();
1538                         if(!temp) {
1539                                 fprintf(stderr,"ERROR: unable to allocate register. %s:%d\n",__FUNCTION__,__LINE__);
1540                                 exit(EXIT_FAILURE);
1541                         }
1542                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
1543                         emitpcode(POC_MOVWF,  temp);
1544                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
1545                         emitpcode(POC_MOVWF,  popGet(AOP(left),0));
1546                         emitpcode(POC_SWAPFW, temp);
1547                         emitpcode(POC_SUBWF,  popGet(AOP(left),0));
1548                         popReleaseTempReg(temp);
1549                         return;
1550                 case 16:
1551                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
1552                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
1553                         emitpcode(POC_MOVWF,  popGet(AOP(left),0));
1554                         return;
1555                 case 17:
1556                         emitpcode(POC_SWAPFW, popGet(AOP(left),0));
1557                         emitpcode(POC_ANDLW,  popGetLit(0xf0));
1558                         emitpcode(POC_ADDWF,  popGet(AOP(left),0));
1559                         return;
1560                 case 32:
1561                         emitpcode(POC_SWAPF,  popGet(AOP(left),0));
1562                         emitpcode(POC_RLFW,   popGet(AOP(left),0));
1563                         emitpcode(POC_ANDLW,  popGetLit(0xe0));
1564                         emitpcode(POC_MOVWF,  popGet(AOP(left),0));
1565                         return;
1566                 case 64:
1567                         emitpcode(POC_SWAPF,  popGet(AOP(left),0));
1568                         emitpcode(POC_RLF,    popGet(AOP(left),0));
1569                         emitpcode(POC_RLFW,   popGet(AOP(left),0));
1570                         emitpcode(POC_ANDLW,  popGetLit(0xc0));
1571                         emitpcode(POC_MOVWF,  popGet(AOP(left),0));
1572                         return;
1573                 case 128:
1574                         emitpcode(POC_RRFW,   popGet(AOP(left),0));
1575                         emitpcode(POC_CLRF,   popGet(AOP(left),0));
1576                         emitpcode(POC_RRF,    popGet(AOP(left),0));
1577                         return;
1578                         
1579                 }
1580         } else {
1581                 
1582                 switch(lit) {
1583                 case 0:
1584                         emitpcode(POC_CLRF,  popGet(AOP(result),0));
1585                         emitpcode(POC_CLRF,  popCopyReg(result_hi));
1586                         return;
1587                 case 2:
1588                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1589                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
1590                         emitpcode(POC_ADDWF, popGet(AOP(result),0));
1591                         emitpcode(POC_CLRF,  popCopyReg(result_hi));
1592                         emitpcode(POC_RLF,   popCopyReg(result_hi));
1593                         return;
1594                 case 4:
1595                 case 8:
1596                         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1597                         emitpcode(POC_MOVWF, popGet(AOP(result),0));
1598                         emitpcode(POC_CLRF,  popCopyReg(result_hi));
1599                         emitpcode(POC_BCF,   popCopyReg(&pc_status));
1600                         emitpcode(POC_RLF,   popGet(AOP(result),0));
1601                         emitpcode(POC_RLF,   popCopyReg(result_hi));
1602                         emitpcode(POC_RLF,   popGet(AOP(result),0));
1603                         emitpcode(POC_RLF,   popCopyReg(result_hi));
1604                         if (lit >= 8) {
1605                                 emitpcode(POC_RLF,   popGet(AOP(result),0));
1606                                 emitpcode(POC_RLF,   popCopyReg(result_hi));
1607                         }
1608                         return;
1609                 }
1610                 
1611         }
1612         
1613         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1614         emitpcode(POC_CLRF,  popGet(AOP(result),0));
1615         emitpcode(POC_CLRF,  popCopyReg(result_hi));
1616
1617         have_first_bit = 0;
1618         for(i=0; i<8; i++) {
1619                 
1620                 if(lit & 1) {
1621                         emitpcode(POC_ADDWF, popCopyReg(result_hi));
1622                         have_first_bit = 1;
1623                 }
1624                 
1625                 if(have_first_bit) {
1626                         emitpcode(POC_RRF,   popCopyReg(result_hi));
1627                         emitpcode(POC_RRF,   popGet(AOP(result),0));
1628                 }
1629                 
1630                 lit >>= 1;
1631         }
1632 }
1633
1634 /*-----------------------------------------------------------------*
1635 * genUMult8X8_16 - unsigned multiplication of two 8-bit numbers.
1636
1637
1638 *-----------------------------------------------------------------*/
1639 void genUMult8X8_16 (operand *left,
1640                                          operand *right,
1641                                          operand *result,
1642                                          pCodeOpReg *result_hi)
1643                                          
1644 {
1645         
1646         int i;
1647         int looped = 1;
1648         
1649         FENTRY;
1650         if(!result_hi) {
1651                 result_hi = PCOR(popGet(AOP(result),1));
1652         }
1653         
1654         if (AOP_TYPE(right) == AOP_LIT) {
1655                 genUMult8XLit_16(left,right,result,result_hi);
1656                 return;
1657         }
1658         
1659         if(!looped) {
1660                 pic14_emitcode(";","Unrolled 8 X 8 multiplication");
1661                 
1662                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
1663                 emitpcode(POC_CLRF,  popGet(AOP(result),0));
1664                 emitpcode(POC_CLRF,  popCopyReg(result_hi));
1665                 emitCLRC;
1666                 
1667                 for(i=0; i<8; i++) {
1668                         emitpcode(POC_BTFSC,  newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),i,0));
1669                         emitpcode(POC_ADDWF, popCopyReg(result_hi));
1670                         emitpcode(POC_RRF,   popCopyReg(result_hi));
1671                         emitpcode(POC_RRF,   popGet(AOP(result),0));
1672                 }
1673                 
1674                 
1675                 /*
1676                 Here's another version that does the same thing and takes the 
1677                 same number of instructions. The one above is slightly better
1678                 because the entry instructions have a higher probability of
1679                 being optimized out.
1680                 */
1681                 /*
1682                 emitpcode(POC_CLRF,  popCopyReg(result_hi));
1683                 emitpcode(POC_RRFW,  popGet(AOP(left),0));
1684                 emitpcode(POC_MOVWF, popGet(AOP(result),0));
1685                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
1686                 
1687                   for(i=0; i<8; i++) {
1688                   emitSKPNC;
1689                   emitpcode(POC_ADDWF, popCopyReg(result_hi));
1690                   emitpcode(POC_RRF,   popCopyReg(result_hi));
1691                   emitpcode(POC_RRF,   popGet(AOP(result),0));
1692                   }
1693                 */
1694                 
1695         } else {
1696                 symbol  *tlbl = newiTempLabel(NULL);
1697                 pCodeOp *temp;
1698                 
1699                 
1700                 pic14_emitcode(";","Looped 8 X 8 multiplication");
1701                 
1702                 emitpcode(POC_CLRF,  popGet(AOP(result),0));
1703                 emitpcode(POC_CLRF,  popCopyReg(result_hi));
1704                 
1705                 emitpcode(POC_BSF,   newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),7,0));
1706                 
1707                 emitpcode(POC_MOVFW, popGet(AOP(right),0));
1708                 
1709                 temp = popGetTempReg();
1710                 emitpcode(POC_MOVWF, popCopyReg(PCOR(temp)));
1711                 
1712                 emitpcode(POC_MOVFW, popGet(AOP(left),0));
1713                 
1714                 emitpLabel(tlbl->key);
1715                 
1716                 emitpcode(POC_RRF,   popCopyReg(PCOR(temp)));
1717                 emitSKPNC;
1718                 emitpcode(POC_ADDWF, popCopyReg(result_hi));
1719                 
1720                 emitpcode(POC_RRF,   popCopyReg(result_hi));
1721                 emitpcode(POC_RRF,   popGet(AOP(result),0));
1722                 
1723                 emitSKPC;
1724                 emitpcode(POC_GOTO,  popGetLabel(tlbl->key));
1725                 
1726                 popReleaseTempReg(temp);
1727                 
1728         }
1729 }
1730
1731 /*-----------------------------------------------------------------*
1732 * genSMult8X8_16 - signed multiplication of two 8-bit numbers
1733 *
1734 *  this routine will call the unsigned multiply routine and then
1735 * post-fix the sign bit.
1736 *-----------------------------------------------------------------*/
1737 void genSMult8X8_16 (operand *left,
1738                                          operand *right,
1739                                          operand *result,
1740                                          pCodeOpReg *result_hi)
1741 {
1742         
1743         FENTRY;
1744         if(!result_hi) {
1745                 result_hi = PCOR(popGet(AOP(result),1));
1746         }
1747         
1748         genUMult8X8_16(left,right,result,result_hi);
1749         
1750         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),7,0));
1751         emitpcode(POC_SUBWF, popCopyReg(result_hi));
1752         emitpcode(POC_MOVFW, popGet(AOP(left),0));
1753         emitpcode(POC_BTFSC, newpCodeOpBit(aopGet(AOP(right),0,FALSE,FALSE),7,0));
1754         emitpcode(POC_SUBWF, popGet(AOP(result),1));
1755         
1756 }
1757
1758 /*-----------------------------------------------------------------*
1759 * genMult8X8_8 - multiplication of two 8-bit numbers
1760 *
1761 *  this routine will call the unsigned multiply 8X8=>16 routine and
1762 * then throw away the high byte of the result.
1763 *
1764 *-----------------------------------------------------------------*/
1765 void genMult8X8_8 (operand *left,
1766                                    operand *right,
1767                                    operand *result)
1768 {
1769         pCodeOp *result_hi;
1770         FENTRY;
1771         if (result && result->aop && result->aop->type==2 && result->aop->size>=1) {
1772                 result->aop->aopu.aop_reg[0]->isFree = 0; /* Sometimes (ie part of last instruction in a blk) the result reg is pre marked as free, which mean on the next line popGetTempReg() will return this reg instead of allocating a new one. */
1773         }
1774         result_hi = popGetTempReg();
1775         
1776         if (AOP_TYPE(right) == AOP_LIT)
1777                 genUMult8XLit_16(left,right,result,PCOR(result_hi));
1778         else
1779                 genUMult8X8_16(left,right,result,PCOR(result_hi));
1780         
1781         popReleaseTempReg(result_hi);
1782 }
1783 #if 0
1784 /*-----------------------------------------------------------------*/
1785 /* constMult - generates code for multiplication by a constant     */
1786 /*-----------------------------------------------------------------*/
1787 void genMultConst(unsigned C)
1788 {
1789         
1790         unsigned lit;
1791         unsigned sr3; // Shift right 3
1792         unsigned mask;
1793         
1794         int size = 1;
1795         
1796         /*
1797         Convert a string of 3 binary 1's in the lit into
1798         0111 = 1000 - 1;
1799         */
1800         
1801         mask = 7 << ( (size*8) - 3);
1802         lit = C;
1803         sr3 = 0;
1804         
1805         while(mask < (1<<size*8)) {
1806                 
1807                 if( (mask & lit) == lit) {
1808                         unsigned lsb;
1809                         
1810                         /* We found 3 (or more) consecutive 1's */
1811                         
1812                         lsb = mask & ~(mask & (mask-1));  // lsb of mask.
1813                         
1814                         consecutive_bits = ((lit + lsb) & lit) ^ lit;
1815                         
1816                         lit ^= consecutive_bits;
1817                         
1818                         mask <<= 3;
1819                         
1820                         sr3 |= (consecutive + lsb);
1821                         
1822                 }
1823                 
1824                 mask >>= 1;
1825                 
1826         }
1827         
1828 }
1829
1830 #endif