* gen.c (genInline): reverted to old code for assemnling inline
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
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   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
30                 Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45 #include "genutils.h"
46 #include "device.h"
47 #include "main.h"
48
49 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
50 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 void pic16_genMult8X8_8 (operand *, operand *,operand *);
52 pCode *pic16_AssembleLine(char *line, int peeps);
53 extern void pic16_printpBlock(FILE *of, pBlock *pb);
54 static asmop *newAsmop (short type);
55 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset);
56 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
57 static void mov2w (asmop *aop, int offset);
58 static int aopIdx (asmop *aop, int offset);
59
60 static int labelOffset=0;
61 extern int pic16_debug_verbose;
62 static int optimized_for_speed = 0;
63 /*
64   hack hack
65
66 */
67
68 /* max_key keeps track of the largest label number used in 
69    a function. This is then used to adjust the label offset
70    for the next function.
71 */
72 static int max_key=0;
73 static int GpsuedoStkPtr=0;
74
75 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
76 unsigned int pic16aopLiteral (value *val, int offset);
77 const char *pic16_AopType(short type);
78 static iCode *ifxForOp ( operand *op, iCode *ic );
79
80 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
81
82 /* this is the down and dirty file with all kinds of 
83    kludgy & hacky stuff. This is what it is all about
84    CODE GENERATION for a specific MCU . some of the
85    routines may be reusable, will have to see */
86
87 static char *zero = "#0x00";
88 static char *one  = "#0x01";
89 static char *spname = "sp";
90
91 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
92 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
93 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
94 static char **fReturn = fReturnpic16;
95
96 static char *accUse[] = {"a","b"};
97
98 //static short rbank = -1;
99
100 static struct {
101     short r0Pushed;
102     short r1Pushed;
103     short accInUse;
104     short inLine;
105     short debugLine;
106     short nRegsSaved;
107     set *sendSet;
108 } _G;
109
110 /* Resolved ifx structure. This structure stores information
111    about an iCode ifx that makes it easier to generate code.
112 */
113 typedef struct resolvedIfx {
114   symbol *lbl;     /* pointer to a label */
115   int condition;   /* true or false ifx */
116   int generated;   /* set true when the code associated with the ifx
117                     * is generated */
118 } resolvedIfx;
119
120 extern int pic16_ptrRegReq ;
121 extern int pic16_nRegs;
122 extern FILE *codeOutFile;
123 static void saverbank (int, iCode *,bool);
124
125 static lineNode *lineHead = NULL;
126 static lineNode *lineCurr = NULL;
127
128 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
129 0xE0, 0xC0, 0x80, 0x00};
130 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
131 0x07, 0x03, 0x01, 0x00};
132
133 static  pBlock *pb;
134
135 /*-----------------------------------------------------------------*/
136 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
137 /*                 exponent of 2 is returned, otherwise -1 is      */
138 /*                 returned.                                       */
139 /* note that this is similar to the function `powof2' in SDCCsymt  */
140 /* if(n == 2^y)                                                    */
141 /*   return y;                                                     */
142 /* return -1;                                                      */
143 /*-----------------------------------------------------------------*/
144 static int my_powof2 (unsigned long num)
145 {
146   if(num) {
147     if( (num & (num-1)) == 0) {
148       int nshifts = -1;
149       while(num) {
150         num>>=1;
151         nshifts++;
152       }
153       return nshifts;
154     }
155   }
156
157   return -1;
158 }
159
160 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
161 {
162
163   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
164                        line_no,
165                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
166                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
167                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
168                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
169                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
170                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
171                        ((result) ? AOP_SIZE(result) : 0));
172
173 }
174
175 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
176 {
177
178   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
179                        line_no,
180                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
181                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
182                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
183                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
184                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
185                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
186
187 }
188
189 void pic16_emitcomment (char *fmt, ...)
190 {
191     va_list ap;
192     char lb[INITIAL_INLINEASM];  
193     char *lbp = lb;
194
195     if(!pic16_debug_verbose)
196       return;
197
198     va_start(ap,fmt);   
199
200     lb[0] = ';';
201     vsprintf(lb+1,fmt,ap);
202
203     while (isspace(*lbp)) lbp++;
204
205     if (lbp && *lbp) 
206         lineCurr = (lineCurr ?
207                     connectLine(lineCurr,newLineNode(lb)) :
208                     (lineHead = newLineNode(lb)));
209     lineCurr->isInline = _G.inLine;
210     lineCurr->isDebug  = _G.debugLine;
211
212     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
213     va_end(ap);
214
215 //      fprintf(stderr, "%s\n", lb);
216 }
217
218 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
219 {
220     va_list ap;
221     char lb[INITIAL_INLINEASM];  
222     char *lbp = lb;
223
224     if(!pic16_debug_verbose)
225       return;
226
227     va_start(ap,fmt);   
228
229     if (inst && *inst) {
230         if (fmt && *fmt)
231             sprintf(lb,"%s\t",inst);
232         else
233             sprintf(lb,"%s",inst);
234         vsprintf(lb+(strlen(lb)),fmt,ap);
235     }  else
236         vsprintf(lb,fmt,ap);
237
238     while (isspace(*lbp)) lbp++;
239
240     if (lbp && *lbp) 
241         lineCurr = (lineCurr ?
242                     connectLine(lineCurr,newLineNode(lb)) :
243                     (lineHead = newLineNode(lb)));
244     lineCurr->isInline = _G.inLine;
245     lineCurr->isDebug  = _G.debugLine;
246
247     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
248     va_end(ap);
249
250 //      fprintf(stderr, "%s\n", lb);
251 }
252
253 void pic16_emitpLabel(int key)
254 {
255   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
256 }
257
258 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
259 {
260
261   if(pcop)
262     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
263   else
264     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
265     
266 //    fprintf(stderr, "%s\n", pcop->name);
267 }
268
269 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
270 {
271
272   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
273
274 }
275
276
277 #if 1
278 #define pic16_emitcode  DEBUGpic16_emitcode
279 #else
280 /*-----------------------------------------------------------------*/
281 /* pic16_emitcode - writes the code into a file : for now it is simple    */
282 /*-----------------------------------------------------------------*/
283 void pic16_emitcode (char *inst,char *fmt, ...)
284 {
285     va_list ap;
286     char lb[INITIAL_INLINEASM];  
287     char *lbp = lb;
288
289     va_start(ap,fmt);   
290
291     if (inst && *inst) {
292         if (fmt && *fmt)
293             sprintf(lb,"%s\t",inst);
294         else
295             sprintf(lb,"%s",inst);
296         vsprintf(lb+(strlen(lb)),fmt,ap);
297     }  else
298         vsprintf(lb,fmt,ap);
299
300     while (isspace(*lbp)) lbp++;
301
302     if (lbp && *lbp) 
303         lineCurr = (lineCurr ?
304                     connectLine(lineCurr,newLineNode(lb)) :
305                     (lineHead = newLineNode(lb)));
306     lineCurr->isInline = _G.inLine;
307     lineCurr->isDebug  = _G.debugLine;
308
309 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
310
311 //    if(pic16_debug_verbose)
312 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
313
314     va_end(ap);
315 }
316 #endif
317
318
319 /*-----------------------------------------------------------------*/
320 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
321 /*-----------------------------------------------------------------*/
322 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
323 {
324     bool r0iu = FALSE , r1iu = FALSE;
325     bool r0ou = FALSE , r1ou = FALSE;
326
327         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
328
329     /* the logic: if r0 & r1 used in the instruction
330     then we are in trouble otherwise */
331
332     /* first check if r0 & r1 are used by this
333     instruction, in which case we are in trouble */
334     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
335         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
336     {
337         goto endOfWorld;      
338     }
339
340     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
341     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
342
343     /* if no usage of r0 then return it */
344     if (!r0iu && !r0ou) {
345         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
346         (*aopp)->type = AOP_R0;
347         
348         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
349     }
350
351     /* if no usage of r1 then return it */
352     if (!r1iu && !r1ou) {
353         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
354         (*aopp)->type = AOP_R1;
355
356         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
357     }    
358
359     /* now we know they both have usage */
360     /* if r0 not used in this instruction */
361     if (!r0iu) {
362         /* push it if not already pushed */
363         if (!_G.r0Pushed) {
364           //pic16_emitcode ("push","%s",
365           //          pic16_regWithIdx(R0_IDX)->dname);
366             _G.r0Pushed++ ;
367         }
368         
369         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
370         (*aopp)->type = AOP_R0;
371
372         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
373     }
374
375     /* if r1 not used then */
376
377     if (!r1iu) {
378         /* push it if not already pushed */
379         if (!_G.r1Pushed) {
380           //pic16_emitcode ("push","%s",
381           //          pic16_regWithIdx(R1_IDX)->dname);
382             _G.r1Pushed++ ;
383         }
384         
385         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
386         (*aopp)->type = AOP_R1;
387         return pic16_regWithIdx(R1_IDX);
388     }
389
390 endOfWorld :
391     /* I said end of world but not quite end of world yet */
392     /* if this is a result then we can push it on the stack*/
393     if (result) {
394         (*aopp)->type = AOP_STK;    
395         return NULL;
396     }
397
398     /* other wise this is true end of the world */
399     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
400            "getFreePtr should never reach here");
401     exit(0);
402 }
403
404 /*-----------------------------------------------------------------*/
405 /* newAsmop - creates a new asmOp                                  */
406 /*-----------------------------------------------------------------*/
407 static asmop *newAsmop (short type)
408 {
409     asmop *aop;
410
411     aop = Safe_calloc(1,sizeof(asmop));
412     aop->type = type;
413     return aop;
414 }
415
416 static void genSetDPTR(int n)
417 {
418     if (!n)
419     {
420         pic16_emitcode(";", "Select standard DPTR");
421         pic16_emitcode("mov", "dps, #0x00");
422     }
423     else
424     {
425         pic16_emitcode(";", "Select alternate DPTR");
426         pic16_emitcode("mov", "dps, #0x01");
427     }
428 }
429
430 /*-----------------------------------------------------------------*/
431 /* resolveIfx - converts an iCode ifx into a form more useful for  */
432 /*              generating code                                    */
433 /*-----------------------------------------------------------------*/
434 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
435 {
436   if(!resIfx) 
437     return;
438
439   //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
440
441   resIfx->condition = 1;    /* assume that the ifx is true */
442   resIfx->generated = 0;    /* indicate that the ifx has not been used */
443
444   if(!ifx) {
445     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
446 /*
447     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
448                         __FUNCTION__,__LINE__,resIfx->lbl->key);
449 */
450   } else {
451     if(IC_TRUE(ifx)) {
452       resIfx->lbl = IC_TRUE(ifx);
453     } else {
454       resIfx->lbl = IC_FALSE(ifx);
455       resIfx->condition = 0;
456     }
457 /*
458     if(IC_TRUE(ifx)) 
459       DEBUGpic16_emitcode("; ***","ifx true is non-null");
460     if(IC_FALSE(ifx)) 
461       DEBUGpic16_emitcode("; ***","ifx false is non-null");
462 */
463   }
464
465   //  DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
466
467 }
468 #if 0
469 /*-----------------------------------------------------------------*/
470 /* pointerCode - returns the code for a pointer type               */
471 /*-----------------------------------------------------------------*/
472 static int pointerCode (sym_link *etype)
473 {
474
475     return PTR_TYPE(SPEC_OCLS(etype));
476
477 }
478 #endif
479 /*-----------------------------------------------------------------*/
480 /* aopForSym - for a true symbol                                   */
481 /*-----------------------------------------------------------------*/
482 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
483 {
484     asmop *aop;
485     memmap *space= SPEC_OCLS(sym->etype);
486
487     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
488     /* if already has one */
489     if (sym->aop) {
490             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
491         return sym->aop;
492     }
493
494     /* assign depending on the storage class */
495     /* if it is on the stack or indirectly addressable */
496     /* space we need to assign either r0 or r1 to it   */    
497     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
498         sym->aop = aop = newAsmop(0);
499         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
500         aop->size = getSize(sym->type);
501
502         /* now assign the address of the variable to 
503         the pointer register */
504         if (aop->type != AOP_STK) {
505
506             if (sym->onStack) {
507                     if ( _G.accInUse )
508                         pic16_emitcode("push","acc");
509
510                     pic16_emitcode("mov","a,_bp");
511                     pic16_emitcode("add","a,#0x%02x",
512                              ((sym->stack < 0) ?
513                               ((char)(sym->stack - _G.nRegsSaved )) :
514                               ((char)sym->stack)) & 0xff);
515                     pic16_emitcode("mov","%s,a",
516                              aop->aopu.aop_ptr->name);
517
518                     if ( _G.accInUse )
519                         pic16_emitcode("pop","acc");
520             } else
521                 pic16_emitcode("mov","%s,#%s",
522                          aop->aopu.aop_ptr->name,
523                          sym->rname);
524             aop->paged = space->paged;
525         } else
526             aop->aopu.aop_stk = sym->stack;
527         return aop;
528     }
529     
530     if (sym->onStack && options.stack10bit)
531     {
532         /* It's on the 10 bit stack, which is located in
533          * far data space.
534          */
535          
536       //DEBUGpic16_emitcode(";","%d",__LINE__);
537
538         if ( _G.accInUse )
539                 pic16_emitcode("push","acc");
540
541         pic16_emitcode("mov","a,_bp");
542         pic16_emitcode("add","a,#0x%02x",
543                  ((sym->stack < 0) ?
544                    ((char)(sym->stack - _G.nRegsSaved )) :
545                    ((char)sym->stack)) & 0xff);
546         
547         genSetDPTR(1);
548         pic16_emitcode ("mov","dpx1,#0x40");
549         pic16_emitcode ("mov","dph1,#0x00");
550         pic16_emitcode ("mov","dpl1, a");
551         genSetDPTR(0);
552         
553         if ( _G.accInUse )
554             pic16_emitcode("pop","acc");
555             
556         sym->aop = aop = newAsmop(AOP_DPTR2);
557         aop->size = getSize(sym->type); 
558         return aop;
559     }
560
561     //DEBUGpic16_emitcode(";","%d",__LINE__);
562     /* if in bit space */
563     if (IN_BITSPACE(space)) {
564         sym->aop = aop = newAsmop (AOP_CRY);
565         aop->aopu.aop_dir = sym->rname ;
566         aop->size = getSize(sym->type);
567         //DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
568         return aop;
569     }
570     /* if it is in direct space */
571     if (IN_DIRSPACE(space)) {
572         sym->aop = aop = newAsmop (AOP_DIR);
573         aop->aopu.aop_dir = sym->rname ;
574         aop->size = getSize(sym->type);
575         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
576         return aop;
577     }
578
579     /* special case for a function */
580     if (IS_FUNC(sym->type)) {   
581         sym->aop = aop = newAsmop(AOP_IMMD);    
582         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
583         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
584         strcpy(aop->aopu.aop_immd,sym->rname);
585         aop->size = FPTRSIZE; 
586         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
587         return aop;
588     }
589
590
591     /* only remaining is far space */
592     /* in which case DPTR gets the address */
593     sym->aop = aop = newAsmop(AOP_PCODE);
594
595     aop->aopu.pcop = pic16_popGetImmd(sym->rname,0,0);
596     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
597     PCOI(aop->aopu.pcop)->index = 0;
598
599     DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
600                         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
601
602     pic16_allocDirReg (IC_LEFT(ic));
603
604     aop->size = FPTRSIZE; 
605 /*
606     DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
607     sym->aop = aop = newAsmop(AOP_DPTR);
608     pic16_emitcode ("mov","dptr,#%s", sym->rname);
609     aop->size = getSize(sym->type);
610
611     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
612 */
613
614     /* if it is in code space */
615     if (IN_CODESPACE(space))
616         aop->code = 1;
617
618     return aop;     
619 }
620
621 /*-----------------------------------------------------------------*/
622 /* aopForRemat - rematerialzes an object                           */
623 /*-----------------------------------------------------------------*/
624 static asmop *aopForRemat (operand *op) // x symbol *sym)
625 {
626   symbol *sym = OP_SYMBOL(op);
627   iCode *ic = NULL;
628   asmop *aop = newAsmop(AOP_PCODE);
629   int val = 0;
630   int offset = 0;
631
632   ic = sym->rematiCode;
633
634   DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
635   if(IS_OP_POINTER(op)) {
636     DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
637   }
638   for (;;) {
639     if (ic->op == '+') {
640       val += (int) operandLitValue(IC_RIGHT(ic));
641     } else if (ic->op == '-') {
642       val -= (int) operandLitValue(IC_RIGHT(ic));
643     } else
644       break;
645         
646     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
647   }
648
649   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
650   aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
651 #if 0
652   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
653 #else
654   PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
655 #endif
656   PCOI(aop->aopu.pcop)->index = val;
657
658   DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
659                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
660 #if 0
661                       val, IS_PTR_CONST(operandType(op)));
662 #else
663                       val, IS_CODEPTR(operandType(op)));
664 #endif
665
666   //    DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
667
668   pic16_allocDirReg (IC_LEFT(ic));
669
670   return aop;        
671 }
672
673 static int aopIdx (asmop *aop, int offset)
674 {
675   if(!aop)
676     return -1;
677
678   if(aop->type !=  AOP_REG)
679     return -2;
680         
681   return aop->aopu.aop_reg[offset]->rIdx;
682
683 }
684 /*-----------------------------------------------------------------*/
685 /* regsInCommon - two operands have some registers in common       */
686 /*-----------------------------------------------------------------*/
687 static bool regsInCommon (operand *op1, operand *op2)
688 {
689     symbol *sym1, *sym2;
690     int i;
691
692     /* if they have registers in common */
693     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
694         return FALSE ;
695
696     sym1 = OP_SYMBOL(op1);
697     sym2 = OP_SYMBOL(op2);
698
699     if (sym1->nRegs == 0 || sym2->nRegs == 0)
700         return FALSE ;
701
702     for (i = 0 ; i < sym1->nRegs ; i++) {
703         int j;
704         if (!sym1->regs[i])
705             continue ;
706
707         for (j = 0 ; j < sym2->nRegs ;j++ ) {
708             if (!sym2->regs[j])
709                 continue ;
710
711             if (sym2->regs[j] == sym1->regs[i])
712                 return TRUE ;
713         }
714     }
715
716     return FALSE ;
717 }
718
719 /*-----------------------------------------------------------------*/
720 /* operandsEqu - equivalent                                        */
721 /*-----------------------------------------------------------------*/
722 static bool operandsEqu ( operand *op1, operand *op2)
723 {
724     symbol *sym1, *sym2;
725
726     /* if they not symbols */
727     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
728         return FALSE;
729
730     sym1 = OP_SYMBOL(op1);
731     sym2 = OP_SYMBOL(op2);
732
733     /* if both are itemps & one is spilt
734        and the other is not then false */
735     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
736         sym1->isspilt != sym2->isspilt )
737         return FALSE ;
738
739     /* if they are the same */
740     if (sym1 == sym2)
741         return TRUE ;
742
743     if (strcmp(sym1->rname,sym2->rname) == 0)
744         return TRUE;
745
746
747     /* if left is a tmp & right is not */
748     if (IS_ITEMP(op1)  && 
749         !IS_ITEMP(op2) &&
750         sym1->isspilt  &&
751         (sym1->usl.spillLoc == sym2))
752         return TRUE;
753
754     if (IS_ITEMP(op2)  && 
755         !IS_ITEMP(op1) &&
756         sym2->isspilt  &&
757         sym1->level > 0 &&
758         (sym2->usl.spillLoc == sym1))
759         return TRUE ;
760
761     return FALSE ;
762 }
763
764 /*-----------------------------------------------------------------*/
765 /* pic16_sameRegs - two asmops have the same registers                   */
766 /*-----------------------------------------------------------------*/
767 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
768 {
769     int i;
770
771     if (aop1 == aop2)
772         return TRUE ;
773
774     if (aop1->type != AOP_REG ||
775         aop2->type != AOP_REG )
776         return FALSE ;
777
778     if (aop1->size != aop2->size )
779         return FALSE ;
780
781     for (i = 0 ; i < aop1->size ; i++ )
782         if (aop1->aopu.aop_reg[i] !=
783             aop2->aopu.aop_reg[i] )
784             return FALSE ;
785
786     return TRUE ;
787 }
788
789 /*-----------------------------------------------------------------*/
790 /* pic16_aopOp - allocates an asmop for an operand  :                    */
791 /*-----------------------------------------------------------------*/
792 void pic16_aopOp (operand *op, iCode *ic, bool result)
793 {
794     asmop *aop;
795     symbol *sym;
796     int i;
797
798     if (!op)
799         return ;
800
801 //      DEBUGpic16_emitcode(";","%d",__LINE__);
802
803     /* if this a literal */
804     if (IS_OP_LITERAL(op)) {
805         op->aop = aop = newAsmop(AOP_LIT);
806         aop->aopu.aop_lit = op->operand.valOperand;
807         aop->size = getSize(operandType(op));
808         return;
809     }
810
811     {
812       sym_link *type = operandType(op);
813 #if 0
814       if(IS_PTR_CONST(type))
815 #else
816       if(IS_CODEPTR(type))
817 #endif
818         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
819     }
820
821     /* if already has a asmop then continue */
822     if (op->aop)
823         return ;
824
825     /* if the underlying symbol has a aop */
826     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
827       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
828         op->aop = OP_SYMBOL(op)->aop;
829         return;
830     }
831
832     /* if this is a true symbol */
833     if (IS_TRUE_SYMOP(op)) {    
834         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
835       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
836       return ;
837     }
838
839     /* this is a temporary : this has
840     only four choices :
841     a) register
842     b) spillocation
843     c) rematerialize 
844     d) conditional   
845     e) can be a return use only */
846
847     sym = OP_SYMBOL(op);
848
849         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
850     /* if the type is a conditional */
851     if (sym->regType == REG_CND) {
852         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
853         aop->size = 0;
854         return;
855     }
856
857     /* if it is spilt then two situations
858     a) is rematerialize 
859     b) has a spill location */
860     if (sym->isspilt || sym->nRegs == 0) {
861
862       DEBUGpic16_emitcode(";","%d",__LINE__);
863         /* rematerialize it NOW */
864         if (sym->remat) {
865
866             sym->aop = op->aop = aop =
867                                       aopForRemat (op);
868             aop->size = getSize(sym->type);
869             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
870             return;
871         }
872
873         if (sym->accuse) {
874             int i;
875             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
876             aop->size = getSize(sym->type);
877             for ( i = 0 ; i < 2 ; i++ )
878                 aop->aopu.aop_str[i] = accUse[i];
879             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
880             return;  
881         }
882
883         if (sym->ruonly ) {
884           /*
885           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
886           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
887           //pic16_allocDirReg (IC_LEFT(ic));
888           aop->size = getSize(sym->type);
889           */
890
891           unsigned i;
892
893           aop = op->aop = sym->aop = newAsmop(AOP_STR);
894           aop->size = getSize(sym->type);
895           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
896             aop->aopu.aop_str[i] = fReturn[i];
897
898           DEBUGpic16_emitcode(";","%d",__LINE__);
899           return;
900         }
901
902         /* else spill location  */
903         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
904             /* force a new aop if sizes differ */
905             sym->usl.spillLoc->aop = NULL;
906         }
907         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
908                             __FUNCTION__,__LINE__,
909                             sym->usl.spillLoc->rname,
910                             sym->rname, sym->usl.spillLoc->offset);
911
912         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
913         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
914         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
915                                           getSize(sym->type), 
916                                           sym->usl.spillLoc->offset);
917         aop->size = getSize(sym->type);
918
919         return;
920     }
921
922     {
923       sym_link *type = operandType(op);
924 #if 0
925       if(IS_PTR_CONST(type)) 
926 #else
927       if(IS_CODEPTR(type)) 
928 #endif
929         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
930     }
931
932     /* must be in a register */
933     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
934     sym->aop = op->aop = aop = newAsmop(AOP_REG);
935     aop->size = sym->nRegs;
936     for ( i = 0 ; i < sym->nRegs ;i++)
937         aop->aopu.aop_reg[i] = sym->regs[i];
938 }
939
940 /*-----------------------------------------------------------------*/
941 /* pic16_freeAsmop - free up the asmop given to an operand               */
942 /*----------------------------------------------------------------*/
943 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
944 {   
945     asmop *aop ;
946
947     if (!op)
948         aop = aaop;
949     else 
950         aop = op->aop;
951
952     if (!aop)
953         return ;
954
955     if (aop->freed)
956         goto dealloc; 
957
958     aop->freed = 1;
959
960     /* depending on the asmop type only three cases need work AOP_RO
961        , AOP_R1 && AOP_STK */
962 #if 0
963     switch (aop->type) {
964         case AOP_R0 :
965             if (_G.r0Pushed ) {
966                 if (pop) {
967                     pic16_emitcode ("pop","ar0");     
968                     _G.r0Pushed--;
969                 }
970             }
971             bitVectUnSetBit(ic->rUsed,R0_IDX);
972             break;
973
974         case AOP_R1 :
975             if (_G.r1Pushed ) {
976                 if (pop) {
977                     pic16_emitcode ("pop","ar1");
978                     _G.r1Pushed--;
979                 }
980             }
981             bitVectUnSetBit(ic->rUsed,R1_IDX);          
982             break;
983
984         case AOP_STK :
985         {
986             int sz = aop->size;    
987             int stk = aop->aopu.aop_stk + aop->size;
988             bitVectUnSetBit(ic->rUsed,R0_IDX);
989             bitVectUnSetBit(ic->rUsed,R1_IDX);          
990
991             getFreePtr(ic,&aop,FALSE);
992             
993             if (options.stack10bit)
994             {
995                 /* I'm not sure what to do here yet... */
996                 /* #STUB */
997                 fprintf(stderr, 
998                         "*** Warning: probably generating bad code for "
999                         "10 bit stack mode.\n");
1000             }
1001             
1002             if (stk) {
1003                 pic16_emitcode ("mov","a,_bp");
1004                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1005                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1006             } else {
1007                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1008             }
1009
1010             while (sz--) {
1011                 pic16_emitcode("pop","acc");
1012                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1013                 if (!sz) break;
1014                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1015             }
1016             op->aop = aop;
1017             pic16_freeAsmop(op,NULL,ic,TRUE);
1018             if (_G.r0Pushed) {
1019                 pic16_emitcode("pop","ar0");
1020                 _G.r0Pushed--;
1021             }
1022
1023             if (_G.r1Pushed) {
1024                 pic16_emitcode("pop","ar1");
1025                 _G.r1Pushed--;
1026             }       
1027         }
1028     }
1029 #endif
1030
1031 dealloc:
1032     /* all other cases just dealloc */
1033     if (op ) {
1034         op->aop = NULL;
1035         if (IS_SYMOP(op)) {
1036             OP_SYMBOL(op)->aop = NULL;    
1037             /* if the symbol has a spill */
1038             if (SPIL_LOC(op))
1039                 SPIL_LOC(op)->aop = NULL;
1040         }
1041     }
1042 }
1043
1044 /*-----------------------------------------------------------------*/
1045 /* pic16_aopGet - for fetching value of the aop                          */
1046 /*-----------------------------------------------------------------*/
1047 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1048 {
1049     char *s = buffer ;
1050     char *rs;
1051
1052     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1053     /* offset is greater than
1054     size then zero */
1055     if (offset > (aop->size - 1) &&
1056         aop->type != AOP_LIT)
1057         return zero;
1058
1059     /* depending on type */
1060     switch (aop->type) {
1061         
1062     case AOP_R0:
1063     case AOP_R1:
1064         DEBUGpic16_emitcode(";","%d",__LINE__);
1065         /* if we need to increment it */       
1066         while (offset > aop->coff) {        
1067             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1068             aop->coff++;
1069         }
1070         
1071         while (offset < aop->coff) {
1072             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1073             aop->coff--;
1074         }
1075         
1076         aop->coff = offset ;
1077         if (aop->paged) {
1078             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1079             return (dname ? "acc" : "a");
1080         }       
1081         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1082         rs = Safe_calloc(1,strlen(s)+1);
1083         strcpy(rs,s);   
1084         return rs;
1085         
1086     case AOP_DPTR:
1087     case AOP_DPTR2:
1088         DEBUGpic16_emitcode(";","%d",__LINE__);
1089     if (aop->type == AOP_DPTR2)
1090     {
1091         genSetDPTR(1);
1092     }
1093     
1094         while (offset > aop->coff) {
1095             pic16_emitcode ("inc","dptr");
1096             aop->coff++;
1097         }
1098         
1099         while (offset < aop->coff) {        
1100             pic16_emitcode("lcall","__decdptr");
1101             aop->coff--;
1102         }
1103         
1104         aop->coff = offset;
1105         if (aop->code) {
1106             pic16_emitcode("clr","a");
1107             pic16_emitcode("movc","a,@a+dptr");
1108         }
1109     else {
1110             pic16_emitcode("movx","a,@dptr");
1111     }
1112             
1113     if (aop->type == AOP_DPTR2)
1114     {
1115         genSetDPTR(0);
1116     }
1117             
1118     return (dname ? "acc" : "a");
1119         
1120         
1121     case AOP_IMMD:
1122         if (bit16) 
1123             sprintf (s,"%s",aop->aopu.aop_immd);
1124         else
1125             if (offset) 
1126                 sprintf(s,"(%s >> %d)",
1127                         aop->aopu.aop_immd,
1128                         offset*8);
1129             else
1130                 sprintf(s,"%s",
1131                         aop->aopu.aop_immd);
1132         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1133         rs = Safe_calloc(1,strlen(s)+1);
1134         strcpy(rs,s);   
1135         return rs;
1136         
1137     case AOP_DIR:
1138       if (offset) {
1139         sprintf(s,"(%s + %d)",
1140                 aop->aopu.aop_dir,
1141                 offset);
1142         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1143       } else
1144             sprintf(s,"%s",aop->aopu.aop_dir);
1145         rs = Safe_calloc(1,strlen(s)+1);
1146         strcpy(rs,s);   
1147         return rs;
1148         
1149     case AOP_REG:
1150       //if (dname) 
1151       //    return aop->aopu.aop_reg[offset]->dname;
1152       //else
1153             return aop->aopu.aop_reg[offset]->name;
1154         
1155     case AOP_CRY:
1156       //pic16_emitcode(";","%d",__LINE__);
1157       return aop->aopu.aop_dir;
1158         
1159     case AOP_ACC:
1160         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1161         return "AOP_accumulator_bug";
1162
1163     case AOP_LIT:
1164         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1165         rs = Safe_calloc(1,strlen(s)+1);
1166         strcpy(rs,s);   
1167         return rs;
1168         
1169     case AOP_STR:
1170         aop->coff = offset ;
1171         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1172             dname)
1173             return "acc";
1174         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1175         
1176         return aop->aopu.aop_str[offset];
1177         
1178     case AOP_PCODE:
1179       {
1180         pCodeOp *pcop = aop->aopu.pcop;
1181         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1182         if(pcop->name) {
1183           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1184           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1185           sprintf(s,"%s", pcop->name);
1186         } else
1187           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1188
1189       }
1190       rs = Safe_calloc(1,strlen(s)+1);
1191       strcpy(rs,s);   
1192       return rs;
1193
1194     }
1195
1196     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1197            "aopget got unsupported aop->type");
1198     exit(0);
1199 }
1200
1201
1202 /*-----------------------------------------------------------------*/
1203 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1204 /*-----------------------------------------------------------------*/
1205 pCodeOp *pic16_popGetTempReg(void)
1206 {
1207
1208   pCodeOp *pcop;
1209
1210   pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1211   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1212     PCOR(pcop)->r->wasUsed=1;
1213     PCOR(pcop)->r->isFree=0;
1214   }
1215
1216   return pcop;
1217 }
1218
1219 /*-----------------------------------------------------------------*/
1220 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1221 /*-----------------------------------------------------------------*/
1222 void pic16_popReleaseTempReg(pCodeOp *pcop)
1223 {
1224
1225   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1226     PCOR(pcop)->r->isFree = 1;
1227
1228 }
1229 /*-----------------------------------------------------------------*/
1230 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1231 /*-----------------------------------------------------------------*/
1232 pCodeOp *pic16_popGetLabel(unsigned int key)
1233 {
1234
1235   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1236
1237   if(key>max_key)
1238     max_key = key;
1239
1240   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1241 }
1242
1243 /*-----------------------------------------------------------------*/
1244 /* pic16_popCopyReg - copy a pcode operator                              */
1245 /*-----------------------------------------------------------------*/
1246 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1247 {
1248   pCodeOpReg *pcor;
1249
1250   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1251   pcor->pcop.type = pc->pcop.type;
1252   if(pc->pcop.name) {
1253     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1254       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1255   } else
1256     pcor->pcop.name = NULL;
1257
1258   pcor->r = pc->r;
1259   pcor->rIdx = pc->rIdx;
1260   pcor->r->wasUsed=1;
1261
1262   //DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1263
1264   return PCOP(pcor);
1265 }
1266
1267 /*-----------------------------------------------------------------*/
1268 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1269 /*-----------------------------------------------------------------*/
1270 pCodeOp *pic16_popGetLit(unsigned int lit)
1271 {
1272   return pic16_newpCodeOpLit(lit);
1273 }
1274
1275 /*-----------------------------------------------------------------*/
1276 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1277 /*-----------------------------------------------------------------*/
1278 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1279 {
1280   return pic16_newpCodeOpLit2(lit, arg2);
1281 }
1282
1283
1284 /*-----------------------------------------------------------------*/
1285 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1286 /*-----------------------------------------------------------------*/
1287 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1288 {
1289
1290   return pic16_newpCodeOpImmd(name, offset,index, 0);
1291 }
1292
1293
1294 /*-----------------------------------------------------------------*/
1295 /* pic16_popGet - asm operator to pcode operator conversion              */
1296 /*-----------------------------------------------------------------*/
1297 pCodeOp *pic16_popGetWithString(char *str)
1298 {
1299   pCodeOp *pcop;
1300
1301
1302   if(!str) {
1303     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1304     exit (1);
1305   }
1306
1307   pcop = pic16_newpCodeOp(str,PO_STR);
1308
1309   return pcop;
1310 }
1311
1312 /*-----------------------------------------------------------------*/
1313 /* pic16_popRegFromString -                                        */
1314 /*-----------------------------------------------------------------*/
1315 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1316 {
1317
1318   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1319   pcop->type = PO_DIR;
1320
1321   DEBUGpic16_emitcode(";","%d %s %s",__LINE__, __FUNCTION__, str);
1322 //  fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1323
1324   if(!str)
1325     str = "BAD_STRING";
1326
1327   pcop->name = Safe_calloc(1,strlen(str)+1);
1328   strcpy(pcop->name,str);
1329
1330   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1331
1332   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1333   if(PCOR(pcop)->r == NULL) {
1334 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1335 //              __FUNCTION__, __LINE__, str, size, offset);
1336     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1337
1338         //fprintf(stderr, "allocating new register -> %s\n", str);
1339
1340     DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1341   } else {
1342     DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1343   }
1344   PCOR(pcop)->instance = offset;
1345
1346   return pcop;
1347 }
1348
1349 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1350 {
1351   pCodeOp *pcop;
1352
1353 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1354
1355         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1356         PCOR(pcop)->rIdx = rIdx;
1357         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1358         PCOR(pcop)->r->isFree = 0;
1359         PCOR(pcop)->r->wasUsed = 1;
1360
1361         pcop->type = PCOR(pcop)->r->pc_type;
1362
1363   return pcop;
1364 }
1365
1366 /*---------------------------------------------------------------------------------*/
1367 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1368 /*                 VR 030601                                                       */
1369 /*---------------------------------------------------------------------------------*/
1370 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1371 {
1372   pCodeOpReg2 *pcop2;
1373   pCodeOp *temp;
1374   
1375         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1376
1377         /* comment the following check, so errors to throw up */
1378 //      if(!pcop2)return NULL;
1379
1380         temp = pic16_popGet(aop_dst, offset);
1381         pcop2->pcop2 = temp;
1382         
1383   return PCOP(pcop2);
1384 }
1385
1386
1387
1388 /*--------------------------------------------------------------------------------.-*/
1389 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1390 /*                  VR 030601 , adapted by Hans Dorn                                */
1391 /*--------------------------------------------------------------------------------.-*/
1392 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1393 {
1394         pCodeOpReg2 *pcop2;
1395  
1396         pcop2 = (pCodeOpReg2 *) src;
1397         pcop2->pcop2 = dst;
1398         
1399         return PCOP(pcop2);
1400 }
1401
1402
1403
1404 /*---------------------------------------------------------------------------------*/
1405 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1406 /*                     movff instruction                                           */
1407 /*---------------------------------------------------------------------------------*/
1408 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1409 {
1410   pCodeOpReg2 *pcop2;
1411
1412         if(!noalloc) {
1413                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1414                 pcop2->pcop2 = pic16_popCopyReg(dst);
1415         } else {
1416                 /* the pCodeOp may be already allocated */
1417                 pcop2 = (pCodeOpReg2 *)(src);
1418                 pcop2->pcop2 = (pCodeOp *)(dst);
1419         }
1420
1421   return PCOP(pcop2);
1422 }
1423
1424
1425 /*-----------------------------------------------------------------*/
1426 /* pic16_popGet - asm operator to pcode operator conversion              */
1427 /*-----------------------------------------------------------------*/
1428 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1429 {
1430   //char *s = buffer ;
1431     //char *rs;
1432
1433     pCodeOp *pcop;
1434
1435     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1436     /* offset is greater than
1437     size then zero */
1438
1439     if (offset > (aop->size - 1) &&
1440         aop->type != AOP_LIT)
1441       return NULL;  //zero;
1442
1443     /* depending on type */
1444     switch (aop->type) {
1445         
1446     case AOP_R0:
1447     case AOP_R1:
1448     case AOP_DPTR:
1449     case AOP_DPTR2:
1450     case AOP_ACC:
1451         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1452         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1453         return NULL;
1454         
1455     case AOP_IMMD:
1456       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1457       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1458
1459     case AOP_DIR:
1460       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1461       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1462         
1463     case AOP_REG:
1464       {
1465         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1466
1467         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1468         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1469         PCOR(pcop)->rIdx = rIdx;
1470         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1471         PCOR(pcop)->r->wasUsed=1;
1472         PCOR(pcop)->r->isFree=0;
1473
1474         PCOR(pcop)->instance = offset;
1475         pcop->type = PCOR(pcop)->r->pc_type;
1476         //rs = aop->aopu.aop_reg[offset]->name;
1477         //DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1478         return pcop;
1479       }
1480
1481     case AOP_CRY:
1482         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1483
1484       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1485       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1486       //if(PCOR(pcop)->r == NULL)
1487       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1488       return pcop;
1489         
1490     case AOP_LIT:
1491         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1492       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1493
1494     case AOP_STR:
1495       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1496       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1497
1498       /*
1499       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1500       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1501       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1502       pcop->type = PCOR(pcop)->r->pc_type;
1503       pcop->name = PCOR(pcop)->r->name;
1504
1505       return pcop;
1506       */
1507
1508     case AOP_PCODE:
1509       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s",pic16_pCodeOpType(aop->aopu.pcop),
1510                           __LINE__, 
1511                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1512       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1513       PCOI(pcop)->offset = offset;
1514       return pcop;
1515     }
1516
1517     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1518            "pic16_popGet got unsupported aop->type");
1519     exit(0);
1520 }
1521 /*-----------------------------------------------------------------*/
1522 /* pic16_aopPut - puts a string for a aop                                */
1523 /*-----------------------------------------------------------------*/
1524 void pic16_aopPut (asmop *aop, char *s, int offset)
1525 {
1526     char *d = buffer ;
1527     symbol *lbl ;
1528
1529     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1530
1531     if (aop->size && offset > ( aop->size - 1)) {
1532         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1533                "pic16_aopPut got offset > aop->size");
1534         exit(0);
1535     }
1536
1537     /* will assign value to value */
1538     /* depending on where it is ofcourse */
1539     switch (aop->type) {
1540     case AOP_DIR:
1541       if (offset) {
1542         sprintf(d,"(%s + %d)",
1543                 aop->aopu.aop_dir,offset);
1544         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1545
1546       } else
1547             sprintf(d,"%s",aop->aopu.aop_dir);
1548         
1549         if (strcmp(d,s)) {
1550           DEBUGpic16_emitcode(";","%d",__LINE__);
1551           if(strcmp(s,"W"))
1552             pic16_emitcode("movf","%s,w",s);
1553           pic16_emitcode("movwf","%s",d);
1554
1555           if(strcmp(s,"W")) {
1556             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1557             if(offset >= aop->size) {
1558               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1559               break;
1560             } else
1561               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1562           }
1563
1564           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1565
1566
1567         }
1568         break;
1569         
1570     case AOP_REG:
1571       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1572         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1573           /*
1574             if (*s == '@'           ||
1575                 strcmp(s,"r0") == 0 ||
1576                 strcmp(s,"r1") == 0 ||
1577                 strcmp(s,"r2") == 0 ||
1578                 strcmp(s,"r3") == 0 ||
1579                 strcmp(s,"r4") == 0 ||
1580                 strcmp(s,"r5") == 0 ||
1581                 strcmp(s,"r6") == 0 || 
1582                 strcmp(s,"r7") == 0 )
1583                 pic16_emitcode("mov","%s,%s  ; %d",
1584                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1585             else
1586           */
1587
1588           if(strcmp(s,"W")==0 )
1589             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1590
1591           pic16_emitcode("movwf","%s",
1592                    aop->aopu.aop_reg[offset]->name);
1593
1594           if(strcmp(s,zero)==0) {
1595             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1596
1597           } else if(strcmp(s,"W")==0) {
1598             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1599             pcop->type = PO_GPR_REGISTER;
1600
1601             PCOR(pcop)->rIdx = -1;
1602             PCOR(pcop)->r = NULL;
1603
1604             DEBUGpic16_emitcode(";","%d",__LINE__);
1605             pcop->name = Safe_strdup(s);
1606             pic16_emitpcode(POC_MOVFW,pcop);
1607             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1608           } else if(strcmp(s,one)==0) {
1609             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1610             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1611           } else {
1612             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1613           }
1614         }
1615         break;
1616         
1617     case AOP_DPTR:
1618     case AOP_DPTR2:
1619     
1620     if (aop->type == AOP_DPTR2)
1621     {
1622         genSetDPTR(1);
1623     }
1624     
1625         if (aop->code) {
1626             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1627                    "pic16_aopPut writting to code space");
1628             exit(0);
1629         }
1630         
1631         while (offset > aop->coff) {
1632             aop->coff++;
1633             pic16_emitcode ("inc","dptr");
1634         }
1635         
1636         while (offset < aop->coff) {
1637             aop->coff-- ;
1638             pic16_emitcode("lcall","__decdptr");
1639         }
1640         
1641         aop->coff = offset;
1642         
1643         /* if not in accumulater */
1644         MOVA(s);        
1645         
1646         pic16_emitcode ("movx","@dptr,a");
1647         
1648     if (aop->type == AOP_DPTR2)
1649     {
1650         genSetDPTR(0);
1651     }
1652         break;
1653         
1654     case AOP_R0:
1655     case AOP_R1:
1656         while (offset > aop->coff) {
1657             aop->coff++;
1658             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1659         }
1660         while (offset < aop->coff) {
1661             aop->coff-- ;
1662             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1663         }
1664         aop->coff = offset;
1665         
1666         if (aop->paged) {
1667             MOVA(s);           
1668             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1669             
1670         } else
1671             if (*s == '@') {
1672                 MOVA(s);
1673                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1674             } else
1675                 if (strcmp(s,"r0") == 0 ||
1676                     strcmp(s,"r1") == 0 ||
1677                     strcmp(s,"r2") == 0 ||
1678                     strcmp(s,"r3") == 0 ||
1679                     strcmp(s,"r4") == 0 ||
1680                     strcmp(s,"r5") == 0 ||
1681                     strcmp(s,"r6") == 0 || 
1682                     strcmp(s,"r7") == 0 ) {
1683                     char buffer[10];
1684                     sprintf(buffer,"a%s",s);
1685                     pic16_emitcode("mov","@%s,%s",
1686                              aop->aopu.aop_ptr->name,buffer);
1687                 } else
1688                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1689         
1690         break;
1691         
1692     case AOP_STK:
1693         if (strcmp(s,"a") == 0)
1694             pic16_emitcode("push","acc");
1695         else
1696             pic16_emitcode("push","%s",s);
1697         
1698         break;
1699         
1700     case AOP_CRY:
1701         /* if bit variable */
1702         if (!aop->aopu.aop_dir) {
1703             pic16_emitcode("clr","a");
1704             pic16_emitcode("rlc","a");
1705         } else {
1706             if (s == zero) 
1707                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1708             else
1709                 if (s == one)
1710                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1711                 else
1712                     if (!strcmp(s,"c"))
1713                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1714                     else {
1715                         lbl = newiTempLabel(NULL);
1716                         
1717                         if (strcmp(s,"a")) {
1718                             MOVA(s);
1719                         }
1720                         pic16_emitcode("clr","c");
1721                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1722                         pic16_emitcode("cpl","c");
1723                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1724                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1725                     }
1726         }
1727         break;
1728         
1729     case AOP_STR:
1730         aop->coff = offset;
1731         if (strcmp(aop->aopu.aop_str[offset],s))
1732             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1733         break;
1734         
1735     case AOP_ACC:
1736         aop->coff = offset;
1737         if (!offset && (strcmp(s,"acc") == 0))
1738             break;
1739         
1740         if (strcmp(aop->aopu.aop_str[offset],s))
1741             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1742         break;
1743
1744     default :
1745         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1746                "pic16_aopPut got unsupported aop->type");
1747         exit(0);    
1748     }    
1749
1750 }
1751
1752 /*-----------------------------------------------------------------*/
1753 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1754 /*-----------------------------------------------------------------*/
1755 static void mov2w (asmop *aop, int offset)
1756 {
1757
1758   if(!aop)
1759     return;
1760
1761   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1762
1763   if ( aop->type == AOP_PCODE ||
1764        aop->type == AOP_LIT )
1765     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1766   else
1767     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1768
1769 }
1770
1771
1772 void pic16_pushpCodeOpReg(pCodeOpReg *pcop)
1773 {
1774         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pcop, &pic16_pc_postdec1, 0));
1775 }
1776
1777 void pic16_poppCodeOpReg(pCodeOpReg *pcop)
1778 {
1779         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, pcop, 0));
1780 }
1781
1782
1783 /*-----------------------------------------------------------------*/
1784 /* pushw - pushes wreg to stack                                    */
1785 /*-----------------------------------------------------------------*/
1786 void pushw(void)
1787 {
1788         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1789         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1790 }
1791
1792                 
1793 /*-----------------------------------------------------------------*/
1794 /* pushaop - pushes aop to stack                                   */
1795 /*-----------------------------------------------------------------*/
1796 void pushaop(asmop *aop, int offset)
1797 {
1798         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1799         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1800 }
1801
1802 /*-----------------------------------------------------------------*/
1803 /* popaop - pops aop from stack                                    */
1804 /*-----------------------------------------------------------------*/
1805 void popaop(asmop *aop, int offset)
1806 {
1807         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1808         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1809 }
1810
1811 void popaopidx(asmop *aop, int offset, int index)
1812 {
1813   int ofs=1;
1814
1815         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1816
1817         if(STACK_MODEL_LARGE)ofs++;
1818
1819         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1820         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1821 }
1822
1823 /*-----------------------------------------------------------------*/
1824 /* reAdjustPreg - points a register back to where it should        */
1825 /*-----------------------------------------------------------------*/
1826 static void reAdjustPreg (asmop *aop)
1827 {
1828     int size ;
1829
1830     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1831     aop->coff = 0;
1832     if ((size = aop->size) <= 1)
1833         return ;
1834     size-- ;
1835     switch (aop->type) {
1836         case AOP_R0 :
1837         case AOP_R1 :
1838             while (size--)
1839                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1840             break;          
1841         case AOP_DPTR :
1842         case AOP_DPTR2:
1843             if (aop->type == AOP_DPTR2)
1844             {
1845                 genSetDPTR(1);
1846             } 
1847             while (size--)
1848             {
1849                 pic16_emitcode("lcall","__decdptr");
1850             }
1851                 
1852             if (aop->type == AOP_DPTR2)
1853             {
1854                 genSetDPTR(0);
1855             }                
1856             break;  
1857
1858     }   
1859
1860 }
1861
1862
1863 #if 0
1864 /*-----------------------------------------------------------------*/
1865 /* opIsGptr: returns non-zero if the passed operand is             */   
1866 /* a generic pointer type.                                         */
1867 /*-----------------------------------------------------------------*/ 
1868 static int opIsGptr(operand *op)
1869 {
1870     sym_link *type = operandType(op);
1871     
1872     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1873     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1874     {
1875         return 1;
1876     }
1877     return 0;        
1878 }
1879 #endif
1880
1881 /*-----------------------------------------------------------------*/
1882 /* pic16_getDataSize - get the operand data size                         */
1883 /*-----------------------------------------------------------------*/
1884 int pic16_getDataSize(operand *op)
1885 {
1886     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1887
1888
1889     return AOP_SIZE(op);
1890
1891     // tsd- in the pic port, the genptr size is 1, so this code here
1892     // fails. ( in the 8051 port, the size was 4).
1893 #if 0
1894     int size;
1895     size = AOP_SIZE(op);
1896     if (size == GPTRSIZE)
1897     {
1898         sym_link *type = operandType(op);
1899         if (IS_GENPTR(type))
1900         {
1901             /* generic pointer; arithmetic operations
1902              * should ignore the high byte (pointer type).
1903              */
1904             size--;
1905     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1906         }
1907     }
1908     return size;
1909 #endif
1910 }
1911
1912 /*-----------------------------------------------------------------*/
1913 /* pic16_outAcc - output Acc                                             */
1914 /*-----------------------------------------------------------------*/
1915 void pic16_outAcc(operand *result)
1916 {
1917   int size,offset;
1918   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1919   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
1920
1921
1922   size = pic16_getDataSize(result);
1923   if(size){
1924     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
1925     size--;
1926     offset = 1;
1927     /* unsigned or positive */
1928     while(size--)
1929       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1930   }
1931
1932 }
1933
1934 /*-----------------------------------------------------------------*/
1935 /* pic16_outBitC - output a bit C                                        */
1936 /*-----------------------------------------------------------------*/
1937 void pic16_outBitC(operand *result)
1938 {
1939
1940     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1941     /* if the result is bit */
1942     if (AOP_TYPE(result) == AOP_CRY) 
1943         pic16_aopPut(AOP(result),"c",0);
1944     else {
1945         pic16_emitcode("clr","a  ; %d", __LINE__);
1946         pic16_emitcode("rlc","a");
1947         pic16_outAcc(result);
1948     }
1949 }
1950
1951 /*-----------------------------------------------------------------*/
1952 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
1953 /*-----------------------------------------------------------------*/
1954 void pic16_toBoolean(operand *oper)
1955 {
1956     int size = AOP_SIZE(oper) - 1;
1957     int offset = 1;
1958
1959     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1960
1961     if ( AOP_TYPE(oper) != AOP_ACC) {
1962       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
1963     }
1964     while (size--) {
1965       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
1966     }
1967 }
1968
1969
1970 #if !defined(GEN_Not)
1971 /*-----------------------------------------------------------------*/
1972 /* genNot - generate code for ! operation                          */
1973 /*-----------------------------------------------------------------*/
1974 static void pic16_genNot (iCode *ic)
1975 {
1976   symbol *tlbl;
1977   int size;
1978
1979   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1980   /* assign asmOps to operand & result */
1981   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1982   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1983
1984   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1985   /* if in bit space then a special case */
1986   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1987     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1988       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1989       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1990     } else {
1991       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1992       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
1993       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1994     }
1995     goto release;
1996   }
1997
1998   size = AOP_SIZE(IC_LEFT(ic));
1999   if(size == 1) {
2000     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2001     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2002     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2003     goto release;
2004   }
2005   pic16_toBoolean(IC_LEFT(ic));
2006
2007   tlbl = newiTempLabel(NULL);
2008   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2009   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2010   pic16_outBitC(IC_RESULT(ic));
2011
2012  release:    
2013   /* release the aops */
2014   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2015   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2016 }
2017 #endif
2018
2019
2020 #if !defined(GEN_Cpl)
2021 /*-----------------------------------------------------------------*/
2022 /* genCpl - generate code for complement                           */
2023 /*-----------------------------------------------------------------*/
2024 static void pic16_genCpl (iCode *ic)
2025 {
2026     int offset = 0;
2027     int size ;
2028
2029
2030     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2031     /* assign asmOps to operand & result */
2032     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2033     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2034
2035     /* if both are in bit space then 
2036     a special case */
2037     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2038         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2039
2040         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2041         pic16_emitcode("cpl","c"); 
2042         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2043         goto release; 
2044     } 
2045
2046     size = AOP_SIZE(IC_RESULT(ic));
2047     while (size--) {
2048 /*
2049         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2050         MOVA(l);       
2051         pic16_emitcode("cpl","a");
2052         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2053 */
2054         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2055               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2056         } else {
2057                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2058                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2059         }
2060         offset++;
2061
2062     }
2063
2064
2065 release:
2066     /* release the aops */
2067     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2068     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2069 }
2070 #endif
2071
2072 /*-----------------------------------------------------------------*/
2073 /* genUminusFloat - unary minus for floating points                */
2074 /*-----------------------------------------------------------------*/
2075 static void genUminusFloat(operand *op,operand *result)
2076 {
2077     int size ,offset =0 ;
2078     char *l;
2079
2080     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2081     /* for this we just need to flip the 
2082     first it then copy the rest in place */
2083     size = AOP_SIZE(op) - 1;
2084     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2085
2086     MOVA(l);    
2087
2088     pic16_emitcode("cpl","acc.7");
2089     pic16_aopPut(AOP(result),"a",3);    
2090
2091     while(size--) {
2092         pic16_aopPut(AOP(result),
2093                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2094                offset);
2095         offset++;
2096     }          
2097 }
2098
2099 /*-----------------------------------------------------------------*/
2100 /* genUminus - unary minus code generation                         */
2101 /*-----------------------------------------------------------------*/
2102 static void genUminus (iCode *ic)
2103 {
2104   int size, i;
2105   sym_link *optype, *rtype;
2106
2107
2108   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2109   /* assign asmops */
2110   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2111   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2112
2113   /* if both in bit space then special
2114      case */
2115   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2116       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2117
2118     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2119     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2120     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2121
2122     goto release; 
2123   } 
2124
2125   optype = operandType(IC_LEFT(ic));
2126   rtype = operandType(IC_RESULT(ic));
2127
2128   /* if float then do float stuff */
2129   if (IS_FLOAT(optype)) {
2130     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2131     goto release;
2132   }
2133
2134   /* otherwise subtract from zero by taking the 2's complement */
2135   size = AOP_SIZE(IC_LEFT(ic));
2136
2137   for(i=0; i<size; i++) {
2138     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2139       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2140     else {
2141       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2142       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2143     }
2144   }
2145
2146   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2147   for(i=1; i<size; i++) {
2148     emitSKPNZ;
2149     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2150   }
2151
2152  release:
2153   /* release the aops */
2154   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2155   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2156 }
2157
2158 /*-----------------------------------------------------------------*/
2159 /* saveRegisters - will look for a call and save the registers     */
2160 /*-----------------------------------------------------------------*/
2161 static void saveRegisters(iCode *lic) 
2162 {
2163     int i;
2164     iCode *ic;
2165     bitVect *rsave;
2166     sym_link *dtype;
2167
2168     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2169     /* look for call */
2170     for (ic = lic ; ic ; ic = ic->next) 
2171         if (ic->op == CALL || ic->op == PCALL)
2172             break;
2173
2174     if (!ic) {
2175         fprintf(stderr,"found parameter push with no function call\n");
2176         return ;
2177     }
2178
2179     /* if the registers have been saved already then
2180     do nothing */
2181     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2182         return ;
2183
2184     /* find the registers in use at this time 
2185     and push them away to safety */
2186     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2187                           ic->rUsed);
2188
2189     ic->regsSaved = 1;
2190     if (options.useXstack) {
2191         if (bitVectBitValue(rsave,R0_IDX))
2192             pic16_emitcode("mov","b,r0");
2193         pic16_emitcode("mov","r0,%s",spname);
2194         for (i = 0 ; i < pic16_nRegs ; i++) {
2195             if (bitVectBitValue(rsave,i)) {
2196                 if (i == R0_IDX)
2197                     pic16_emitcode("mov","a,b");
2198                 else
2199                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2200                 pic16_emitcode("movx","@r0,a");
2201                 pic16_emitcode("inc","r0");
2202             }
2203         }
2204         pic16_emitcode("mov","%s,r0",spname);
2205         if (bitVectBitValue(rsave,R0_IDX))
2206             pic16_emitcode("mov","r0,b");           
2207     }// else
2208     //for (i = 0 ; i < pic16_nRegs ; i++) {
2209     //    if (bitVectBitValue(rsave,i))
2210     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2211     //}
2212
2213     dtype = operandType(IC_LEFT(ic));
2214     if (currFunc && dtype && 
2215         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2216         IFFUNC_ISISR(currFunc->type) &&
2217         !ic->bankSaved) 
2218
2219         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2220
2221 }
2222 /*-----------------------------------------------------------------*/
2223 /* unsaveRegisters - pop the pushed registers                      */
2224 /*-----------------------------------------------------------------*/
2225 static void unsaveRegisters (iCode *ic)
2226 {
2227     int i;
2228     bitVect *rsave;
2229
2230     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2231     /* find the registers in use at this time 
2232     and push them away to safety */
2233     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2234                           ic->rUsed);
2235     
2236     if (options.useXstack) {
2237         pic16_emitcode("mov","r0,%s",spname);   
2238         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2239             if (bitVectBitValue(rsave,i)) {
2240                 pic16_emitcode("dec","r0");
2241                 pic16_emitcode("movx","a,@r0");
2242                 if (i == R0_IDX)
2243                     pic16_emitcode("mov","b,a");
2244                 else
2245                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2246             }       
2247
2248         }
2249         pic16_emitcode("mov","%s,r0",spname);
2250         if (bitVectBitValue(rsave,R0_IDX))
2251             pic16_emitcode("mov","r0,b");
2252     } //else
2253     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2254     //    if (bitVectBitValue(rsave,i))
2255     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2256     //}
2257
2258 }  
2259
2260
2261 /*-----------------------------------------------------------------*/
2262 /* pushSide -                                                      */
2263 /*-----------------------------------------------------------------*/
2264 static void pushSide(operand * oper, int size)
2265 {
2266 #if 0
2267         int offset = 0;
2268     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2269         while (size--) {
2270                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2271                 if (AOP_TYPE(oper) != AOP_REG &&
2272                     AOP_TYPE(oper) != AOP_DIR &&
2273                     strcmp(l,"a") ) {
2274                         pic16_emitcode("mov","a,%s",l);
2275                         pic16_emitcode("push","acc");
2276                 } else
2277                         pic16_emitcode("push","%s",l);
2278         }
2279 #endif
2280 }
2281
2282 /*-----------------------------------------------------------------*/
2283 /* assignResultValue -                                             */
2284 /*-----------------------------------------------------------------*/
2285 static void assignResultValue(operand * oper)
2286 {
2287   int size = AOP_SIZE(oper);
2288
2289         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2290         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2291
2292         if(!GpsuedoStkPtr) {
2293 //              DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2294                 /* The last byte in the assignment is in W */
2295                 size--;
2296                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2297                 GpsuedoStkPtr++;
2298         }
2299
2300         while (size--) {
2301 //              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2302 //              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2303                 
2304 #if STACK_SUPPORT
2305                 if(USE_STACK) {
2306                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2307                 } else {
2308                         pic16_emitpcode(POC_MOVFW, pic16_popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2309                 }
2310 #else
2311                 pic16_emitpcode(POC_MOVFW, pic16_popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2312 #endif  /* STACK_SUPPORT */
2313                 GpsuedoStkPtr++;
2314
2315 #if STACK_SUPPORT
2316                 if(!USE_STACK)
2317                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2318 #else
2319                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2320 #endif
2321
2322         }
2323                 
2324 }
2325
2326
2327 /*-----------------------------------------------------------------*/
2328 /* genIpush - genrate code for pushing this gets a little complex  */
2329 /*-----------------------------------------------------------------*/
2330 static void genIpush (iCode *ic)
2331 {
2332
2333   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2334 #if 0
2335     int size, offset = 0 ;
2336     char *l;
2337
2338
2339     /* if this is not a parm push : ie. it is spill push 
2340     and spill push is always done on the local stack */
2341     if (!ic->parmPush) {
2342
2343         /* and the item is spilt then do nothing */
2344         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2345             return ;
2346
2347         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2348         size = AOP_SIZE(IC_LEFT(ic));
2349         /* push it on the stack */
2350         while(size--) {
2351             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2352             if (*l == '#') {
2353                 MOVA(l);
2354                 l = "acc";
2355             }
2356             pic16_emitcode("push","%s",l);
2357         }
2358         return ;        
2359     }
2360
2361     /* this is a paramter push: in this case we call
2362     the routine to find the call and save those
2363     registers that need to be saved */   
2364     saveRegisters(ic);
2365
2366     /* then do the push */
2367     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2368
2369
2370         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2371     size = AOP_SIZE(IC_LEFT(ic));
2372
2373     while (size--) {
2374         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2375         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2376             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2377             strcmp(l,"a") ) {
2378             pic16_emitcode("mov","a,%s",l);
2379             pic16_emitcode("push","acc");
2380         } else
2381             pic16_emitcode("push","%s",l);
2382     }       
2383
2384     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2385 #endif
2386 }
2387
2388 /*-----------------------------------------------------------------*/
2389 /* genIpop - recover the registers: can happen only for spilling   */
2390 /*-----------------------------------------------------------------*/
2391 static void genIpop (iCode *ic)
2392 {
2393   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2394 #if 0
2395     int size,offset ;
2396
2397
2398     /* if the temp was not pushed then */
2399     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2400         return ;
2401
2402     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2403     size = AOP_SIZE(IC_LEFT(ic));
2404     offset = (size-1);
2405     while (size--) 
2406         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2407                                    FALSE,TRUE));
2408
2409     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2410 #endif
2411 }
2412
2413 /*-----------------------------------------------------------------*/
2414 /* unsaverbank - restores the resgister bank from stack            */
2415 /*-----------------------------------------------------------------*/
2416 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2417 {
2418   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2419 #if 0
2420     int i;
2421     asmop *aop ;
2422     regs *r = NULL;
2423
2424     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2425     if (popPsw) {
2426         if (options.useXstack) {
2427             aop = newAsmop(0);
2428             r = getFreePtr(ic,&aop,FALSE);
2429             
2430             
2431             pic16_emitcode("mov","%s,_spx",r->name);
2432             pic16_emitcode("movx","a,@%s",r->name);
2433             pic16_emitcode("mov","psw,a");
2434             pic16_emitcode("dec","%s",r->name);
2435             
2436         }else
2437             pic16_emitcode ("pop","psw");
2438     }
2439
2440     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2441         if (options.useXstack) {       
2442             pic16_emitcode("movx","a,@%s",r->name);
2443             //pic16_emitcode("mov","(%s+%d),a",
2444             //       regspic16[i].base,8*bank+regspic16[i].offset);
2445             pic16_emitcode("dec","%s",r->name);
2446
2447         } else 
2448           pic16_emitcode("pop",""); //"(%s+%d)",
2449         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2450     }
2451
2452     if (options.useXstack) {
2453
2454         pic16_emitcode("mov","_spx,%s",r->name);
2455         pic16_freeAsmop(NULL,aop,ic,TRUE);
2456
2457     }
2458 #endif 
2459 }
2460
2461 /*-----------------------------------------------------------------*/
2462 /* saverbank - saves an entire register bank on the stack          */
2463 /*-----------------------------------------------------------------*/
2464 static void saverbank (int bank, iCode *ic, bool pushPsw)
2465 {
2466   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2467 #if 0
2468     int i;
2469     asmop *aop ;
2470     regs *r = NULL;
2471
2472     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2473     if (options.useXstack) {
2474
2475         aop = newAsmop(0);
2476         r = getFreePtr(ic,&aop,FALSE);  
2477         pic16_emitcode("mov","%s,_spx",r->name);
2478
2479     }
2480
2481     for (i = 0 ; i < pic16_nRegs ;i++) {
2482         if (options.useXstack) {
2483             pic16_emitcode("inc","%s",r->name);
2484             //pic16_emitcode("mov","a,(%s+%d)",
2485             //         regspic16[i].base,8*bank+regspic16[i].offset);
2486             pic16_emitcode("movx","@%s,a",r->name);           
2487         } else 
2488           pic16_emitcode("push","");// "(%s+%d)",
2489                      //regspic16[i].base,8*bank+regspic16[i].offset);
2490     }
2491     
2492     if (pushPsw) {
2493         if (options.useXstack) {
2494             pic16_emitcode("mov","a,psw");
2495             pic16_emitcode("movx","@%s,a",r->name);     
2496             pic16_emitcode("inc","%s",r->name);
2497             pic16_emitcode("mov","_spx,%s",r->name);       
2498             pic16_freeAsmop (NULL,aop,ic,TRUE);
2499             
2500         } else
2501             pic16_emitcode("push","psw");
2502         
2503         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2504     }
2505     ic->bankSaved = 1;
2506 #endif
2507 }
2508
2509
2510
2511 /*-----------------------------------------------------------------*/
2512 /* genCall - generates a call statement                            */
2513 /*-----------------------------------------------------------------*/
2514 static void genCall (iCode *ic)
2515 {
2516   sym_link *dtype;   
2517   int stackParms=0;
2518   
2519         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2520
2521         /* if caller saves & we have not saved then */
2522         if (!ic->regsSaved)
2523                 saveRegisters(ic);
2524
2525         /* if we are calling a function that is not using
2526          * the same register bank then we need to save the
2527          * destination registers on the stack */
2528         dtype = operandType(IC_LEFT(ic));
2529         if (currFunc && dtype && 
2530                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2531                 IFFUNC_ISISR(currFunc->type) &&
2532                 !ic->bankSaved) 
2533
2534                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2535
2536         /* if send set is not empty the assign */
2537         if (_G.sendSet) {
2538           iCode *sic;
2539
2540                 /* For the Pic port, there is no data stack.
2541                  * So parameters passed to functions are stored
2542                  * in registers. (The pCode optimizer will get
2543                  * rid of most of these :). */
2544
2545           int psuedoStkPtr=-1; 
2546           int firstTimeThruLoop = 1;
2547
2548                 _G.sendSet = reverseSet(_G.sendSet);
2549
2550                 /* First figure how many parameters are getting passed */
2551                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2552                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2553                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2554                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2555                 }
2556
2557                 stackParms = psuedoStkPtr;
2558
2559                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2560                   int size, offset = 0;
2561
2562                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2563                         size = AOP_SIZE(IC_LEFT(sic));
2564
2565                         while (size--) {
2566                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2567                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2568                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2569
2570                                 if(!firstTimeThruLoop) {
2571                                         /* If this is not the first time we've been through the loop
2572                                          * then we need to save the parameter in a temporary
2573                                          * register. The last byte of the last parameter is
2574                                          * passed in W. */
2575
2576 #if STACK_SUPPORT
2577                                         if(USE_STACK) {
2578                                                 pushw();
2579                                                 --psuedoStkPtr;         // sanity check
2580                                         } else {
2581                                                 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2582                                         }
2583 #else
2584                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2585 #endif  /* STACK_SUPPORT */
2586                                 }
2587                         
2588                                 firstTimeThruLoop=0;
2589
2590                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2591                                 offset++;
2592                         }
2593                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2594                 }
2595                 _G.sendSet = NULL;
2596         }
2597
2598         /* make the call */
2599         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2600                         OP_SYMBOL(IC_LEFT(ic))->rname :
2601                         OP_SYMBOL(IC_LEFT(ic))->name));
2602
2603         GpsuedoStkPtr=0;
2604         /* if we need assign a result value */
2605         if ((IS_ITEMP(IC_RESULT(ic)) && 
2606                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2607                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2608                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2609
2610                 _G.accInUse++;
2611                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2612                 _G.accInUse--;
2613
2614                 assignResultValue(IC_RESULT(ic));
2615
2616                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2617                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2618                 
2619                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2620         }
2621
2622 #if STACK_SUPPORT
2623         if(USE_STACK && stackParms>0) {
2624                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2625                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2626                 if(STACK_MODEL_LARGE) {
2627                         emitSKPNC;
2628                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2629                 }
2630         }
2631 #endif
2632
2633         /* adjust the stack for parameters if required */
2634 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2635
2636         if (ic->parmBytes) {
2637           int i;
2638
2639                 if (ic->parmBytes > 3) {
2640                         pic16_emitcode("mov","a,%s",spname);
2641                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2642                         pic16_emitcode("mov","%s,a",spname);
2643                 } else 
2644                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2645                                 pic16_emitcode("dec","%s",spname);
2646         }
2647
2648         /* if register bank was saved then pop them */
2649         if (ic->bankSaved)
2650                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2651
2652         /* if we hade saved some registers then unsave them */
2653         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2654                 unsaveRegisters (ic);
2655 }
2656
2657 /*-----------------------------------------------------------------*/
2658 /* genPcall - generates a call by pointer statement                */
2659 /*-----------------------------------------------------------------*/
2660 static void genPcall (iCode *ic)
2661 {
2662     sym_link *dtype;
2663     symbol *rlbl = newiTempLabel(NULL);
2664
2665
2666     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2667     /* if caller saves & we have not saved then */
2668     if (!ic->regsSaved)
2669         saveRegisters(ic);
2670
2671     /* if we are calling a function that is not using
2672     the same register bank then we need to save the
2673     destination registers on the stack */
2674     dtype = operandType(IC_LEFT(ic));
2675     if (currFunc && dtype && 
2676         IFFUNC_ISISR(currFunc->type) &&
2677         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2678         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2679
2680
2681     /* push the return address on to the stack */
2682     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2683     pic16_emitcode("push","acc");    
2684     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2685     pic16_emitcode("push","acc");
2686     
2687     if (options.model == MODEL_FLAT24)
2688     {
2689         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2690         pic16_emitcode("push","acc");    
2691     }
2692
2693     /* now push the calling address */
2694     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2695
2696     pushSide(IC_LEFT(ic), FPTRSIZE);
2697
2698     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2699
2700     /* if send set is not empty the assign */
2701     if (_G.sendSet) {
2702         iCode *sic ;
2703
2704         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2705              sic = setNextItem(_G.sendSet)) {
2706             int size, offset = 0;
2707             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2708             size = AOP_SIZE(IC_LEFT(sic));
2709             while (size--) {
2710                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
2711                                 FALSE,FALSE);
2712                 if (strcmp(l,fReturn[offset]))
2713                     pic16_emitcode("mov","%s,%s",
2714                              fReturn[offset],
2715                              l);
2716                 offset++;
2717             }
2718             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2719         }
2720         _G.sendSet = NULL;
2721     }
2722
2723     pic16_emitcode("ret","");
2724     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
2725
2726
2727     /* if we need assign a result value */
2728     if ((IS_ITEMP(IC_RESULT(ic)) &&
2729          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2730           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2731         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2732
2733         _G.accInUse++;
2734         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2735         _G.accInUse--;
2736         
2737         assignResultValue(IC_RESULT(ic));
2738
2739         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2740     }
2741
2742     /* adjust the stack for parameters if 
2743     required */
2744     if (ic->parmBytes) {
2745         int i;
2746         if (ic->parmBytes > 3) {
2747             pic16_emitcode("mov","a,%s",spname);
2748             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2749             pic16_emitcode("mov","%s,a",spname);
2750         } else 
2751             for ( i = 0 ; i <  ic->parmBytes ;i++)
2752                 pic16_emitcode("dec","%s",spname);
2753
2754     }
2755
2756     /* if register bank was saved then unsave them */
2757     if (currFunc && dtype && 
2758         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2759         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2760
2761     /* if we hade saved some registers then
2762     unsave them */
2763     if (ic->regsSaved)
2764         unsaveRegisters (ic);
2765
2766 }
2767
2768 /*-----------------------------------------------------------------*/
2769 /* resultRemat - result  is rematerializable                       */
2770 /*-----------------------------------------------------------------*/
2771 static int resultRemat (iCode *ic)
2772 {
2773   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2774   if (SKIP_IC(ic) || ic->op == IFX)
2775     return 0;
2776
2777   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2778     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2779     if (sym->remat && !POINTER_SET(ic)) 
2780       return 1;
2781   }
2782
2783   return 0;
2784 }
2785
2786 #if defined(__BORLANDC__) || defined(_MSC_VER)
2787 #define STRCASECMP stricmp
2788 #else
2789 #define STRCASECMP strcasecmp
2790 #endif
2791
2792 #if 0
2793 /*-----------------------------------------------------------------*/
2794 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2795 /*-----------------------------------------------------------------*/
2796 static bool inExcludeList(char *s)
2797 {
2798   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2799     int i =0;
2800     
2801     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2802     if (options.excludeRegs[i] &&
2803     STRCASECMP(options.excludeRegs[i],"none") == 0)
2804         return FALSE ;
2805
2806     for ( i = 0 ; options.excludeRegs[i]; i++) {
2807         if (options.excludeRegs[i] &&
2808         STRCASECMP(s,options.excludeRegs[i]) == 0)
2809             return TRUE;
2810     }
2811     return FALSE ;
2812 }
2813 #endif
2814
2815 /*-----------------------------------------------------------------*/
2816 /* genFunction - generated code for function entry                 */
2817 /*-----------------------------------------------------------------*/
2818 static void genFunction (iCode *ic)
2819 {
2820   symbol *sym;
2821   sym_link *ftype;
2822
2823         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2824
2825         labelOffset += (max_key+4);
2826         max_key=0;
2827         GpsuedoStkPtr=0;
2828         _G.nRegsSaved = 0;
2829         /* create the function header */
2830         pic16_emitcode(";","-----------------------------------------");
2831         pic16_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2832         pic16_emitcode(";","-----------------------------------------");
2833
2834         pic16_emitcode("","%s:",sym->rname);
2835         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
2836
2837         {
2838           absSym *ab;
2839
2840                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
2841                         if(strcmp(ab->name, sym->name)) {
2842                                 pic16_pBlockConvert2Absolute(pb);
2843                                 break;
2844                         }
2845                 
2846         }
2847
2848         ftype = operandType(IC_LEFT(ic));
2849
2850         if(IFFUNC_ISNAKED(ftype)) {
2851                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
2852                 return;
2853         }
2854         
2855
2856         /* if critical function then turn interrupts off */
2857         if (IFFUNC_ISCRITICAL(ftype))
2858                 pic16_emitcode("clr","ea");
2859
2860         /* here we need to generate the equates for the
2861          * register bank if required */
2862 #if 0
2863         if (FUNC_REGBANK(ftype) != rbank) {
2864           int i ;
2865
2866                 rbank = FUNC_REGBANK(ftype);
2867                 for ( i = 0 ; i < pic16_nRegs ; i++ ) {
2868                         if (strcmp(regspic16[i].base,"0") == 0)
2869                                 pic16_emitcode("","%s = 0x%02x",
2870                                         regspic16[i].dname,
2871                                         8*rbank+regspic16[i].offset);
2872                         else
2873                                 pic16_emitcode ("","%s = %s + 0x%02x",
2874                                         regspic16[i].dname,
2875                                         regspic16[i].base,
2876                                         *rbank+regspic16[i].offset);
2877                 }
2878         }
2879 #endif
2880
2881         /* if this is an interrupt service routine then
2882          * save acc, b, dpl, dph  */
2883         if (IFFUNC_ISISR(sym->type)) {
2884                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_wsave));
2885                 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_status));
2886                 pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2887                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_ssave));
2888
2889                 pic16_pBlockConvert2ISR(pb);
2890 #if 0  
2891                 if (!inExcludeList("acc"))          
2892                         pic16_emitcode ("push","acc");  
2893                 if (!inExcludeList("b"))
2894                         pic16_emitcode ("push","b");
2895                 if (!inExcludeList("dpl"))
2896                         pic16_emitcode ("push","dpl");
2897                 if (!inExcludeList("dph"))
2898                         pic16_emitcode ("push","dph");
2899                 
2900                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx")) {
2901                         pic16_emitcode ("push", "dpx");
2902
2903                         /* Make sure we're using standard DPTR */
2904                         pic16_emitcode ("push", "dps");
2905                         pic16_emitcode ("mov", "dps, #0x00");
2906                         if (options.stack10bit) {       
2907                                 /* This ISR could conceivably use DPTR2. Better save it. */
2908                                 pic16_emitcode ("push", "dpl1");
2909                                 pic16_emitcode ("push", "dph1");
2910                                 pic16_emitcode ("push", "dpx1");
2911                         }
2912                 }
2913
2914                 /* if this isr has no bank i.e. is going to
2915                  * run with bank 0 , then we need to save more
2916                  * registers :-) */
2917                 if (!FUNC_REGBANK(sym->type)) {
2918
2919                         /* if this function does not call any other
2920                          * function then we can be economical and
2921                          * save only those registers that are used */
2922                         if (! IFFUNC_HASFCALL(sym->type)) {
2923                           int i;
2924
2925                                 /* if any registers used */
2926                                 if (sym->regsUsed) {
2927                                         /* save the registers used */
2928                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2929                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2930                                                         (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2931                                                 pic16_emitcode("push","junk");//"%s",pic16_regWithIdx(i)->dname);                           
2932                                         }
2933                                 }
2934
2935                         } else {
2936                                 /* this function has  a function call cannot
2937                                  * determines register usage so we will have the
2938                                  * entire bank */
2939                                 saverbank(0,ic,FALSE);
2940                         }           
2941                 }
2942 #endif
2943         } else {
2944 #if STACK_SUPPORT
2945                 /* emit code to setup stack frame if user enabled,
2946                  * and function is not main() */
2947          
2948 //              fprintf(stderr, "function name: %s\n", sym->name);
2949                 if(USE_STACK && strcmp(sym->name, "main")) {
2950                         if(!options.ommitFramePtr || sym->regsUsed) {
2951                         /* setup the stack frame */
2952                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
2953                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
2954                                 if(STACK_MODEL_LARGE)
2955                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
2956                         }
2957                 }
2958 #endif
2959
2960                 /* if callee-save to be used for this function
2961                 * then save the registers being used in this function */
2962                 if (IFFUNC_CALLEESAVES(sym->type)) {
2963                   int i;
2964             
2965 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %p\n", __FILE__, __LINE__, sym->regsUsed);
2966                         
2967                         /* if any registers used */
2968                         if (sym->regsUsed
2969 #if STACK_SUPPORT
2970                                 && USE_STACK
2971 #endif
2972                                 ) {
2973                                 /* save the registers used */
2974                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
2975                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2976                                         if (bitVectBitValue(sym->regsUsed,i)) {
2977 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
2978 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
2979 //                                                              pic16_regWithIdx(i)->name);
2980
2981                                                 pic16_pushpCodeOpReg( PCOR(pic16_popRegFromIdx(i) ));
2982 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
2983 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
2984 //                                                      &pic16_pc_postdec1, 0));
2985                                                 _G.nRegsSaved++;
2986                                         }
2987                                 }
2988                         }
2989                 }
2990         }
2991
2992
2993         
2994 #if 0
2995         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2996
2997                 if (options.useXstack) {
2998                         pic16_emitcode("mov","r0,%s",spname);
2999                         pic16_emitcode("mov","a,_bp");
3000                         pic16_emitcode("movx","@r0,a");
3001                         pic16_emitcode("inc","%s",spname);
3002                 } else {
3003                         /* set up the stack */
3004                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3005                 }
3006                 pic16_emitcode ("mov","_bp,%s",spname);
3007         }
3008 #endif
3009         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3010
3011         /* adjust the stack for the function */
3012         if (sym->stack) {
3013           int i = sym->stack;
3014
3015                 if (i > 127 ) 
3016                         werror(W_STACK_OVERFLOW,sym->name);
3017
3018                 if (i > 3 && sym->recvSize < 4) {              
3019                         pic16_emitcode ("mov","a,sp");
3020                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3021                         pic16_emitcode ("mov","sp,a");
3022                 } else
3023                         while(i--)
3024                                 pic16_emitcode("inc","sp");
3025         }
3026
3027         if (sym->xstack) {
3028                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3029
3030                 pic16_emitcode ("mov","a,_spx");
3031                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3032                 pic16_emitcode ("mov","_spx,a");
3033         }
3034     
3035 }
3036
3037 /*-----------------------------------------------------------------*/
3038 /* genEndFunction - generates epilogue for functions               */
3039 /*-----------------------------------------------------------------*/
3040 static void genEndFunction (iCode *ic)
3041 {
3042     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3043
3044     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3045
3046     if(IFFUNC_ISNAKED(sym->type)) {
3047         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3048         return;
3049     }
3050
3051 #if 0
3052     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3053     {
3054         pic16_emitcode ("mov","%s,_bp",spname);
3055     }
3056 #endif
3057
3058     /* if use external stack but some variables were
3059     added to the local stack then decrement the
3060     local stack */
3061     if (options.useXstack && sym->stack) {      
3062         pic16_emitcode("mov","a,sp");
3063         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3064         pic16_emitcode("mov","sp,a");
3065     }
3066
3067
3068 #if 0
3069     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3070         if (options.useXstack) {
3071             pic16_emitcode("mov","r0,%s",spname);
3072             pic16_emitcode("movx","a,@r0");
3073             pic16_emitcode("mov","_bp,a");
3074             pic16_emitcode("dec","%s",spname);
3075         }
3076         else
3077         {
3078             pic16_emitcode ("pop","_bp");
3079         }
3080     }
3081 #endif
3082
3083     /* restore the register bank  */    
3084     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3085         pic16_emitcode ("pop","psw");
3086
3087     if (IFFUNC_ISISR(sym->type)) {
3088
3089         /* now we need to restore the registers */
3090         /* if this isr has no bank i.e. is going to
3091            run with bank 0 , then we need to save more
3092            registers :-) */
3093         if (!FUNC_REGBANK(sym->type)) {
3094             
3095             /* if this function does not call any other
3096                function then we can be economical and
3097                save only those registers that are used */
3098             if (! IFFUNC_HASFCALL(sym->type)) {
3099                 int i;
3100                 
3101                 /* if any registers used */
3102                 if (sym->regsUsed) {
3103                     /* save the registers used */
3104                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3105                         if (bitVectBitValue(sym->regsUsed,i) ||
3106                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3107                           pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
3108                     }
3109                 }
3110                 
3111             } else {
3112                 /* this function has  a function call cannot
3113                    determines register usage so we will have the
3114                    entire bank */
3115                 unsaverbank(0,ic,FALSE);
3116             }       
3117         }
3118 #if 0
3119         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3120         {
3121             if (options.stack10bit)
3122             {
3123                 pic16_emitcode ("pop", "dpx1");
3124                 pic16_emitcode ("pop", "dph1");
3125                 pic16_emitcode ("pop", "dpl1");
3126             }   
3127             pic16_emitcode ("pop", "dps");
3128             pic16_emitcode ("pop", "dpx");
3129         }
3130         if (!inExcludeList("dph"))
3131             pic16_emitcode ("pop","dph");
3132         if (!inExcludeList("dpl"))
3133             pic16_emitcode ("pop","dpl");
3134         if (!inExcludeList("b"))
3135             pic16_emitcode ("pop","b");
3136         if (!inExcludeList("acc"))
3137             pic16_emitcode ("pop","acc");
3138
3139         if (IFFUNC_ISCRITICAL(sym->type))
3140             pic16_emitcode("setb","ea");
3141 #endif
3142
3143         /* if debug then send end of function */
3144 /*      if (options.debug && currFunc) { */
3145         if (currFunc) {
3146             _G.debugLine = 1;
3147             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3148                      FileBaseName(ic->filename),currFunc->lastLine,
3149                      ic->level,ic->block); 
3150             if (IS_STATIC(currFunc->etype))         
3151                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3152             else
3153                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3154             _G.debugLine = 0;
3155         }
3156         
3157 //      pic16_emitcode ("reti","");
3158
3159         pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
3160         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
3161         pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
3162         pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
3163         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
3164
3165 #if 0
3166         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("END_OF_INTERRUPT",-1));
3167 #endif
3168
3169         pic16_emitpcodeNULLop(POC_RETFIE);
3170
3171     }
3172     else {
3173         if (IFFUNC_ISCRITICAL(sym->type))
3174             pic16_emitcode("setb","ea");
3175         
3176         /* if any registers used */
3177         if (sym->regsUsed
3178 #if STACK_SUPPORT
3179                 && USE_STACK
3180 #endif
3181         ) {
3182           int i;
3183                 /* save the registers used */
3184                 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3185                 for ( i = sym->regsUsed->size; i >= 0; i--) {
3186                         if (bitVectBitValue(sym->regsUsed,i)) {
3187 //                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3188 //                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3189 //                                              pic16_regWithIdx(i)->name);
3190         
3191                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3192                                         &pic16_pc_preinc1,
3193                                         PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3194                         }
3195                 }
3196         }
3197         
3198
3199         /* if debug then send end of function */
3200         if (currFunc) {
3201             _G.debugLine = 1;
3202             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3203                      FileBaseName(ic->filename),currFunc->lastLine,
3204                      ic->level,ic->block); 
3205             if (IS_STATIC(currFunc->etype))         
3206                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3207             else
3208                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3209             _G.debugLine = 0;
3210         }
3211
3212 #if STACK_SUPPORT
3213         /* insert code to restore stack frame, if user enabled it
3214          * and function is not main() */
3215          
3216         if(USE_STACK && strcmp(sym->name, "main")) {
3217                 if(!options.ommitFramePtr || sym->regsUsed) {
3218                         /* restore stack frame */
3219                         if(STACK_MODEL_LARGE)
3220                                 pic16_emitpcode(POC_MOVFF,
3221                                         pic16_popCombine2( &pic16_pc_postinc1, &pic16_pc_fsr2h, 0));
3222                         pic16_emitpcode(POC_MOVFF,
3223                                         pic16_popCombine2( &pic16_pc_postinc1, &pic16_pc_fsr2l, 0));
3224                 }
3225         }
3226 #endif
3227
3228         pic16_emitcode ("return","");
3229         pic16_emitpcodeNULLop(POC_RETURN);
3230
3231         /* Mark the end of a function */
3232         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3233     }
3234
3235 }
3236
3237 /*-----------------------------------------------------------------*/
3238 /* genRet - generate code for return statement                     */
3239 /*-----------------------------------------------------------------*/
3240 static void genRet (iCode *ic)
3241 {
3242   int size,offset = 0 , pushed = 0;
3243     
3244   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3245   /* if we have no return value then
3246      just generate the "ret" */
3247   if (!IC_LEFT(ic)) 
3248     goto jumpret;       
3249     
3250   /* we have something to return then
3251      move the return value into place */
3252   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3253   size = AOP_SIZE(IC_LEFT(ic));
3254     
3255   while (size--) {
3256     char *l ;
3257     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3258       /* #NOCHANGE */
3259       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,
3260                  FALSE,TRUE);
3261       pic16_emitcode("push","%s",l);
3262       pushed++;
3263     } else {
3264         DEBUGpic16_emitcode(";", "%d", __LINE__);
3265       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,
3266                  FALSE,FALSE);
3267         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3268       if (strcmp(fReturn[offset],l)) {
3269         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3270             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3271           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3272         }else {
3273           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3274         }
3275         if(size) {
3276           pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3277         }
3278         offset++;
3279       }
3280     }
3281   }    
3282
3283   if (pushed) {
3284     while(pushed) {
3285       pushed--;
3286       if (strcmp(fReturn[pushed],"a"))
3287         pic16_emitcode("pop",fReturn[pushed]);
3288       else
3289         pic16_emitcode("pop","acc");
3290     }
3291   }
3292   pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3293     
3294  jumpret:
3295   /* generate a jump to the return label
3296      if the next is not the return statement */
3297   if (!(ic->next && ic->next->op == LABEL &&
3298         IC_LABEL(ic->next) == returnLabel)) {
3299         
3300     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3301     pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3302   }
3303     
3304 }
3305
3306 /*-----------------------------------------------------------------*/
3307 /* genLabel - generates a label                                    */
3308 /*-----------------------------------------------------------------*/
3309 static void genLabel (iCode *ic)
3310 {
3311     /* special case never generate */
3312     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3313     if (IC_LABEL(ic) == entryLabel)
3314         return ;
3315
3316     pic16_emitpLabel(IC_LABEL(ic)->key);
3317     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3318 }
3319
3320 /*-----------------------------------------------------------------*/
3321 /* genGoto - generates a goto                                      */
3322 /*-----------------------------------------------------------------*/
3323 //tsd
3324 static void genGoto (iCode *ic)
3325 {
3326   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3327   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3328 }
3329
3330
3331 /*-----------------------------------------------------------------*/
3332 /* genMultbits :- multiplication of bits                           */
3333 /*-----------------------------------------------------------------*/
3334 static void genMultbits (operand *left, 
3335                          operand *right, 
3336                          operand *result)
3337 {
3338   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3339
3340   if(!pic16_sameRegs(AOP(result),AOP(right)))
3341     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3342
3343   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3344   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3345   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3346
3347 }
3348
3349
3350 /*-----------------------------------------------------------------*/
3351 /* genMultOneByte : 8 bit multiplication & division                */
3352 /*-----------------------------------------------------------------*/
3353 static void genMultOneByte (operand *left,
3354                             operand *right,
3355                             operand *result)
3356 {
3357   sym_link *opetype = operandType(result);
3358
3359   // symbol *lbl ;
3360   int size,offset;
3361
3362   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3363   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3364   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3365
3366   /* (if two literals, the value is computed before) */
3367   /* if one literal, literal on the right */
3368   if (AOP_TYPE(left) == AOP_LIT){
3369     operand *t = right;
3370     right = left;
3371     left = t;
3372   }
3373
3374   size = AOP_SIZE(result);
3375   if(size == 1) {
3376
3377     if (AOP_TYPE(right) == AOP_LIT){
3378       pic16_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3379                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3380                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3381                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3382       pic16_emitcode("call","genMultLit");
3383     } else {
3384       pic16_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3385                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3386                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3387                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3388       pic16_emitcode("call","pic16_genMult8X8_8");
3389
3390     }
3391     pic16_genMult8X8_8 (left, right,result);
3392
3393
3394     /* signed or unsigned */
3395     //pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3396     //l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3397     //MOVA(l);       
3398     //pic16_emitcode("mul","ab");
3399     /* if result size = 1, mul signed = mul unsigned */
3400     //pic16_aopPut(AOP(result),"a",0);
3401
3402   } else {  // (size > 1)
3403
3404     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3405                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3406                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3407                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3408
3409     if (SPEC_USIGN(opetype)){
3410       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3411       pic16_genUMult8X8_16 (left, right, result, NULL);
3412
3413       if (size > 2) {
3414         /* for filling the MSBs */
3415         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3416         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3417       }
3418     }
3419     else{
3420       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3421
3422       pic16_emitcode("mov","a,b");
3423
3424       /* adjust the MSB if left or right neg */
3425
3426       /* if one literal */
3427       if (AOP_TYPE(right) == AOP_LIT){
3428         pic16_emitcode("multiply ","right is a lit");
3429         /* AND literal negative */
3430         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3431           /* adjust MSB (c==0 after mul) */
3432           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3433         }
3434       }
3435       else{
3436         pic16_genSMult8X8_16 (left, right, result, NULL);
3437       }
3438
3439       if(size > 2){
3440         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3441         /* get the sign */
3442         pic16_emitcode("rlc","a");
3443         pic16_emitcode("subb","a,acc");
3444       }
3445     }
3446
3447     size -= 2;   
3448     offset = 2;
3449     if (size > 0)
3450       while (size--)
3451         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3452     //pic16_aopPut(AOP(result),"a",offset++);
3453   }
3454 }
3455
3456 /*-----------------------------------------------------------------*/
3457 /* genMult - generates code for multiplication                     */
3458 /*-----------------------------------------------------------------*/
3459 static void genMult (iCode *ic)
3460 {
3461     operand *left = IC_LEFT(ic);
3462     operand *right = IC_RIGHT(ic);
3463     operand *result= IC_RESULT(ic);   
3464
3465     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3466     /* assign the amsops */
3467     pic16_aopOp (left,ic,FALSE);
3468     pic16_aopOp (right,ic,FALSE);
3469     pic16_aopOp (result,ic,TRUE);
3470
3471   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3472
3473     /* special cases first */
3474     /* both are bits */
3475     if (AOP_TYPE(left) == AOP_CRY &&
3476         AOP_TYPE(right)== AOP_CRY) {
3477         genMultbits(left,right,result);
3478         goto release ;
3479     }
3480
3481     /* if both are of size == 1 */
3482     if (AOP_SIZE(left) == 1 &&
3483         AOP_SIZE(right) == 1 ) {
3484         genMultOneByte(left,right,result);
3485         goto release ;
3486     }
3487
3488     pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3489
3490     /* should have been converted to function call */
3491     //assert(0) ;
3492
3493 release :
3494     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3495     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3496     pic16_freeAsmop(result,NULL,ic,TRUE); 
3497 }
3498
3499 /*-----------------------------------------------------------------*/
3500 /* genDivbits :- division of bits                                  */
3501 /*-----------------------------------------------------------------*/
3502 static void genDivbits (operand *left, 
3503                         operand *right, 
3504                         operand *result)
3505 {
3506
3507     char *l;
3508
3509     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3510     /* the result must be bit */    
3511     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3512     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3513
3514     MOVA(l);    
3515
3516     pic16_emitcode("div","ab");
3517     pic16_emitcode("rrc","a");
3518     pic16_aopPut(AOP(result),"c",0);
3519 }
3520
3521 /*-----------------------------------------------------------------*/
3522 /* genDivOneByte : 8 bit division                                  */
3523 /*-----------------------------------------------------------------*/
3524 static void genDivOneByte (operand *left,
3525                            operand *right,
3526                            operand *result)
3527 {
3528     sym_link *opetype = operandType(result);
3529     char *l ;
3530     symbol *lbl ;
3531     int size,offset;
3532
3533     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3534     size = AOP_SIZE(result) - 1;
3535     offset = 1;
3536     /* signed or unsigned */
3537     if (SPEC_USIGN(opetype)) {
3538         /* unsigned is easy */
3539         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3540         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3541         MOVA(l);        
3542         pic16_emitcode("div","ab");
3543         pic16_aopPut(AOP(result),"a",0);
3544         while (size--)
3545             pic16_aopPut(AOP(result),zero,offset++);
3546         return ;
3547     }
3548
3549     /* signed is a little bit more difficult */
3550
3551     /* save the signs of the operands */
3552     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3553     MOVA(l);    
3554     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3555     pic16_emitcode("push","acc"); /* save it on the stack */
3556
3557     /* now sign adjust for both left & right */
3558     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3559     MOVA(l);       
3560     lbl = newiTempLabel(NULL);
3561     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3562     pic16_emitcode("cpl","a");   
3563     pic16_emitcode("inc","a");
3564     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3565     pic16_emitcode("mov","b,a");
3566
3567     /* sign adjust left side */
3568     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3569     MOVA(l);
3570
3571     lbl = newiTempLabel(NULL);
3572     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3573     pic16_emitcode("cpl","a");
3574     pic16_emitcode("inc","a");
3575     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3576
3577     /* now the division */
3578     pic16_emitcode("div","ab");
3579     /* we are interested in the lower order
3580     only */
3581     pic16_emitcode("mov","b,a");
3582     lbl = newiTempLabel(NULL);
3583     pic16_emitcode("pop","acc");   
3584     /* if there was an over flow we don't 
3585     adjust the sign of the result */
3586     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3587     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3588     CLRC;
3589     pic16_emitcode("clr","a");
3590     pic16_emitcode("subb","a,b");
3591     pic16_emitcode("mov","b,a");
3592     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3593
3594     /* now we are done */
3595     pic16_aopPut(AOP(result),"b",0);
3596     if(size > 0){
3597         pic16_emitcode("mov","c,b.7");
3598         pic16_emitcode("subb","a,acc");   
3599     }
3600     while (size--)
3601         pic16_aopPut(AOP(result),"a",offset++);
3602
3603 }
3604
3605 /*-----------------------------------------------------------------*/
3606 /* genDiv - generates code for division                            */
3607 /*-----------------------------------------------------------------*/
3608 static void genDiv (iCode *ic)
3609 {
3610     operand *left = IC_LEFT(ic);
3611     operand *right = IC_RIGHT(ic);
3612     operand *result= IC_RESULT(ic);   
3613
3614     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3615     /* assign the amsops */
3616     pic16_aopOp (left,ic,FALSE);
3617     pic16_aopOp (right,ic,FALSE);
3618     pic16_aopOp (result,ic,TRUE);
3619
3620     /* special cases first */
3621     /* both are bits */
3622     if (AOP_TYPE(left) == AOP_CRY &&
3623         AOP_TYPE(right)== AOP_CRY) {
3624         genDivbits(left,right,result);
3625         goto release ;
3626     }
3627
3628     /* if both are of size == 1 */
3629     if (AOP_SIZE(left) == 1 &&
3630         AOP_SIZE(right) == 1 ) {
3631         genDivOneByte(left,right,result);
3632         goto release ;
3633     }
3634
3635     /* should have been converted to function call */
3636     assert(0);
3637 release :
3638     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3639     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3640     pic16_freeAsmop(result,NULL,ic,TRUE); 
3641 }
3642
3643 /*-----------------------------------------------------------------*/
3644 /* genModbits :- modulus of bits                                   */
3645 /*-----------------------------------------------------------------*/
3646 static void genModbits (operand *left, 
3647                         operand *right, 
3648                         operand *result)
3649 {
3650
3651     char *l;
3652
3653     /* the result must be bit */    
3654     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3655     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3656
3657     MOVA(l);       
3658
3659     pic16_emitcode("div","ab");
3660     pic16_emitcode("mov","a,b");
3661     pic16_emitcode("rrc","a");
3662     pic16_aopPut(AOP(result),"c",0);
3663 }
3664
3665 /*-----------------------------------------------------------------*/
3666 /* genModOneByte : 8 bit modulus                                   */
3667 /*-----------------------------------------------------------------*/
3668 static void genModOneByte (operand *left,
3669                            operand *right,
3670                            operand *result)
3671 {
3672     sym_link *opetype = operandType(result);
3673     char *l ;
3674     symbol *lbl ;
3675
3676     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3677     /* signed or unsigned */
3678     if (SPEC_USIGN(opetype)) {
3679         /* unsigned is easy */
3680         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3681         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3682         MOVA(l);    
3683         pic16_emitcode("div","ab");
3684         pic16_aopPut(AOP(result),"b",0);
3685         return ;
3686     }
3687
3688     /* signed is a little bit more difficult */
3689
3690     /* save the signs of the operands */
3691     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3692     MOVA(l);
3693
3694     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3695     pic16_emitcode("push","acc"); /* save it on the stack */
3696
3697     /* now sign adjust for both left & right */
3698     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3699     MOVA(l);
3700
3701     lbl = newiTempLabel(NULL);
3702     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3703     pic16_emitcode("cpl","a");   
3704     pic16_emitcode("inc","a");
3705     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3706     pic16_emitcode("mov","b,a"); 
3707
3708     /* sign adjust left side */
3709     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3710     MOVA(l);
3711
3712     lbl = newiTempLabel(NULL);
3713     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3714     pic16_emitcode("cpl","a");   
3715     pic16_emitcode("inc","a");
3716     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3717
3718     /* now the multiplication */
3719     pic16_emitcode("div","ab");
3720     /* we are interested in the lower order
3721     only */
3722     lbl = newiTempLabel(NULL);
3723     pic16_emitcode("pop","acc");   
3724     /* if there was an over flow we don't 
3725     adjust the sign of the result */
3726     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3727     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3728     CLRC ;
3729     pic16_emitcode("clr","a");
3730     pic16_emitcode("subb","a,b");
3731     pic16_emitcode("mov","b,a");
3732     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3733
3734     /* now we are done */
3735     pic16_aopPut(AOP(result),"b",0);
3736
3737 }
3738
3739 /*-----------------------------------------------------------------*/
3740 /* genMod - generates code for division                            */
3741 /*-----------------------------------------------------------------*/
3742 static void genMod (iCode *ic)
3743 {
3744     operand *left = IC_LEFT(ic);
3745     operand *right = IC_RIGHT(ic);
3746     operand *result= IC_RESULT(ic);  
3747
3748     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3749     /* assign the amsops */
3750     pic16_aopOp (left,ic,FALSE);
3751     pic16_aopOp (right,ic,FALSE);
3752     pic16_aopOp (result,ic,TRUE);
3753
3754     /* special cases first */
3755     /* both are bits */
3756     if (AOP_TYPE(left) == AOP_CRY &&
3757         AOP_TYPE(right)== AOP_CRY) {
3758         genModbits(left,right,result);
3759         goto release ;
3760     }
3761
3762     /* if both are of size == 1 */
3763     if (AOP_SIZE(left) == 1 &&
3764         AOP_SIZE(right) == 1 ) {
3765         genModOneByte(left,right,result);
3766         goto release ;
3767     }
3768
3769     /* should have been converted to function call */
3770     assert(0);
3771
3772 release :
3773     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3774     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3775     pic16_freeAsmop(result,NULL,ic,TRUE); 
3776 }
3777
3778 /*-----------------------------------------------------------------*/
3779 /* genIfxJump :- will create a jump depending on the ifx           */
3780 /*-----------------------------------------------------------------*/
3781 /*
3782   note: May need to add parameter to indicate when a variable is in bit space.
3783 */
3784 static void genIfxJump (iCode *ic, char *jval)
3785 {
3786
3787     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3788     /* if true label then we jump if condition
3789     supplied is true */
3790     if ( IC_TRUE(ic) ) {
3791
3792         if(strcmp(jval,"a") == 0)
3793           emitSKPZ;
3794         else if (strcmp(jval,"c") == 0)
3795           emitSKPC;
3796         else {
3797           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3798           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
3799         }
3800
3801         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
3802         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3803
3804     }
3805     else {
3806         /* false label is present */
3807         if(strcmp(jval,"a") == 0)
3808           emitSKPNZ;
3809         else if (strcmp(jval,"c") == 0)
3810           emitSKPNC;
3811         else {
3812           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3813           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
3814         }
3815
3816         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
3817         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3818
3819     }
3820
3821
3822     /* mark the icode as generated */
3823     ic->generated = 1;
3824 }
3825
3826 /*-----------------------------------------------------------------*/
3827 /* genSkip                                                         */
3828 /*-----------------------------------------------------------------*/
3829 static void genSkip(iCode *ifx,int status_bit)
3830 {
3831   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3832   if(!ifx)
3833     return;
3834
3835   if ( IC_TRUE(ifx) ) {
3836     switch(status_bit) {
3837     case 'z':
3838       emitSKPNZ;
3839       break;
3840
3841     case 'c':
3842       emitSKPNC;
3843       break;
3844
3845     case 'd':
3846       emitSKPDC;
3847       break;
3848
3849     }
3850
3851     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3852     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3853
3854   } else {
3855
3856     switch(status_bit) {
3857
3858     case 'z':
3859       emitSKPZ;
3860       break;
3861
3862     case 'c':
3863       emitSKPC;
3864       break;
3865
3866     case 'd':
3867       emitSKPDC;
3868       break;
3869     }
3870     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3871     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3872
3873   }
3874
3875 }
3876
3877 /*-----------------------------------------------------------------*/
3878 /* genSkipc                                                        */
3879 /*-----------------------------------------------------------------*/
3880 static void genSkipc(resolvedIfx *rifx)
3881 {
3882   if(!rifx)
3883     return;
3884
3885   if(rifx->condition)
3886     emitSKPC;
3887   else
3888     emitSKPNC;
3889
3890   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3891   rifx->generated = 1;
3892 }
3893
3894 /*-----------------------------------------------------------------*/
3895 /* genSkipz2                                                       */
3896 /*-----------------------------------------------------------------*/
3897 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3898 {
3899   if(!rifx)
3900     return;
3901
3902   if( (rifx->condition ^ invert_condition) & 1)
3903     emitSKPZ;
3904   else
3905     emitSKPNZ;
3906
3907   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3908   rifx->generated = 1;
3909 }
3910
3911 #if 0
3912 /*-----------------------------------------------------------------*/
3913 /* genSkipz                                                        */
3914 /*-----------------------------------------------------------------*/
3915 static void genSkipz(iCode *ifx, int condition)
3916 {
3917   if(!ifx)
3918     return;
3919
3920   if(condition)
3921     emitSKPNZ;
3922   else
3923     emitSKPZ;
3924
3925   if ( IC_TRUE(ifx) )
3926     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3927   else
3928     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3929
3930   if ( IC_TRUE(ifx) )
3931     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3932   else
3933     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3934
3935 }
3936 #endif
3937
3938 /*-----------------------------------------------------------------*/
3939 /* genSkipCond                                                     */
3940 /*-----------------------------------------------------------------*/
3941 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3942 {
3943   if(!rifx)
3944     return;
3945
3946   if(rifx->condition)
3947     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3948   else
3949     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3950
3951
3952   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3953   rifx->generated = 1;
3954 }
3955
3956 #if 0
3957 /*-----------------------------------------------------------------*/
3958 /* genChkZeroes :- greater or less than comparison                 */
3959 /*     For each byte in a literal that is zero, inclusive or the   */
3960 /*     the corresponding byte in the operand with W                */
3961 /*     returns true if any of the bytes are zero                   */
3962 /*-----------------------------------------------------------------*/
3963 static int genChkZeroes(operand *op, int lit,  int size)
3964 {
3965
3966   int i;
3967   int flag =1;
3968
3969   while(size--) {
3970     i = (lit >> (size*8)) & 0xff;
3971
3972     if(i==0) {
3973       if(flag) 
3974         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
3975       else
3976         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
3977       flag = 0;
3978     }
3979   }
3980
3981   return (flag==0);
3982 }
3983 #endif
3984
3985 /*-----------------------------------------------------------------*/
3986 /* genCmp :- greater or less than comparison                       */
3987 /*-----------------------------------------------------------------*/
3988 static void genCmp (operand *left,operand *right,
3989                     operand *result, iCode *ifx, int sign)
3990 {
3991   int size; //, offset = 0 ;
3992   unsigned long lit = 0L,i = 0;
3993   resolvedIfx rFalseIfx;
3994   //  resolvedIfx rTrueIfx;
3995   symbol *truelbl;
3996   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3997 /*
3998   if(ifx) {
3999     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4000     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4001   }
4002 */
4003
4004   resolveIfx(&rFalseIfx,ifx);
4005   truelbl  = newiTempLabel(NULL);
4006   size = max(AOP_SIZE(left),AOP_SIZE(right));
4007
4008   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4009
4010 #define _swapp
4011
4012   /* if literal is on the right then swap with left */
4013   if ((AOP_TYPE(right) == AOP_LIT)) {
4014     operand *tmp = right ;
4015     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4016     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4017 #ifdef _swapp
4018
4019     lit = (lit - 1) & mask;
4020     right = left;
4021     left = tmp;
4022     rFalseIfx.condition ^= 1;
4023 #endif
4024
4025   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4026     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4027   }
4028
4029
4030   //if(IC_TRUE(ifx) == NULL)
4031   /* if left & right are bit variables */
4032   if (AOP_TYPE(left) == AOP_CRY &&
4033       AOP_TYPE(right) == AOP_CRY ) {
4034     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4035     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4036   } else {
4037     /* subtract right from left if at the
4038        end the carry flag is set then we know that
4039        left is greater than right */
4040
4041     //    {
4042
4043     symbol *lbl  = newiTempLabel(NULL);
4044
4045 #ifndef _swapp
4046     if(AOP_TYPE(right) == AOP_LIT) {
4047
4048       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4049
4050       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4051
4052       /* special cases */
4053
4054       if(lit == 0) {
4055
4056         if(sign != 0) 
4057           genSkipCond(&rFalseIfx,left,size-1,7);
4058         else 
4059           /* no need to compare to 0...*/
4060           /* NOTE: this is a de-generate compare that most certainly 
4061            *       creates some dead code. */
4062           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4063
4064         if(ifx) ifx->generated = 1;
4065         return;
4066
4067       }
4068       size--;
4069
4070       if(size == 0) {
4071         //i = (lit >> (size*8)) & 0xff;
4072         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4073         
4074         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4075
4076         i = ((0-lit) & 0xff);
4077         if(sign) {
4078           if( i == 0x81) { 
4079             /* lit is 0x7f, all signed chars are less than
4080              * this except for 0x7f itself */
4081             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4082             genSkipz2(&rFalseIfx,0);
4083           } else {
4084             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4085             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4086             genSkipc(&rFalseIfx);
4087           }
4088
4089         } else {
4090           if(lit == 1) {
4091             genSkipz2(&rFalseIfx,1);
4092           } else {
4093             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4094             genSkipc(&rFalseIfx);
4095           }
4096         }
4097
4098         if(ifx) ifx->generated = 1;
4099         return;
4100       }
4101
4102       /* chars are out of the way. now do ints and longs */
4103
4104
4105       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4106         
4107       /* special cases */
4108
4109       if(sign) {
4110
4111         if(lit == 0) {
4112           genSkipCond(&rFalseIfx,left,size,7);
4113           if(ifx) ifx->generated = 1;
4114           return;
4115         }
4116
4117         if(lit <0x100) {
4118           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4119
4120           //rFalseIfx.condition ^= 1;
4121           //genSkipCond(&rFalseIfx,left,size,7);
4122           //rFalseIfx.condition ^= 1;
4123
4124           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4125           if(rFalseIfx.condition)
4126             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4127           else
4128             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4129
4130           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4131           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4132           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4133
4134           while(size > 1)
4135             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4136
4137           if(rFalseIfx.condition) {
4138             emitSKPZ;
4139             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4140
4141           } else {
4142             emitSKPNZ;
4143           }
4144
4145           genSkipc(&rFalseIfx);
4146           pic16_emitpLabel(truelbl->key);
4147           if(ifx) ifx->generated = 1;
4148           return;
4149
4150         }
4151
4152         if(size == 1) {
4153
4154           if( (lit & 0xff) == 0) {
4155             /* lower byte is zero */
4156             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4157             i = ((lit >> 8) & 0xff) ^0x80;
4158             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4159             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4160             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4161             genSkipc(&rFalseIfx);
4162
4163
4164             if(ifx) ifx->generated = 1;
4165             return;
4166
4167           }
4168         } else {
4169           /* Special cases for signed longs */
4170           if( (lit & 0xffffff) == 0) {
4171             /* lower byte is zero */
4172             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4173             i = ((lit >> 8*3) & 0xff) ^0x80;
4174             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4175             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4176             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4177             genSkipc(&rFalseIfx);
4178
4179
4180             if(ifx) ifx->generated = 1;
4181             return;
4182
4183           }
4184
4185         }
4186
4187
4188         if(lit & (0x80 << (size*8))) {
4189           /* lit is negative */
4190           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4191
4192           //genSkipCond(&rFalseIfx,left,size,7);
4193
4194           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4195
4196           if(rFalseIfx.condition)
4197             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4198           else
4199             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4200
4201
4202         } else {
4203           /* lit is positive */
4204           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4205           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4206           if(rFalseIfx.condition)
4207             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4208           else
4209             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4210
4211         }
4212
4213         /*
4214           This works, but is only good for ints.
4215           It also requires a "known zero" register.
4216           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4217           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4218           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4219           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4220           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4221           genSkipc(&rFalseIfx);
4222
4223           pic16_emitpLabel(truelbl->key);
4224           if(ifx) ifx->generated = 1;
4225           return;
4226         **/
4227           
4228         /* There are no more special cases, so perform a general compare */
4229   
4230         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4231         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4232
4233         while(size--) {
4234
4235           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4236           emitSKPNZ;
4237           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4238         }
4239         //rFalseIfx.condition ^= 1;
4240         genSkipc(&rFalseIfx);
4241
4242         pic16_emitpLabel(truelbl->key);
4243
4244         if(ifx) ifx->generated = 1;
4245         return;
4246
4247
4248       }
4249
4250
4251       /* sign is out of the way. So now do an unsigned compare */
4252       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4253
4254
4255       /* General case - compare to an unsigned literal on the right.*/
4256
4257       i = (lit >> (size*8)) & 0xff;
4258       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4259       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4260       while(size--) {
4261         i = (lit >> (size*8)) & 0xff;
4262
4263         if(i) {
4264           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4265           emitSKPNZ;
4266           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4267         } else {
4268           /* this byte of the lit is zero, 
4269            *if it's not the last then OR in the variable */
4270           if(size)
4271             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4272         }
4273       }
4274
4275
4276       pic16_emitpLabel(lbl->key);
4277       //if(emitFinalCheck)
4278       genSkipc(&rFalseIfx);
4279       if(sign)
4280         pic16_emitpLabel(truelbl->key);
4281
4282       if(ifx) ifx->generated = 1;
4283       return;
4284
4285
4286     }
4287 #endif  // _swapp
4288
4289     if(AOP_TYPE(left) == AOP_LIT) {
4290       //symbol *lbl = newiTempLabel(NULL);
4291
4292       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4293
4294
4295       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4296
4297       /* Special cases */
4298       if((lit == 0) && (sign == 0)){
4299
4300         size--;
4301         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4302         while(size) 
4303           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4304
4305         genSkipz2(&rFalseIfx,0);
4306         if(ifx) ifx->generated = 1;
4307         return;
4308       }
4309
4310       if(size==1) {
4311         /* Special cases */
4312         lit &= 0xff;
4313         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4314           /* degenerate compare can never be true */
4315           if(rFalseIfx.condition == 0)
4316             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4317
4318           if(ifx) ifx->generated = 1;
4319           return;
4320         }
4321
4322         if(sign) {
4323           /* signed comparisons to a literal byte */
4324
4325           int lp1 = (lit+1) & 0xff;
4326
4327           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4328           switch (lp1) {
4329           case 0:
4330             rFalseIfx.condition ^= 1;
4331             genSkipCond(&rFalseIfx,right,0,7);
4332             break;
4333           case 0x7f:
4334             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4335             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4336             genSkipz2(&rFalseIfx,1);
4337             break;
4338           default:
4339             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4340             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4341             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4342             rFalseIfx.condition ^= 1;
4343             genSkipc(&rFalseIfx);
4344             break;
4345           }
4346         } else {
4347           /* unsigned comparisons to a literal byte */
4348
4349           switch(lit & 0xff ) {
4350           case 0:
4351             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4352             genSkipz2(&rFalseIfx,0);
4353             break;
4354           case 0x7f:
4355             rFalseIfx.condition ^= 1;
4356             genSkipCond(&rFalseIfx,right,0,7);
4357             break;
4358
4359           default:
4360             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4361             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4362             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4363             rFalseIfx.condition ^= 1;
4364             if (AOP_TYPE(result) == AOP_CRY)
4365               genSkipc(&rFalseIfx);
4366             else {
4367               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4368               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4369             }         
4370             break;
4371           }
4372         }
4373
4374         if(ifx) ifx->generated = 1;
4375         //goto check_carry;
4376         return;
4377
4378       } else {
4379
4380         /* Size is greater than 1 */
4381
4382         if(sign) {
4383           int lp1 = lit+1;
4384
4385           size--;
4386
4387           if(lp1 == 0) {
4388             /* this means lit = 0xffffffff, or -1 */
4389
4390
4391             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4392             rFalseIfx.condition ^= 1;
4393             genSkipCond(&rFalseIfx,right,size,7);
4394             if(ifx) ifx->generated = 1;
4395             return;
4396           }
4397
4398           if(lit == 0) {
4399             int s = size;
4400
4401             if(rFalseIfx.condition) {
4402               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4403               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4404             }
4405
4406             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4407             while(size--)
4408               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4409
4410
4411             emitSKPZ;
4412             if(rFalseIfx.condition) {
4413               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4414               pic16_emitpLabel(truelbl->key);
4415             }else {
4416               rFalseIfx.condition ^= 1;
4417               genSkipCond(&rFalseIfx,right,s,7);
4418             }
4419
4420             if(ifx) ifx->generated = 1;
4421             return;
4422           }
4423
4424           if((size == 1) &&  (0 == (lp1&0xff))) {
4425             /* lower byte of signed word is zero */
4426             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4427             i = ((lp1 >> 8) & 0xff) ^0x80;
4428             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4429             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4430             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4431             rFalseIfx.condition ^= 1;
4432             genSkipc(&rFalseIfx);
4433
4434
4435             if(ifx) ifx->generated = 1;
4436             return;
4437           }
4438
4439           if(lit & (0x80 << (size*8))) {
4440             /* Lit is less than zero */
4441             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4442             //rFalseIfx.condition ^= 1;
4443             //genSkipCond(&rFalseIfx,left,size,7);
4444             //rFalseIfx.condition ^= 1;
4445             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4446             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4447
4448             if(rFalseIfx.condition)
4449               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4450             else
4451               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4452
4453
4454           } else {
4455             /* Lit is greater than or equal to zero */
4456             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4457             //rFalseIfx.condition ^= 1;
4458             //genSkipCond(&rFalseIfx,right,size,7);
4459             //rFalseIfx.condition ^= 1;
4460
4461             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4462             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4463
4464             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4465             if(rFalseIfx.condition)
4466               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4467             else
4468               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4469
4470           }
4471
4472
4473           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4474           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4475
4476           while(size--) {
4477
4478             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4479             emitSKPNZ;
4480             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4481           }
4482           rFalseIfx.condition ^= 1;
4483           //rFalseIfx.condition = 1;
4484           genSkipc(&rFalseIfx);
4485
4486           pic16_emitpLabel(truelbl->key);
4487
4488           if(ifx) ifx->generated = 1;
4489           return;
4490           // end of if (sign)
4491         } else {
4492
4493           /* compare word or long to an unsigned literal on the right.*/
4494
4495
4496           size--;
4497           if(lit < 0xff) {
4498             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4499             switch (lit) {
4500             case 0:
4501               break; /* handled above */
4502 /*
4503             case 0xff:
4504               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4505               while(size--)
4506                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4507               genSkipz2(&rFalseIfx,0);
4508               break;
4509 */
4510             default:
4511               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4512               while(--size)
4513                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4514
4515               emitSKPZ;
4516               if(rFalseIfx.condition)
4517                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4518               else
4519                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4520
4521
4522               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4523               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4524
4525               rFalseIfx.condition ^= 1;
4526               genSkipc(&rFalseIfx);
4527             }
4528
4529             pic16_emitpLabel(truelbl->key);
4530
4531             if(ifx) ifx->generated = 1;
4532             return;
4533           }
4534
4535
4536           lit++;
4537           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4538           i = (lit >> (size*8)) & 0xff;
4539
4540           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4541           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4542
4543           while(size--) {
4544             i = (lit >> (size*8)) & 0xff;
4545
4546             if(i) {
4547               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4548               emitSKPNZ;
4549               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4550             } else {
4551               /* this byte of the lit is zero, 
4552                *if it's not the last then OR in the variable */
4553               if(size)
4554                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4555             }
4556           }
4557
4558
4559           pic16_emitpLabel(lbl->key);
4560
4561           rFalseIfx.condition ^= 1;
4562           genSkipc(&rFalseIfx);
4563         }
4564
4565         if(sign)
4566           pic16_emitpLabel(truelbl->key);
4567         if(ifx) ifx->generated = 1;
4568         return;
4569       }
4570     }
4571     /* Compare two variables */
4572
4573     DEBUGpic16_emitcode(";sign","%d",sign);
4574
4575     size--;
4576     if(sign) {
4577       /* Sigh. thus sucks... */
4578       if(size) {
4579         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4580         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4581         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4582         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4583         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4584         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4585       } else {
4586         /* Signed char comparison */
4587         /* Special thanks to Nikolai Golovchenko for this snippet */
4588         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4589         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4590         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
4591         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4592         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4593         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4594
4595         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4596         genSkipc(&rFalseIfx);
4597           
4598         if(ifx) ifx->generated = 1;
4599         return;
4600       }
4601
4602     } else {
4603
4604       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4605       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4606     }
4607
4608
4609     /* The rest of the bytes of a multi-byte compare */
4610     while (size) {
4611
4612       emitSKPZ;
4613       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
4614       size--;
4615
4616       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4617       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4618
4619
4620     }
4621
4622     pic16_emitpLabel(lbl->key);
4623
4624     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4625     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4626         (AOP_TYPE(result) == AOP_REG)) {
4627       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4628       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4629     } else {
4630       genSkipc(&rFalseIfx);
4631     }         
4632     //genSkipc(&rFalseIfx);
4633     if(ifx) ifx->generated = 1;
4634
4635     return;
4636
4637   }
4638
4639   // check_carry:
4640   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4641     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4642     pic16_outBitC(result);
4643   } else {
4644     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4645     /* if the result is used in the next
4646        ifx conditional branch then generate
4647        code a little differently */
4648     if (ifx )
4649       genIfxJump (ifx,"c");
4650     else
4651       pic16_outBitC(result);
4652     /* leave the result in acc */
4653   }
4654
4655 }
4656
4657 /*-----------------------------------------------------------------*/
4658 /* genCmpGt :- greater than comparison                             */
4659 /*-----------------------------------------------------------------*/
4660 static void genCmpGt (iCode *ic, iCode *ifx)
4661 {
4662     operand *left, *right, *result;
4663     sym_link *letype , *retype;
4664     int sign ;
4665
4666     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4667     left = IC_LEFT(ic);
4668     right= IC_RIGHT(ic);
4669     result = IC_RESULT(ic);
4670
4671     letype = getSpec(operandType(left));
4672     retype =getSpec(operandType(right));
4673     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4674     /* assign the amsops */
4675     pic16_aopOp (left,ic,FALSE);
4676     pic16_aopOp (right,ic,FALSE);
4677     pic16_aopOp (result,ic,TRUE);
4678
4679     genCmp(right, left, result, ifx, sign);
4680
4681     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4682     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4683     pic16_freeAsmop(result,NULL,ic,TRUE); 
4684 }
4685
4686 /*-----------------------------------------------------------------*/
4687 /* genCmpLt - less than comparisons                                */
4688 /*-----------------------------------------------------------------*/
4689 static void genCmpLt (iCode *ic, iCode *ifx)
4690 {
4691     operand *left, *right, *result;
4692     sym_link *letype , *retype;
4693     int sign ;
4694
4695     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4696     left = IC_LEFT(ic);
4697     right= IC_RIGHT(ic);
4698     result = IC_RESULT(ic);
4699
4700     letype = getSpec(operandType(left));
4701     retype =getSpec(operandType(right));
4702     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4703
4704     /* assign the amsops */
4705     pic16_aopOp (left,ic,FALSE);
4706     pic16_aopOp (right,ic,FALSE);
4707     pic16_aopOp (result,ic,TRUE);
4708
4709     genCmp(left, right, result, ifx, sign);
4710
4711     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4712     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4713     pic16_freeAsmop(result,NULL,ic,TRUE); 
4714 }
4715
4716 /*-----------------------------------------------------------------*/
4717 /* genc16bit2lit - compare a 16 bit value to a literal             */
4718 /*-----------------------------------------------------------------*/
4719 static void genc16bit2lit(operand *op, int lit, int offset)
4720 {
4721   int i;
4722
4723   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4724   if( (lit&0xff) == 0) 
4725     i=1;
4726   else
4727     i=0;
4728
4729   switch( BYTEofLONG(lit,i)) { 
4730   case 0:
4731     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4732     break;
4733   case 1:
4734     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4735     break;
4736   case 0xff:
4737     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4738     break;
4739   default:
4740     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4741     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4742   }
4743
4744   i ^= 1;
4745
4746   switch( BYTEofLONG(lit,i)) { 
4747   case 0:
4748     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
4749     break;
4750   case 1:
4751     emitSKPNZ;
4752     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4753     break;
4754   case 0xff:
4755     emitSKPNZ;
4756     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4757     break;
4758   default:
4759     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4760     emitSKPNZ;
4761     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
4762
4763   }
4764
4765 }
4766
4767 /*-----------------------------------------------------------------*/
4768 /* gencjneshort - compare and jump if not equal                    */
4769 /*-----------------------------------------------------------------*/
4770 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4771 {
4772   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4773   int offset = 0;
4774   int res_offset = 0;  /* the result may be a different size then left or right */
4775   int res_size = AOP_SIZE(result);
4776   resolvedIfx rIfx;
4777   symbol *lbl;
4778
4779   unsigned long lit = 0L;
4780   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4781   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4782   if(result)
4783     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4784   resolveIfx(&rIfx,ifx);
4785   lbl =  newiTempLabel(NULL);
4786
4787
4788   /* if the left side is a literal or 
4789      if the right is in a pointer register and left 
4790      is not */
4791   if ((AOP_TYPE(left) == AOP_LIT) || 
4792       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4793     operand *t = right;
4794     right = left;
4795     left = t;
4796   }
4797   if(AOP_TYPE(right) == AOP_LIT)
4798     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4799
4800   /* if the right side is a literal then anything goes */
4801   if (AOP_TYPE(right) == AOP_LIT &&
4802       AOP_TYPE(left) != AOP_DIR ) {
4803     switch(size) {
4804     case 2:
4805       genc16bit2lit(left, lit, 0);
4806       emitSKPNZ;
4807       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4808       break;
4809     default:
4810       while (size--) {
4811         if(lit & 0xff) {
4812           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4813           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4814         } else {
4815           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4816         }
4817
4818         emitSKPNZ;
4819         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4820         offset++;
4821         if(res_offset < res_size-1)
4822           res_offset++;
4823         lit >>= 8;
4824       }
4825       break;
4826     }
4827   }
4828
4829   /* if the right side is in a register or in direct space or
4830      if the left is a pointer register & right is not */    
4831   else if (AOP_TYPE(right) == AOP_REG ||
4832            AOP_TYPE(right) == AOP_DIR || 
4833            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4834            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4835     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4836     int lbl_key = lbl->key;
4837
4838     if(result) {
4839       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
4840       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4841     }else {
4842       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4843       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4844               __FUNCTION__,__LINE__);
4845       return;
4846     }
4847
4848 /*     switch(size) { */
4849 /*     case 2: */
4850 /*       genc16bit2lit(left, lit, 0); */
4851 /*       emitSKPNZ; */
4852 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
4853 /*       break; */
4854 /*     default: */
4855     while (size--) {
4856       int emit_skip=1;
4857       if((AOP_TYPE(left) == AOP_DIR) && 
4858          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4859
4860         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4861         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4862
4863       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4864             
4865         switch (lit & 0xff) {
4866         case 0:
4867           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4868           break;
4869         case 1:
4870           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4871           pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4872           //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4873           emit_skip=0;
4874           break;
4875         case 0xff:
4876           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4877           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4878           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4879           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4880           emit_skip=0;
4881           break;
4882         default:
4883           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4884           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4885         }
4886         lit >>= 8;
4887
4888       } else {
4889         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4890       }
4891       if(emit_skip) {
4892         if(AOP_TYPE(result) == AOP_CRY) {
4893           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4894           if(rIfx.condition)
4895             emitSKPNZ;
4896           else
4897             emitSKPZ;
4898           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4899         } else {
4900           /* fix me. probably need to check result size too */
4901           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
4902           if(rIfx.condition)
4903             emitSKPZ;
4904           else
4905             emitSKPNZ;
4906           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4907           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4908         }
4909         if(ifx)
4910           ifx->generated=1;
4911       }
4912       emit_skip++;
4913       offset++;
4914       if(res_offset < res_size-1)
4915         res_offset++;
4916     }
4917 /*       break; */
4918 /*     } */
4919   } else if(AOP_TYPE(right) == AOP_REG &&
4920             AOP_TYPE(left) != AOP_DIR){
4921
4922     while(size--) {
4923       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4924       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4925       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4926       if(rIfx.condition)
4927         emitSKPNZ;
4928       else
4929         emitSKPZ;
4930       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4931       offset++;
4932       if(res_offset < res_size-1)
4933         res_offset++;
4934     }
4935       
4936   }else{
4937     /* right is a pointer reg need both a & b */
4938     while(size--) {
4939       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
4940       if(strcmp(l,"b"))
4941         pic16_emitcode("mov","b,%s",l);
4942       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
4943       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4944       offset++;
4945     }
4946   }
4947
4948   pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4949   if(!rIfx.condition)
4950     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4951
4952   pic16_emitpLabel(lbl->key);
4953
4954   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4955
4956   if(ifx)
4957     ifx->generated = 1;
4958 }
4959
4960 #if 0
4961 /*-----------------------------------------------------------------*/
4962 /* gencjne - compare and jump if not equal                         */
4963 /*-----------------------------------------------------------------*/
4964 static void gencjne(operand *left, operand *right, iCode *ifx)
4965 {
4966     symbol *tlbl  = newiTempLabel(NULL);
4967
4968     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4969     gencjneshort(left, right, lbl);
4970
4971     pic16_emitcode("mov","a,%s",one);
4972     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4973     pic16_emitcode("","%05d_DS_:",lbl->key+100);
4974     pic16_emitcode("clr","a");
4975     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
4976
4977     pic16_emitpLabel(lbl->key);
4978     pic16_emitpLabel(tlbl->key);
4979
4980 }
4981 #endif
4982
4983 /*-----------------------------------------------------------------*/
4984 /* genCmpEq - generates code for equal to                          */
4985 /*-----------------------------------------------------------------*/
4986 static void genCmpEq (iCode *ic, iCode *ifx)
4987 {
4988     operand *left, *right, *result;
4989     unsigned long lit = 0L;
4990     int size,offset=0;
4991     symbol *falselbl  = newiTempLabel(NULL);
4992
4993
4994     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4995
4996     if(ifx)
4997       DEBUGpic16_emitcode ("; ifx is non-null","");
4998     else
4999       DEBUGpic16_emitcode ("; ifx is null","");
5000
5001     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5002     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5003     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5004
5005     size = max(AOP_SIZE(left),AOP_SIZE(right));
5006
5007     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5008
5009     /* if literal, literal on the right or 
5010     if the right is in a pointer register and left 
5011     is not */
5012     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5013         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5014       operand *tmp = right ;
5015       right = left;
5016       left = tmp;
5017     }
5018
5019
5020     if(ifx && !AOP_SIZE(result)){
5021         symbol *tlbl;
5022         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5023         /* if they are both bit variables */
5024         if (AOP_TYPE(left) == AOP_CRY &&
5025             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5026                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5027             if(AOP_TYPE(right) == AOP_LIT){
5028                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5029                 if(lit == 0L){
5030                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5031                     pic16_emitcode("cpl","c");
5032                 } else if(lit == 1L) {
5033                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5034                 } else {
5035                     pic16_emitcode("clr","c");
5036                 }
5037                 /* AOP_TYPE(right) == AOP_CRY */
5038             } else {
5039                 symbol *lbl = newiTempLabel(NULL);
5040                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5041                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5042                 pic16_emitcode("cpl","c");
5043                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5044             }
5045             /* if true label then we jump if condition
5046             supplied is true */
5047             tlbl = newiTempLabel(NULL);
5048             if ( IC_TRUE(ifx) ) {
5049                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5050                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5051             } else {
5052                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5053                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5054             }
5055             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5056
5057                 {
5058                 /* left and right are both bit variables, result is carry */
5059                         resolvedIfx rIfx;
5060               
5061                         resolveIfx(&rIfx,ifx);
5062
5063                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5064                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5065                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5066                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5067                         genSkipz2(&rIfx,0);
5068                 }
5069         } else {
5070
5071                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5072
5073                         /* They're not both bit variables. Is the right a literal? */
5074                         if(AOP_TYPE(right) == AOP_LIT) {
5075                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5076             
5077                         switch(size) {
5078
5079                                 case 1:
5080                                         switch(lit & 0xff) {
5081                                                 case 1:
5082                                                                 if ( IC_TRUE(ifx) ) {
5083                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5084                                                                         emitSKPNZ;
5085                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5086                                                                 } else {
5087                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5088                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5089                                                                 }
5090                                                                 break;
5091                                                 case 0xff:
5092                                                                 if ( IC_TRUE(ifx) ) {
5093                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5094                                                                         emitSKPNZ;
5095                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5096                                                                 } else {
5097                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5098                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5099                                                                 }
5100                                                                 break;
5101                                                 default:
5102                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5103                                                                 if(lit)
5104                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5105                                                                 genSkip(ifx,'z');
5106                                         } // switch lit
5107
5108
5109                                         /* end of size == 1 */
5110                                         break;
5111               
5112                                 case 2:
5113                                         genc16bit2lit(left,lit,offset);
5114                                         genSkip(ifx,'z');
5115                                         break;
5116                                         /* end of size == 2 */
5117
5118                                 default:
5119                                         /* size is 4 */
5120                                         if(lit==0) {
5121                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5122                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5123                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5124                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5125                                                 genSkip(ifx,'z');
5126                                         } else {
5127                                                 /* search for patterns that can be optimized */
5128
5129                                                 genc16bit2lit(left,lit,0);
5130                                                 lit >>= 16;
5131                                                 if(lit) {
5132                                                                 if(IC_TRUE(ifx))
5133                                                                 emitSKPZ; // if hi word unequal
5134                                                                 else
5135                                                                 emitSKPNZ; // if hi word equal
5136                                                                 // fail early
5137                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5138                                                         genc16bit2lit(left,lit,2);
5139                                                         genSkip(ifx,'z');
5140                                                 } else {
5141                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5142                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5143                                                         genSkip(ifx,'z');
5144                                                 }
5145                                         }
5146                                                 pic16_emitpLabel(falselbl->key);
5147                                                 break;
5148
5149                         } // switch size
5150           
5151                         ifx->generated = 1;
5152                         goto release ;
5153             
5154
5155           } else if(AOP_TYPE(right) == AOP_CRY ) {
5156             /* we know the left is not a bit, but that the right is */
5157             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5158             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5159                       pic16_popGet(AOP(right),offset));
5160             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5161
5162             /* if the two are equal, then W will be 0 and the Z bit is set
5163              * we could test Z now, or go ahead and check the high order bytes if
5164              * the variable we're comparing is larger than a byte. */
5165
5166             while(--size)
5167               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5168
5169             if ( IC_TRUE(ifx) ) {
5170               emitSKPNZ;
5171               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5172               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5173             } else {
5174               emitSKPZ;
5175               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5176               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5177             }
5178
5179           } else {
5180             /* They're both variables that are larger than bits */
5181             int s = size;
5182
5183             tlbl = newiTempLabel(NULL);
5184
5185             while(size--) {
5186               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5187               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5188
5189               if ( IC_TRUE(ifx) ) {
5190                 if(size) {
5191                   emitSKPZ;
5192                 
5193                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5194
5195                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5196                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5197                 } else {
5198                   emitSKPNZ;
5199
5200                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5201
5202
5203                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5204                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5205                 }
5206               } else {
5207                 emitSKPZ;
5208
5209                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5210
5211                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5212                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5213               }
5214               offset++;
5215             }
5216             if(s>1 && IC_TRUE(ifx)) {
5217               pic16_emitpLabel(tlbl->key);
5218               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5219             }
5220           }
5221         }
5222         /* mark the icode as generated */
5223         ifx->generated = 1;
5224         goto release ;
5225     }
5226
5227     /* if they are both bit variables */
5228     if (AOP_TYPE(left) == AOP_CRY &&
5229         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5230         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5231         if(AOP_TYPE(right) == AOP_LIT){
5232             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5233             if(lit == 0L){
5234                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5235                 pic16_emitcode("cpl","c");
5236             } else if(lit == 1L) {
5237                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5238             } else {
5239                 pic16_emitcode("clr","c");
5240             }
5241             /* AOP_TYPE(right) == AOP_CRY */
5242         } else {
5243             symbol *lbl = newiTempLabel(NULL);
5244             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5245             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5246             pic16_emitcode("cpl","c");
5247             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5248         }
5249         /* c = 1 if egal */
5250         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5251             pic16_outBitC(result);
5252             goto release ;
5253         }
5254         if (ifx) {
5255             genIfxJump (ifx,"c");
5256             goto release ;
5257         }
5258         /* if the result is used in an arithmetic operation
5259         then put the result in place */
5260         pic16_outBitC(result);
5261     } else {
5262       
5263       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5264       gencjne(left,right,result,ifx);
5265 /*
5266       if(ifx) 
5267         gencjne(left,right,newiTempLabel(NULL));
5268       else {
5269         if(IC_TRUE(ifx)->key)
5270           gencjne(left,right,IC_TRUE(ifx)->key);
5271         else
5272           gencjne(left,right,IC_FALSE(ifx)->key);
5273         ifx->generated = 1;
5274         goto release ;
5275       }
5276       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5277         pic16_aopPut(AOP(result),"a",0);
5278         goto release ;
5279       }
5280
5281       if (ifx) {
5282         genIfxJump (ifx,"a");
5283         goto release ;
5284       }
5285 */
5286       /* if the result is used in an arithmetic operation
5287          then put the result in place */
5288 /*
5289       if (AOP_TYPE(result) != AOP_CRY) 
5290         pic16_outAcc(result);
5291 */
5292       /* leave the result in acc */
5293     }
5294
5295 release:
5296     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5297     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5298     pic16_freeAsmop(result,NULL,ic,TRUE);
5299 }
5300
5301 /*-----------------------------------------------------------------*/
5302 /* ifxForOp - returns the icode containing the ifx for operand     */
5303 /*-----------------------------------------------------------------*/
5304 static iCode *ifxForOp ( operand *op, iCode *ic )
5305 {
5306     /* if true symbol then needs to be assigned */
5307     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5308     if (IS_TRUE_SYMOP(op))
5309         return NULL ;
5310
5311     /* if this has register type condition and
5312     the next instruction is ifx with the same operand
5313     and live to of the operand is upto the ifx only then */
5314     if (ic->next &&
5315         ic->next->op == IFX &&
5316         IC_COND(ic->next)->key == op->key &&
5317         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5318         return ic->next;
5319
5320     if (ic->next &&
5321         ic->next->op == IFX &&
5322         IC_COND(ic->next)->key == op->key) {
5323       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5324       return ic->next;
5325     }
5326
5327     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5328     if (ic->next &&
5329         ic->next->op == IFX)
5330       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5331
5332     if (ic->next &&
5333         ic->next->op == IFX &&
5334         IC_COND(ic->next)->key == op->key) {
5335       DEBUGpic16_emitcode ("; "," key is okay");
5336       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5337                            OP_SYMBOL(op)->liveTo,
5338                            ic->next->seq);
5339     }
5340
5341
5342     return NULL;
5343 }
5344 /*-----------------------------------------------------------------*/
5345 /* genAndOp - for && operation                                     */
5346 /*-----------------------------------------------------------------*/
5347 static void genAndOp (iCode *ic)
5348 {
5349     operand *left,*right, *result;
5350 /*     symbol *tlbl; */
5351
5352     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5353     /* note here that && operations that are in an
5354     if statement are taken away by backPatchLabels
5355     only those used in arthmetic operations remain */
5356     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5357     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5358     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5359
5360     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5361
5362     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5363     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5364     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5365
5366     /* if both are bit variables */
5367 /*     if (AOP_TYPE(left) == AOP_CRY && */
5368 /*         AOP_TYPE(right) == AOP_CRY ) { */
5369 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5370 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5371 /*         pic16_outBitC(result); */
5372 /*     } else { */
5373 /*         tlbl = newiTempLabel(NULL); */
5374 /*         pic16_toBoolean(left);     */
5375 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5376 /*         pic16_toBoolean(right); */
5377 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5378 /*         pic16_outBitAcc(result); */
5379 /*     } */
5380
5381     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5382     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5383     pic16_freeAsmop(result,NULL,ic,TRUE);
5384 }
5385
5386
5387 /*-----------------------------------------------------------------*/
5388 /* genOrOp - for || operation                                      */
5389 /*-----------------------------------------------------------------*/
5390 /*
5391   tsd pic port -
5392   modified this code, but it doesn't appear to ever get called
5393 */
5394
5395 static void genOrOp (iCode *ic)
5396 {
5397     operand *left,*right, *result;
5398     symbol *tlbl;
5399
5400     /* note here that || operations that are in an
5401     if statement are taken away by backPatchLabels
5402     only those used in arthmetic operations remain */
5403     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5404     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5405     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5406     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5407
5408     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5409
5410     /* if both are bit variables */
5411     if (AOP_TYPE(left) == AOP_CRY &&
5412         AOP_TYPE(right) == AOP_CRY ) {
5413       pic16_emitcode("clrc","");
5414       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5415                AOP(left)->aopu.aop_dir,
5416                AOP(left)->aopu.aop_dir);
5417       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5418                AOP(right)->aopu.aop_dir,
5419                AOP(right)->aopu.aop_dir);
5420       pic16_emitcode("setc","");
5421
5422     } else {
5423         tlbl = newiTempLabel(NULL);
5424         pic16_toBoolean(left);
5425         emitSKPZ;
5426         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5427         pic16_toBoolean(right);
5428         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5429
5430         pic16_outBitAcc(result);
5431     }
5432
5433     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5434     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5435     pic16_freeAsmop(result,NULL,ic,TRUE);            
5436 }
5437
5438 /*-----------------------------------------------------------------*/
5439 /* isLiteralBit - test if lit == 2^n                               */
5440 /*-----------------------------------------------------------------*/
5441 static int isLiteralBit(unsigned long lit)
5442 {
5443     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5444     0x100L,0x200L,0x400L,0x800L,
5445     0x1000L,0x2000L,0x4000L,0x8000L,
5446     0x10000L,0x20000L,0x40000L,0x80000L,
5447     0x100000L,0x200000L,0x400000L,0x800000L,
5448     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5449     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5450     int idx;
5451     
5452     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5453     for(idx = 0; idx < 32; idx++)
5454         if(lit == pw[idx])
5455             return idx+1;
5456     return 0;
5457 }
5458
5459 /*-----------------------------------------------------------------*/
5460 /* continueIfTrue -                                                */
5461 /*-----------------------------------------------------------------*/
5462 static void continueIfTrue (iCode *ic)
5463 {
5464     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5465     if(IC_TRUE(ic))
5466         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5467     ic->generated = 1;
5468 }
5469
5470 /*-----------------------------------------------------------------*/
5471 /* jmpIfTrue -                                                     */
5472 /*-----------------------------------------------------------------*/
5473 static void jumpIfTrue (iCode *ic)
5474 {
5475     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5476     if(!IC_TRUE(ic))
5477         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5478     ic->generated = 1;
5479 }
5480
5481 /*-----------------------------------------------------------------*/
5482 /* jmpTrueOrFalse -                                                */
5483 /*-----------------------------------------------------------------*/
5484 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5485 {
5486     // ugly but optimized by peephole
5487     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5488     if(IC_TRUE(ic)){
5489         symbol *nlbl = newiTempLabel(NULL);
5490         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5491         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5492         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5493         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5494     }
5495     else{
5496         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5497         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5498     }
5499     ic->generated = 1;
5500 }
5501
5502 /*-----------------------------------------------------------------*/
5503 /* genAnd  - code for and                                          */
5504 /*-----------------------------------------------------------------*/
5505 static void genAnd (iCode *ic, iCode *ifx)
5506 {
5507   operand *left, *right, *result;
5508   int size, offset=0;  
5509   unsigned long lit = 0L;
5510   int bytelit = 0;
5511   resolvedIfx rIfx;
5512
5513
5514   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5515   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5516   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5517   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5518
5519   resolveIfx(&rIfx,ifx);
5520
5521   /* if left is a literal & right is not then exchange them */
5522   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5523       AOP_NEEDSACC(left)) {
5524     operand *tmp = right ;
5525     right = left;
5526     left = tmp;
5527   }
5528
5529   /* if result = right then exchange them */
5530   if(pic16_sameRegs(AOP(result),AOP(right))){
5531     operand *tmp = right ;
5532     right = left;
5533     left = tmp;
5534   }
5535
5536   /* if right is bit then exchange them */
5537   if (AOP_TYPE(right) == AOP_CRY &&
5538       AOP_TYPE(left) != AOP_CRY){
5539     operand *tmp = right ;
5540     right = left;
5541     left = tmp;
5542   }
5543   if(AOP_TYPE(right) == AOP_LIT)
5544     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5545
5546   size = AOP_SIZE(result);
5547
5548   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5549
5550   // if(bit & yy)
5551   // result = bit & yy;
5552   if (AOP_TYPE(left) == AOP_CRY){
5553     // c = bit & literal;
5554     if(AOP_TYPE(right) == AOP_LIT){
5555       if(lit & 1) {
5556         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5557           // no change
5558           goto release;
5559         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5560       } else {
5561         // bit(result) = 0;
5562         if(size && (AOP_TYPE(result) == AOP_CRY)){
5563           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5564           goto release;
5565         }
5566         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5567           jumpIfTrue(ifx);
5568           goto release;
5569         }
5570         pic16_emitcode("clr","c");
5571       }
5572     } else {
5573       if (AOP_TYPE(right) == AOP_CRY){
5574         // c = bit & bit;
5575         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5576         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5577       } else {
5578         // c = bit & val;
5579         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5580         // c = lsb
5581         pic16_emitcode("rrc","a");
5582         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5583       }
5584     }
5585     // bit = c
5586     // val = c
5587     if(size)
5588       pic16_outBitC(result);
5589     // if(bit & ...)
5590     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5591       genIfxJump(ifx, "c");           
5592     goto release ;
5593   }
5594
5595   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5596   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5597   if((AOP_TYPE(right) == AOP_LIT) &&
5598      (AOP_TYPE(result) == AOP_CRY) &&
5599      (AOP_TYPE(left) != AOP_CRY)){
5600     int posbit = isLiteralBit(lit);
5601     /* left &  2^n */
5602     if(posbit){
5603       posbit--;
5604       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5605       // bit = left & 2^n
5606       if(size)
5607         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5608       // if(left &  2^n)
5609       else{
5610         if(ifx){
5611 /*
5612           if(IC_TRUE(ifx)) {
5613             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5614             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5615           } else {
5616             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5617             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5618           }
5619 */
5620           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5621                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5622           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5623           
5624           ifx->generated = 1;
5625         }
5626         goto release;
5627       }
5628     } else {
5629       symbol *tlbl = newiTempLabel(NULL);
5630       int sizel = AOP_SIZE(left);
5631       if(size)
5632         pic16_emitcode("setb","c");
5633       while(sizel--){
5634         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5635           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5636           // byte ==  2^n ?
5637           if((posbit = isLiteralBit(bytelit)) != 0)
5638             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5639           else{
5640             if(bytelit != 0x0FFL)
5641               pic16_emitcode("anl","a,%s",
5642                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
5643             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5644           }
5645         }
5646         offset++;
5647       }
5648       // bit = left & literal
5649       if(size){
5650         pic16_emitcode("clr","c");
5651         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5652       }
5653       // if(left & literal)
5654       else{
5655         if(ifx)
5656           jmpTrueOrFalse(ifx, tlbl);
5657         goto release ;
5658       }
5659     }
5660     pic16_outBitC(result);
5661     goto release ;
5662   }
5663
5664   /* if left is same as result */
5665   if(pic16_sameRegs(AOP(result),AOP(left))){
5666     int know_W = -1;
5667     for(;size--; offset++,lit>>=8) {
5668       if(AOP_TYPE(right) == AOP_LIT){
5669         switch(lit & 0xff) {
5670         case 0x00:
5671           /*  and'ing with 0 has clears the result */
5672 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5673           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5674           break;
5675         case 0xff:
5676           /* and'ing with 0xff is a nop when the result and left are the same */
5677           break;
5678
5679         default:
5680           {
5681             int p = my_powof2( (~lit) & 0xff );
5682             if(p>=0) {
5683               /* only one bit is set in the literal, so use a bcf instruction */
5684 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5685               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5686
5687             } else {
5688               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5689               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5690               if(know_W != (lit&0xff))
5691                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5692               know_W = lit &0xff;
5693               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5694             }
5695           }    
5696         }
5697       } else {
5698         if (AOP_TYPE(left) == AOP_ACC) {
5699           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5700         } else {                    
5701           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5702           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5703
5704         }
5705       }
5706     }
5707
5708   } else {
5709     // left & result in different registers
5710     if(AOP_TYPE(result) == AOP_CRY){
5711       // result = bit
5712       // if(size), result in bit
5713       // if(!size && ifx), conditional oper: if(left & right)
5714       symbol *tlbl = newiTempLabel(NULL);
5715       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5716       if(size)
5717         pic16_emitcode("setb","c");
5718       while(sizer--){
5719         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5720         pic16_emitcode("anl","a,%s",
5721                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5722         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5723         offset++;
5724       }
5725       if(size){
5726         CLRC;
5727         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5728         pic16_outBitC(result);
5729       } else if(ifx)
5730         jmpTrueOrFalse(ifx, tlbl);
5731     } else {
5732       for(;(size--);offset++) {
5733         // normal case
5734         // result = left & right
5735         if(AOP_TYPE(right) == AOP_LIT){
5736           int t = (lit >> (offset*8)) & 0x0FFL;
5737           switch(t) { 
5738           case 0x00:
5739             pic16_emitcode("clrf","%s",
5740                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5741             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5742             break;
5743           case 0xff:
5744             pic16_emitcode("movf","%s,w",
5745                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5746             pic16_emitcode("movwf","%s",
5747                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5748             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5749             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5750             break;
5751           default:
5752             pic16_emitcode("movlw","0x%x",t);
5753             pic16_emitcode("andwf","%s,w",
5754                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5755             pic16_emitcode("movwf","%s",
5756                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5757               
5758             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5759             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5760             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5761           }
5762           continue;
5763         }
5764
5765         if (AOP_TYPE(left) == AOP_ACC) {
5766           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5767           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5768         } else {
5769           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5770           pic16_emitcode("andwf","%s,w",
5771                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5772           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5773           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5774         }
5775         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5776         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5777       }
5778     }
5779   }
5780
5781   release :
5782     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5783   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5784   pic16_freeAsmop(result,NULL,ic,TRUE);     
5785 }
5786
5787 /*-----------------------------------------------------------------*/
5788 /* genOr  - code for or                                            */
5789 /*-----------------------------------------------------------------*/
5790 static void genOr (iCode *ic, iCode *ifx)
5791 {
5792     operand *left, *right, *result;
5793     int size, offset=0;
5794     unsigned long lit = 0L;
5795
5796     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5797
5798     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5799     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5800     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5801
5802     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5803
5804     /* if left is a literal & right is not then exchange them */
5805     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5806         AOP_NEEDSACC(left)) {
5807         operand *tmp = right ;
5808         right = left;
5809         left = tmp;
5810     }
5811
5812     /* if result = right then exchange them */
5813     if(pic16_sameRegs(AOP(result),AOP(right))){
5814         operand *tmp = right ;
5815         right = left;
5816         left = tmp;
5817     }
5818
5819     /* if right is bit then exchange them */
5820     if (AOP_TYPE(right) == AOP_CRY &&
5821         AOP_TYPE(left) != AOP_CRY){
5822         operand *tmp = right ;
5823         right = left;
5824         left = tmp;
5825     }
5826
5827     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5828
5829     if(AOP_TYPE(right) == AOP_LIT)
5830         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5831
5832     size = AOP_SIZE(result);
5833
5834     // if(bit | yy)
5835     // xx = bit | yy;
5836     if (AOP_TYPE(left) == AOP_CRY){
5837         if(AOP_TYPE(right) == AOP_LIT){
5838             // c = bit & literal;
5839             if(lit){
5840                 // lit != 0 => result = 1
5841                 if(AOP_TYPE(result) == AOP_CRY){
5842                   if(size)
5843                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5844                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5845                   //     AOP(result)->aopu.aop_dir,
5846                   //     AOP(result)->aopu.aop_dir);
5847                     else if(ifx)
5848                         continueIfTrue(ifx);
5849                     goto release;
5850                 }
5851             } else {
5852                 // lit == 0 => result = left
5853                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5854                     goto release;
5855                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5856             }
5857         } else {
5858             if (AOP_TYPE(right) == AOP_CRY){
5859               if(pic16_sameRegs(AOP(result),AOP(left))){
5860                 // c = bit | bit;
5861                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5862                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5863                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5864
5865                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5866                          AOP(result)->aopu.aop_dir,
5867                          AOP(result)->aopu.aop_dir);
5868                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5869                          AOP(right)->aopu.aop_dir,
5870                          AOP(right)->aopu.aop_dir);
5871                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5872                          AOP(result)->aopu.aop_dir,
5873                          AOP(result)->aopu.aop_dir);
5874               } else {
5875                 if( AOP_TYPE(result) == AOP_ACC) {
5876                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5877                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5878                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5879                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5880
5881                 } else {
5882
5883                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5884                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5885                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5886                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5887
5888                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5889                                  AOP(result)->aopu.aop_dir,
5890                                  AOP(result)->aopu.aop_dir);
5891                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5892                                  AOP(right)->aopu.aop_dir,
5893                                  AOP(right)->aopu.aop_dir);
5894                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5895                                  AOP(left)->aopu.aop_dir,
5896                                  AOP(left)->aopu.aop_dir);
5897                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5898                                  AOP(result)->aopu.aop_dir,
5899                                  AOP(result)->aopu.aop_dir);
5900                 }
5901               }
5902             } else {
5903                 // c = bit | val;
5904                 symbol *tlbl = newiTempLabel(NULL);
5905                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5906
5907
5908                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5909                 if( AOP_TYPE(right) == AOP_ACC) {
5910                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5911                   emitSKPNZ;
5912                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5913                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5914                 }
5915
5916
5917
5918                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5919                     pic16_emitcode(";XXX setb","c");
5920                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5921                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5922                 pic16_toBoolean(right);
5923                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5924                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5925                     jmpTrueOrFalse(ifx, tlbl);
5926                     goto release;
5927                 } else {
5928                     CLRC;
5929                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5930                 }
5931             }
5932         }
5933         // bit = c
5934         // val = c
5935         if(size)
5936             pic16_outBitC(result);
5937         // if(bit | ...)
5938         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5939             genIfxJump(ifx, "c");           
5940         goto release ;
5941     }
5942
5943     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5944     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5945     if((AOP_TYPE(right) == AOP_LIT) &&
5946        (AOP_TYPE(result) == AOP_CRY) &&
5947        (AOP_TYPE(left) != AOP_CRY)){
5948         if(lit){
5949           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5950             // result = 1
5951             if(size)
5952                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5953             else 
5954                 continueIfTrue(ifx);
5955             goto release;
5956         } else {
5957           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5958             // lit = 0, result = boolean(left)
5959             if(size)
5960                 pic16_emitcode(";XXX setb","c");
5961             pic16_toBoolean(right);
5962             if(size){
5963                 symbol *tlbl = newiTempLabel(NULL);
5964                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5965                 CLRC;
5966                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5967             } else {
5968                 genIfxJump (ifx,"a");
5969                 goto release;
5970             }
5971         }
5972         pic16_outBitC(result);
5973         goto release ;
5974     }
5975
5976     /* if left is same as result */
5977     if(pic16_sameRegs(AOP(result),AOP(left))){
5978       int know_W = -1;
5979       for(;size--; offset++,lit>>=8) {
5980         if(AOP_TYPE(right) == AOP_LIT){
5981           if((lit & 0xff) == 0)
5982             /*  or'ing with 0 has no effect */
5983             continue;
5984           else {
5985             int p = my_powof2(lit & 0xff);
5986             if(p>=0) {
5987               /* only one bit is set in the literal, so use a bsf instruction */
5988               pic16_emitpcode(POC_BSF,
5989                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5990             } else {
5991               if(know_W != (lit & 0xff))
5992                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5993               know_W = lit & 0xff;
5994               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5995             }
5996                     
5997           }
5998         } else {
5999           if (AOP_TYPE(left) == AOP_ACC) {
6000             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6001             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6002           } else {                  
6003             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6004             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6005
6006             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6007             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6008
6009           }
6010         }
6011       }
6012     } else {
6013         // left & result in different registers
6014         if(AOP_TYPE(result) == AOP_CRY){
6015             // result = bit
6016             // if(size), result in bit
6017             // if(!size && ifx), conditional oper: if(left | right)
6018             symbol *tlbl = newiTempLabel(NULL);
6019             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6020             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6021
6022
6023             if(size)
6024                 pic16_emitcode(";XXX setb","c");
6025             while(sizer--){
6026                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6027                 pic16_emitcode(";XXX orl","a,%s",
6028                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6029                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6030                 offset++;
6031             }
6032             if(size){
6033                 CLRC;
6034                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6035                 pic16_outBitC(result);
6036             } else if(ifx)
6037                 jmpTrueOrFalse(ifx, tlbl);
6038         } else for(;(size--);offset++){
6039           // normal case
6040           // result = left & right
6041           if(AOP_TYPE(right) == AOP_LIT){
6042             int t = (lit >> (offset*8)) & 0x0FFL;
6043             switch(t) { 
6044             case 0x00:
6045               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6046               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6047
6048               pic16_emitcode("movf","%s,w",
6049                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6050               pic16_emitcode("movwf","%s",
6051                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6052               break;
6053             default:
6054               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6055               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6056               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6057
6058               pic16_emitcode("movlw","0x%x",t);
6059               pic16_emitcode("iorwf","%s,w",
6060                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6061               pic16_emitcode("movwf","%s",
6062                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6063               
6064             }
6065             continue;
6066           }
6067
6068           // faster than result <- left, anl result,right
6069           // and better if result is SFR
6070           if (AOP_TYPE(left) == AOP_ACC) {
6071             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6072             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6073           } else {
6074             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6075             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6076
6077             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6078             pic16_emitcode("iorwf","%s,w",
6079                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6080           }
6081           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6082           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6083         }
6084     }
6085
6086 release :
6087     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6088     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6089     pic16_freeAsmop(result,NULL,ic,TRUE);     
6090 }
6091
6092 /*-----------------------------------------------------------------*/
6093 /* genXor - code for xclusive or                                   */
6094 /*-----------------------------------------------------------------*/
6095 static void genXor (iCode *ic, iCode *ifx)
6096 {
6097   operand *left, *right, *result;
6098   int size, offset=0;
6099   unsigned long lit = 0L;
6100
6101   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6102
6103   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6104   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6105   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6106
6107   /* if left is a literal & right is not ||
6108      if left needs acc & right does not */
6109   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6110       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6111     operand *tmp = right ;
6112     right = left;
6113     left = tmp;
6114   }
6115
6116   /* if result = right then exchange them */
6117   if(pic16_sameRegs(AOP(result),AOP(right))){
6118     operand *tmp = right ;
6119     right = left;
6120     left = tmp;
6121   }
6122
6123   /* if right is bit then exchange them */
6124   if (AOP_TYPE(right) == AOP_CRY &&
6125       AOP_TYPE(left) != AOP_CRY){
6126     operand *tmp = right ;
6127     right = left;
6128     left = tmp;
6129   }
6130   if(AOP_TYPE(right) == AOP_LIT)
6131     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6132
6133   size = AOP_SIZE(result);
6134
6135   // if(bit ^ yy)
6136   // xx = bit ^ yy;
6137   if (AOP_TYPE(left) == AOP_CRY){
6138     if(AOP_TYPE(right) == AOP_LIT){
6139       // c = bit & literal;
6140       if(lit>>1){
6141         // lit>>1  != 0 => result = 1
6142         if(AOP_TYPE(result) == AOP_CRY){
6143           if(size)
6144             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6145             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6146           else if(ifx)
6147             continueIfTrue(ifx);
6148           goto release;
6149         }
6150         pic16_emitcode("setb","c");
6151       } else{
6152         // lit == (0 or 1)
6153         if(lit == 0){
6154           // lit == 0, result = left
6155           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6156             goto release;
6157           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6158         } else{
6159           // lit == 1, result = not(left)
6160           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6161             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6162             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6163             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6164             goto release;
6165           } else {
6166             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6167             pic16_emitcode("cpl","c");
6168           }
6169         }
6170       }
6171
6172     } else {
6173       // right != literal
6174       symbol *tlbl = newiTempLabel(NULL);
6175       if (AOP_TYPE(right) == AOP_CRY){
6176         // c = bit ^ bit;
6177         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6178       }
6179       else{
6180         int sizer = AOP_SIZE(right);
6181         // c = bit ^ val
6182         // if val>>1 != 0, result = 1
6183         pic16_emitcode("setb","c");
6184         while(sizer){
6185           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6186           if(sizer == 1)
6187             // test the msb of the lsb
6188             pic16_emitcode("anl","a,#0xfe");
6189           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6190           sizer--;
6191         }
6192         // val = (0,1)
6193         pic16_emitcode("rrc","a");
6194       }
6195       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6196       pic16_emitcode("cpl","c");
6197       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6198     }
6199     // bit = c
6200     // val = c
6201     if(size)
6202       pic16_outBitC(result);
6203     // if(bit | ...)
6204     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6205       genIfxJump(ifx, "c");           
6206     goto release ;
6207   }
6208
6209   if(pic16_sameRegs(AOP(result),AOP(left))){
6210     /* if left is same as result */
6211     for(;size--; offset++) {
6212       if(AOP_TYPE(right) == AOP_LIT){
6213         int t  = (lit >> (offset*8)) & 0x0FFL;
6214         if(t == 0x00L)
6215           continue;
6216         else
6217           if (IS_AOP_PREG(left)) {
6218             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6219             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6220             pic16_aopPut(AOP(result),"a",offset);
6221           } else {
6222             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6223             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6224             pic16_emitcode("xrl","%s,%s",
6225                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6226                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6227           }
6228       } else {
6229         if (AOP_TYPE(left) == AOP_ACC)
6230           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6231         else {
6232           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6233           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6234 /*
6235           if (IS_AOP_PREG(left)) {
6236             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6237             pic16_aopPut(AOP(result),"a",offset);
6238           } else
6239             pic16_emitcode("xrl","%s,a",
6240                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6241 */
6242         }
6243       }
6244     }
6245   } else {
6246     // left & result in different registers
6247     if(AOP_TYPE(result) == AOP_CRY){
6248       // result = bit
6249       // if(size), result in bit
6250       // if(!size && ifx), conditional oper: if(left ^ right)
6251       symbol *tlbl = newiTempLabel(NULL);
6252       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6253       if(size)
6254         pic16_emitcode("setb","c");
6255       while(sizer--){
6256         if((AOP_TYPE(right) == AOP_LIT) &&
6257            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6258           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6259         } else {
6260           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6261           pic16_emitcode("xrl","a,%s",
6262                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6263         }
6264         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6265         offset++;
6266       }
6267       if(size){
6268         CLRC;
6269         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6270         pic16_outBitC(result);
6271       } else if(ifx)
6272         jmpTrueOrFalse(ifx, tlbl);
6273     } else for(;(size--);offset++){
6274       // normal case
6275       // result = left & right
6276       if(AOP_TYPE(right) == AOP_LIT){
6277         int t = (lit >> (offset*8)) & 0x0FFL;
6278         switch(t) { 
6279         case 0x00:
6280           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6281           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6282           pic16_emitcode("movf","%s,w",
6283                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6284           pic16_emitcode("movwf","%s",
6285                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6286           break;
6287         case 0xff:
6288           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6289           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6290           pic16_emitcode("comf","%s,w",
6291                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6292           pic16_emitcode("movwf","%s",
6293                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6294           break;
6295         default:
6296           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6297           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6298           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6299           pic16_emitcode("movlw","0x%x",t);
6300           pic16_emitcode("xorwf","%s,w",
6301                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6302           pic16_emitcode("movwf","%s",
6303                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6304
6305         }
6306         continue;
6307       }
6308
6309       // faster than result <- left, anl result,right
6310       // and better if result is SFR
6311       if (AOP_TYPE(left) == AOP_ACC) {
6312         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6313         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6314       } else {
6315         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6316         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6317         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6318         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6319       }
6320       if ( AOP_TYPE(result) != AOP_ACC){
6321         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6322         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6323       }
6324     }
6325   }
6326
6327   release :
6328     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6329   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6330   pic16_freeAsmop(result,NULL,ic,TRUE);     
6331 }
6332
6333 /*-----------------------------------------------------------------*/
6334 /* genInline - write the inline code out                           */
6335 /*-----------------------------------------------------------------*/
6336 static void genInline (iCode *ic)
6337 {
6338     char *buffer, *bp, *bp1;
6339     
6340     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6341
6342     _G.inLine += (!options.asmpeep);
6343
6344     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6345     strcpy(buffer,IC_INLINE(ic));
6346
6347     /* emit each line as a code */
6348     while (*bp) {
6349         if (*bp == '\n') {
6350             *bp++ = '\0';
6351
6352             if(*bp1)
6353 #if 0
6354                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL));
6355 #else
6356                 pic16_addpCode2pBlock(pb, pic16_AssembleLine(bp1, 0));
6357 #endif
6358                                         // inline directly, no process
6359             bp1 = bp;
6360         } else {
6361             if (*bp == ':') {
6362                 bp++;
6363                 *bp = '\0';
6364                 bp++;
6365                 pic16_emitcode(bp1,"");
6366                 bp1 = bp;
6367             } else
6368                 bp++;
6369         }
6370     }
6371     if ((bp1 != bp) && *bp1)
6372       pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL));               //pic16_AssembleLine(bp1, 0));
6373
6374     Safe_free(buffer);
6375
6376     _G.inLine -= (!options.asmpeep);
6377 }
6378
6379 /*-----------------------------------------------------------------*/
6380 /* genRRC - rotate right with carry                                */
6381 /*-----------------------------------------------------------------*/
6382 static void genRRC (iCode *ic)
6383 {
6384   operand *left , *result ;
6385   int size, offset = 0, same;
6386
6387   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6388
6389   /* rotate right with carry */
6390   left = IC_LEFT(ic);
6391   result=IC_RESULT(ic);
6392   pic16_aopOp (left,ic,FALSE);
6393   pic16_aopOp (result,ic,FALSE);
6394
6395   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6396
6397   same = pic16_sameRegs(AOP(result),AOP(left));
6398
6399   size = AOP_SIZE(result);    
6400
6401   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6402
6403   /* get the lsb and put it into the carry */
6404   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6405
6406   offset = 0 ;
6407
6408   while(size--) {
6409
6410     if(same) {
6411       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6412     } else {
6413       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6414       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6415     }
6416
6417     offset++;
6418   }
6419
6420   pic16_freeAsmop(left,NULL,ic,TRUE);
6421   pic16_freeAsmop(result,NULL,ic,TRUE);
6422 }
6423
6424 /*-----------------------------------------------------------------*/
6425 /* genRLC - generate code for rotate left with carry               */
6426 /*-----------------------------------------------------------------*/
6427 static void genRLC (iCode *ic)
6428 {    
6429   operand *left , *result ;
6430   int size, offset = 0;
6431   int same;
6432
6433   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6434   /* rotate right with carry */
6435   left = IC_LEFT(ic);
6436   result=IC_RESULT(ic);
6437   pic16_aopOp (left,ic,FALSE);
6438   pic16_aopOp (result,ic,FALSE);
6439
6440   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6441
6442   same = pic16_sameRegs(AOP(result),AOP(left));
6443
6444   /* move it to the result */
6445   size = AOP_SIZE(result);    
6446
6447   /* get the msb and put it into the carry */
6448   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6449
6450   offset = 0 ;
6451
6452   while(size--) {
6453
6454     if(same) {
6455       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6456     } else {
6457       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6458       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6459     }
6460
6461     offset++;
6462   }
6463
6464
6465   pic16_freeAsmop(left,NULL,ic,TRUE);
6466   pic16_freeAsmop(result,NULL,ic,TRUE);
6467 }
6468
6469 /*-----------------------------------------------------------------*/
6470 /* genGetHbit - generates code get highest order bit               */
6471 /*-----------------------------------------------------------------*/
6472 static void genGetHbit (iCode *ic)
6473 {
6474     operand *left, *result;
6475     left = IC_LEFT(ic);
6476     result=IC_RESULT(ic);
6477     pic16_aopOp (left,ic,FALSE);
6478     pic16_aopOp (result,ic,FALSE);
6479
6480     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6481     /* get the highest order byte into a */
6482     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6483     if(AOP_TYPE(result) == AOP_CRY){
6484         pic16_emitcode("rlc","a");
6485         pic16_outBitC(result);
6486     }
6487     else{
6488         pic16_emitcode("rl","a");
6489         pic16_emitcode("anl","a,#0x01");
6490         pic16_outAcc(result);
6491     }
6492
6493
6494     pic16_freeAsmop(left,NULL,ic,TRUE);
6495     pic16_freeAsmop(result,NULL,ic,TRUE);
6496 }
6497
6498 #if 0
6499 /*-----------------------------------------------------------------*/
6500 /* AccRol - rotate left accumulator by known count                 */
6501 /*-----------------------------------------------------------------*/
6502 static void AccRol (int shCount)
6503 {
6504     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6505     shCount &= 0x0007;              // shCount : 0..7
6506     switch(shCount){
6507         case 0 :
6508             break;
6509         case 1 :
6510             pic16_emitcode("rl","a");
6511             break;
6512         case 2 :
6513             pic16_emitcode("rl","a");
6514             pic16_emitcode("rl","a");
6515             break;
6516         case 3 :
6517             pic16_emitcode("swap","a");
6518             pic16_emitcode("rr","a");
6519             break;
6520         case 4 :
6521             pic16_emitcode("swap","a");
6522             break;
6523         case 5 :
6524             pic16_emitcode("swap","a");
6525             pic16_emitcode("rl","a");
6526             break;
6527         case 6 :
6528             pic16_emitcode("rr","a");
6529             pic16_emitcode("rr","a");
6530             break;
6531         case 7 :
6532             pic16_emitcode("rr","a");
6533             break;
6534     }
6535 }
6536 #endif
6537
6538 /*-----------------------------------------------------------------*/
6539 /* AccLsh - left shift accumulator by known count                  */
6540 /*-----------------------------------------------------------------*/
6541 static void AccLsh (int shCount)
6542 {
6543     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6544     switch(shCount){
6545         case 0 :
6546                         return;
6547             break;
6548         case 1 :
6549             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6550             break;
6551         case 2 :
6552             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6553             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6554             break;
6555         case 3 :
6556             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6557             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6558             break;
6559         case 4 :
6560             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6561             break;
6562         case 5 :
6563             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6564             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6565             break;
6566         case 6 :
6567             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6568             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6569             break;
6570         case 7 :
6571             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6572             break;
6573     }
6574     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6575
6576 }
6577
6578 /*-----------------------------------------------------------------*/
6579 /* AccRsh - right shift accumulator by known count                 */
6580 /*-----------------------------------------------------------------*/
6581 static void AccRsh (int shCount)
6582 {
6583     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6584     switch(shCount){
6585         case 0 :
6586                         return;
6587             break;
6588         case 1 :
6589             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6590             break;
6591         case 2 :
6592             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6593             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6594             break;
6595         case 3 :
6596             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6597             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6598             break;
6599         case 4 :
6600             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6601             break;
6602         case 5 :
6603             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6604             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6605             break;
6606         case 6 :
6607             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6608             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6609             break;
6610         case 7 :
6611             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6612             break;
6613     }
6614     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6615 }
6616
6617 #if 0
6618 /*-----------------------------------------------------------------*/
6619 /* AccSRsh - signed right shift accumulator by known count                 */
6620 /*-----------------------------------------------------------------*/
6621 static void AccSRsh (int shCount)
6622 {
6623     symbol *tlbl ;
6624     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6625     if(shCount != 0){
6626         if(shCount == 1){
6627             pic16_emitcode("mov","c,acc.7");
6628             pic16_emitcode("rrc","a");
6629         } else if(shCount == 2){
6630             pic16_emitcode("mov","c,acc.7");
6631             pic16_emitcode("rrc","a");
6632             pic16_emitcode("mov","c,acc.7");
6633             pic16_emitcode("rrc","a");
6634         } else {
6635             tlbl = newiTempLabel(NULL);
6636             /* rotate right accumulator */
6637             AccRol(8 - shCount);
6638             /* and kill the higher order bits */
6639             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6640             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6641             pic16_emitcode("orl","a,#0x%02x",
6642                      (unsigned char)~SRMask[shCount]);
6643             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6644         }
6645     }
6646 }
6647 #endif
6648 /*-----------------------------------------------------------------*/
6649 /* shiftR1Left2Result - shift right one byte from left to result   */
6650 /*-----------------------------------------------------------------*/
6651 static void shiftR1Left2ResultSigned (operand *left, int offl,
6652                                 operand *result, int offr,
6653                                 int shCount)
6654 {
6655   int same;
6656
6657   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6658
6659   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6660
6661   switch(shCount) {
6662   case 1:
6663     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6664     if(same) 
6665       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6666     else {
6667       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6668       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6669     }
6670
6671     break;
6672   case 2:
6673
6674     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6675     if(same) 
6676       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6677     else {
6678       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6679       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6680     }
6681     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6682     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6683
6684     break;
6685
6686   case 3:
6687     if(same)
6688       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6689     else {
6690       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6691       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6692     }
6693
6694     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6695     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6696     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6697
6698     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6699     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
6700
6701     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6702     break;
6703
6704   case 4:
6705     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6706     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
6707     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6708     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
6709     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6710     break;
6711   case 5:
6712     if(same) {
6713       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
6714     } else {
6715       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
6716       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6717     }
6718     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
6719     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
6720     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6721     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
6722     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6723     break;
6724
6725   case 6:
6726     if(same) {
6727       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6728       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6729       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
6730       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6731       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
6732       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6733     } else {
6734       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6735       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6736       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6737       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6738       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6739     }
6740     break;
6741
6742   case 7:
6743     if(same) {
6744       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6745       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6746       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6747       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6748     } else {
6749       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6750       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6751       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6752     }
6753
6754   default:
6755     break;
6756   }
6757 }
6758
6759 /*-----------------------------------------------------------------*/
6760 /* shiftR1Left2Result - shift right one byte from left to result   */
6761 /*-----------------------------------------------------------------*/
6762 static void shiftR1Left2Result (operand *left, int offl,
6763                                 operand *result, int offr,
6764                                 int shCount, int sign)
6765 {
6766   int same;
6767
6768   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6769
6770   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6771
6772   /* Copy the msb into the carry if signed. */
6773   if(sign) {
6774     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6775     return;
6776   }
6777
6778
6779
6780   switch(shCount) {
6781   case 1:
6782     emitCLRC;
6783     if(same) 
6784       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6785     else {
6786       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6787       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6788     }
6789     break;
6790   case 2:
6791     emitCLRC;
6792     if(same) {
6793       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6794     } else {
6795       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6796       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6797     }
6798     emitCLRC;
6799     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6800
6801     break;
6802   case 3:
6803     if(same)
6804       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6805     else {
6806       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6807       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6808     }
6809
6810     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6811     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6812     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6813     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6814     break;
6815       
6816   case 4:
6817     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6818     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6819     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6820     break;
6821
6822   case 5:
6823     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6824     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6825     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6826     emitCLRC;
6827     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6828
6829     break;
6830   case 6:
6831
6832     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
6833     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6834     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6835     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6836     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6837     break;
6838
6839   case 7:
6840
6841     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6842     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6843     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6844
6845     break;
6846
6847   default:
6848     break;
6849   }
6850 }
6851
6852 /*-----------------------------------------------------------------*/
6853 /* shiftL1Left2Result - shift left one byte from left to result    */
6854 /*-----------------------------------------------------------------*/
6855 static void shiftL1Left2Result (operand *left, int offl,
6856                                 operand *result, int offr, int shCount)
6857 {
6858   int same;
6859
6860   //    char *l;
6861   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6862
6863   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6864   DEBUGpic16_emitcode ("; ***","same =  %d",same);
6865     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6866     //    MOVA(l);
6867     /* shift left accumulator */
6868     //AccLsh(shCount); // don't comment out just yet...
6869   //    pic16_aopPut(AOP(result),"a",offr);
6870
6871   switch(shCount) {
6872   case 1:
6873     /* Shift left 1 bit position */
6874     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6875     if(same) {
6876       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
6877     } else {
6878       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
6879       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6880     }
6881     break;
6882   case 2:
6883     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6884     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
6885     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6886     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6887     break;
6888   case 3:
6889     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6890     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
6891     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6892     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6893     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6894     break;
6895   case 4:
6896     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6897     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6898     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6899     break;
6900   case 5:
6901     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6902     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6903     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6904     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6905     break;
6906   case 6:
6907     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6908     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
6909     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6910     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6911     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6912     break;
6913   case 7:
6914     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6915     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6916     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6917     break;
6918
6919   default:
6920     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6921   }
6922
6923 }
6924
6925 /*-----------------------------------------------------------------*/
6926 /* movLeft2Result - move byte from left to result                  */
6927 /*-----------------------------------------------------------------*/
6928 static void movLeft2Result (operand *left, int offl,
6929                             operand *result, int offr)
6930 {
6931   char *l;
6932   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6933   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6934     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6935
6936     if (*l == '@' && (IS_AOP_PREG(result))) {
6937       pic16_emitcode("mov","a,%s",l);
6938       pic16_aopPut(AOP(result),"a",offr);
6939     } else {
6940       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6941       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6942     }
6943   }
6944 }
6945
6946 /*-----------------------------------------------------------------*/
6947 /* shiftL2Left2Result - shift left two bytes from left to result   */
6948 /*-----------------------------------------------------------------*/
6949 static void shiftL2Left2Result (operand *left, int offl,
6950                                 operand *result, int offr, int shCount)
6951 {
6952   int same = pic16_sameRegs(AOP(result), AOP(left));
6953   int i;
6954
6955   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6956
6957   if (same && (offl != offr)) { // shift bytes
6958     if (offr > offl) {
6959        for(i=1;i>-1;i--) {
6960          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6961          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6962        }
6963     } else { // just treat as different later on
6964                 same = 0;
6965     }
6966   }
6967
6968   if(same) {
6969     switch(shCount) {
6970     case 0:
6971       break;
6972     case 1:
6973     case 2:
6974     case 3:
6975
6976       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6977       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6978       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6979
6980       while(--shCount) {
6981                 emitCLRC;
6982                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6983                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6984       }
6985
6986       break;
6987     case 4:
6988     case 5:
6989       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6990       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6991       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6992       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6993       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6994       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6995       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6996       if(shCount >=5) {
6997                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6998                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6999       }
7000       break;
7001     case 6:
7002       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7003       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7004       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7005       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7006       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7007       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7008       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7009       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7010       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7011       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7012       break;
7013     case 7:
7014       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7015       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7016       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7017       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7018       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7019     }
7020
7021   } else {
7022     switch(shCount) {
7023     case 0:
7024       break;
7025     case 1:
7026     case 2:
7027     case 3:
7028       /* note, use a mov/add for the shift since the mov has a
7029          chance of getting optimized out */
7030       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7031       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7032       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7033       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7034       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7035
7036       while(--shCount) {
7037                 emitCLRC;
7038                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7039                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7040       }
7041       break;
7042
7043     case 4:
7044     case 5:
7045       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7046       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7047       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7048       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7049       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7050       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7051       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7052       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7053
7054
7055       if(shCount == 5) {
7056                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7057                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7058       }
7059       break;
7060     case 6:
7061       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7062       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7063       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7064       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7065
7066       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7067       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7068       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7069       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7070       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7071       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7072       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7073       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7074       break;
7075     case 7:
7076       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7077       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7078       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7079       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7080       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7081     }
7082   }
7083
7084 }
7085 /*-----------------------------------------------------------------*/
7086 /* shiftR2Left2Result - shift right two bytes from left to result  */
7087 /*-----------------------------------------------------------------*/
7088 static void shiftR2Left2Result (operand *left, int offl,
7089                                 operand *result, int offr,
7090                                 int shCount, int sign)
7091 {
7092   int same = pic16_sameRegs(AOP(result), AOP(left));
7093   int i;
7094   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7095
7096   if (same && (offl != offr)) { // shift right bytes
7097     if (offr < offl) {
7098        for(i=0;i<2;i++) {
7099          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7100          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7101        }
7102     } else { // just treat as different later on
7103                 same = 0;
7104     }
7105   }
7106
7107   switch(shCount) {
7108   case 0:
7109     break;
7110   case 1:
7111   case 2:
7112   case 3:
7113     if(sign)
7114       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7115     else
7116       emitCLRC;
7117
7118     if(same) {
7119       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7120       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7121     } else {
7122       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7123       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7124       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7125       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7126     }
7127
7128     while(--shCount) {
7129       if(sign)
7130                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7131       else
7132                 emitCLRC;
7133       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7134       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7135     }
7136     break;
7137   case 4:
7138   case 5:
7139     if(same) {
7140
7141       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7142       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7143       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7144
7145       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7146       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7147       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7148       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7149     } else {
7150       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7151       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7152       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7153
7154       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7155       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7156       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7157       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7158       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7159     }
7160
7161     if(shCount >=5) {
7162       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7163       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7164     }
7165
7166     if(sign) {
7167       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7168       pic16_emitpcode(POC_BTFSC, 
7169                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7170       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7171     }
7172
7173     break;
7174
7175   case 6:
7176     if(same) {
7177
7178       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7179       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7180
7181       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7182       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7183       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7184       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7185       if(sign) {
7186         pic16_emitpcode(POC_BTFSC, 
7187                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7188         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7189       }
7190       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7191       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7192       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7193       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7194     } else {
7195       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7196       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7197       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7198       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7199       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7200       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7201       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7202       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7203       if(sign) {
7204         pic16_emitpcode(POC_BTFSC, 
7205                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7206         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7207       }
7208       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7209       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7210
7211         
7212     }
7213
7214     break;
7215   case 7:
7216     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7217     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7218     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7219     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7220     if(sign) {
7221       emitSKPNC;
7222       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7223     } else 
7224       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7225   }
7226 }
7227
7228
7229 /*-----------------------------------------------------------------*/
7230 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7231 /*-----------------------------------------------------------------*/
7232 static void shiftLLeftOrResult (operand *left, int offl,
7233                                 operand *result, int offr, int shCount)
7234 {
7235     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7236
7237     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7238     /* shift left accumulator */
7239     AccLsh(shCount);
7240     /* or with result */
7241     /* back to result */
7242     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7243 }
7244
7245 /*-----------------------------------------------------------------*/
7246 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7247 /*-----------------------------------------------------------------*/
7248 static void shiftRLeftOrResult (operand *left, int offl,
7249                                 operand *result, int offr, int shCount)
7250 {
7251     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7252     
7253     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7254     /* shift right accumulator */
7255     AccRsh(shCount);
7256     /* or with result */
7257     /* back to result */
7258     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7259 }
7260
7261 /*-----------------------------------------------------------------*/
7262 /* genlshOne - left shift a one byte quantity by known count       */
7263 /*-----------------------------------------------------------------*/
7264 static void genlshOne (operand *result, operand *left, int shCount)
7265 {       
7266     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7267     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7268 }
7269
7270 /*-----------------------------------------------------------------*/
7271 /* genlshTwo - left shift two bytes by known amount != 0           */
7272 /*-----------------------------------------------------------------*/
7273 static void genlshTwo (operand *result,operand *left, int shCount)
7274 {
7275     int size;
7276     
7277     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7278     size = pic16_getDataSize(result);
7279
7280     /* if shCount >= 8 */
7281     if (shCount >= 8) {
7282         shCount -= 8 ;
7283
7284         if (size > 1){
7285             if (shCount)
7286                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7287             else 
7288                 movLeft2Result(left, LSB, result, MSB16);
7289         }
7290         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7291     }
7292
7293     /*  1 <= shCount <= 7 */
7294     else {  
7295         if(size == 1)
7296             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7297         else 
7298             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7299     }
7300 }
7301
7302 /*-----------------------------------------------------------------*/
7303 /* shiftLLong - shift left one long from left to result            */
7304 /* offr = LSB or MSB16                                             */
7305 /*-----------------------------------------------------------------*/
7306 static void shiftLLong (operand *left, operand *result, int offr )
7307 {
7308     int size = AOP_SIZE(result);
7309     int same = pic16_sameRegs(AOP(left),AOP(result));
7310         int i;
7311
7312     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7313
7314         if (same && (offr == MSB16)) { //shift one byte
7315                 for(i=size-1;i>=MSB16;i--) {
7316                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7317                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7318                 }
7319         } else {
7320                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7321         }
7322         
7323     if (size >= LSB+offr ){
7324                 if (same) {
7325                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7326                 } else {
7327                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7328                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7329                 }
7330          }
7331
7332     if(size >= MSB16+offr){
7333                 if (same) {
7334                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7335                 } else {
7336                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7337                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7338                 }
7339     }
7340
7341     if(size >= MSB24+offr){
7342                 if (same) {
7343                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7344                 } else {
7345                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7346                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7347                 }
7348     }
7349
7350     if(size > MSB32+offr){
7351                 if (same) {
7352                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7353                 } else {
7354                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7355                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7356                 }
7357     }
7358     if(offr != LSB)
7359                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7360
7361 }
7362
7363 /*-----------------------------------------------------------------*/
7364 /* genlshFour - shift four byte by a known amount != 0             */
7365 /*-----------------------------------------------------------------*/
7366 static void genlshFour (operand *result, operand *left, int shCount)
7367 {
7368     int size;
7369
7370     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7371     size = AOP_SIZE(result);
7372
7373     /* if shifting more that 3 bytes */
7374     if (shCount >= 24 ) {
7375         shCount -= 24;
7376         if (shCount)
7377             /* lowest order of left goes to the highest
7378             order of the destination */
7379             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7380         else
7381             movLeft2Result(left, LSB, result, MSB32);
7382
7383                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7384                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7385                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7386
7387         return;
7388     }
7389
7390     /* more than two bytes */
7391     else if ( shCount >= 16 ) {
7392         /* lower order two bytes goes to higher order two bytes */
7393         shCount -= 16;
7394         /* if some more remaining */
7395         if (shCount)
7396             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7397         else {
7398             movLeft2Result(left, MSB16, result, MSB32);
7399             movLeft2Result(left, LSB, result, MSB24);
7400         }
7401                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7402                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7403         return;
7404     }    
7405
7406     /* if more than 1 byte */
7407     else if ( shCount >= 8 ) {
7408         /* lower order three bytes goes to higher order  three bytes */
7409         shCount -= 8;
7410         if(size == 2){
7411             if(shCount)
7412                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7413             else
7414                 movLeft2Result(left, LSB, result, MSB16);
7415         }
7416         else{   /* size = 4 */
7417             if(shCount == 0){
7418                 movLeft2Result(left, MSB24, result, MSB32);
7419                 movLeft2Result(left, MSB16, result, MSB24);
7420                 movLeft2Result(left, LSB, result, MSB16);
7421                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7422             }
7423             else if(shCount == 1)
7424                 shiftLLong(left, result, MSB16);
7425             else{
7426                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7427                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7428                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7429                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7430             }
7431         }
7432     }
7433
7434     /* 1 <= shCount <= 7 */
7435     else if(shCount <= 3)
7436     { 
7437         shiftLLong(left, result, LSB);
7438         while(--shCount >= 1)
7439             shiftLLong(result, result, LSB);
7440     }
7441     /* 3 <= shCount <= 7, optimize */
7442     else{
7443         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7444         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7445         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7446     }
7447 }
7448
7449 /*-----------------------------------------------------------------*/
7450 /* genLeftShiftLiteral - left shifting by known count              */
7451 /*-----------------------------------------------------------------*/
7452 static void genLeftShiftLiteral (operand *left,
7453                                  operand *right,
7454                                  operand *result,
7455                                  iCode *ic)
7456 {    
7457     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7458     int size;
7459
7460     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7461     pic16_freeAsmop(right,NULL,ic,TRUE);
7462
7463     pic16_aopOp(left,ic,FALSE);
7464     pic16_aopOp(result,ic,FALSE);
7465
7466     size = getSize(operandType(result));
7467
7468 #if VIEW_SIZE
7469     pic16_emitcode("; shift left ","result %d, left %d",size,
7470              AOP_SIZE(left));
7471 #endif
7472
7473     /* I suppose that the left size >= result size */
7474     if(shCount == 0){
7475         while(size--){
7476             movLeft2Result(left, size, result, size);
7477         }
7478     }
7479
7480     else if(shCount >= (size * 8))
7481         while(size--)
7482             pic16_aopPut(AOP(result),zero,size);
7483     else{
7484         switch (size) {
7485             case 1:
7486                 genlshOne (result,left,shCount);
7487                 break;
7488
7489             case 2:
7490             case 3:
7491                 genlshTwo (result,left,shCount);
7492                 break;
7493
7494             case 4:
7495                 genlshFour (result,left,shCount);
7496                 break;
7497         }
7498     }
7499     pic16_freeAsmop(left,NULL,ic,TRUE);
7500     pic16_freeAsmop(result,NULL,ic,TRUE);
7501 }
7502
7503 /*-----------------------------------------------------------------*
7504  * genMultiAsm - repeat assembly instruction for size of register.
7505  * if endian == 1, then the high byte (i.e base address + size of 
7506  * register) is used first else the low byte is used first;
7507  *-----------------------------------------------------------------*/
7508 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7509 {
7510
7511   int offset = 0;
7512
7513   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7514
7515   if(!reg)
7516     return;
7517
7518   if(!endian) {
7519     endian = 1;
7520   } else {
7521     endian = -1;
7522     offset = size-1;
7523   }
7524
7525   while(size--) {
7526     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7527     offset += endian;
7528   }
7529
7530 }
7531 /*-----------------------------------------------------------------*/
7532 /* genLeftShift - generates code for left shifting                 */
7533 /*-----------------------------------------------------------------*/
7534 static void genLeftShift (iCode *ic)
7535 {
7536   operand *left,*right, *result;
7537   int size, offset;
7538   char *l;
7539   symbol *tlbl , *tlbl1;
7540   pCodeOp *pctemp;
7541
7542   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7543
7544   right = IC_RIGHT(ic);
7545   left  = IC_LEFT(ic);
7546   result = IC_RESULT(ic);
7547
7548   pic16_aopOp(right,ic,FALSE);
7549
7550   /* if the shift count is known then do it 
7551      as efficiently as possible */
7552   if (AOP_TYPE(right) == AOP_LIT) {
7553     genLeftShiftLiteral (left,right,result,ic);
7554     return ;
7555   }
7556
7557   /* shift count is unknown then we have to form 
7558      a loop get the loop count in B : Note: we take
7559      only the lower order byte since shifting
7560      more that 32 bits make no sense anyway, ( the
7561      largest size of an object can be only 32 bits ) */  
7562
7563     
7564   pic16_aopOp(left,ic,FALSE);
7565   pic16_aopOp(result,ic,FALSE);
7566
7567   /* now move the left to the result if they are not the
7568      same */
7569   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7570       AOP_SIZE(result) > 1) {
7571
7572     size = AOP_SIZE(result);
7573     offset=0;
7574     while (size--) {
7575       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7576       if (*l == '@' && (IS_AOP_PREG(result))) {
7577
7578         pic16_emitcode("mov","a,%s",l);
7579         pic16_aopPut(AOP(result),"a",offset);
7580       } else {
7581         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7582         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7583         //pic16_aopPut(AOP(result),l,offset);
7584       }
7585       offset++;
7586     }
7587   }
7588
7589   size = AOP_SIZE(result);
7590
7591   /* if it is only one byte then */
7592   if (size == 1) {
7593     if(optimized_for_speed) {
7594       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7595       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7596       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7597       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7598       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7599       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7600       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7601       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7602       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7603       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7604       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7605       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7606     } else {
7607
7608       tlbl = newiTempLabel(NULL);
7609       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7610                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7611                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7612       }
7613
7614       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7615       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7616       pic16_emitpLabel(tlbl->key);
7617       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7618       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7619       emitSKPC;
7620       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7621     }
7622     goto release ;
7623   }
7624     
7625   if (pic16_sameRegs(AOP(left),AOP(result))) {
7626
7627     tlbl = newiTempLabel(NULL);
7628     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7629     genMultiAsm(POC_RRCF, result, size,1);
7630     pic16_emitpLabel(tlbl->key);
7631     genMultiAsm(POC_RLCF, result, size,0);
7632     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7633     emitSKPC;
7634     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7635     goto release;
7636   }
7637
7638   //tlbl = newiTempLabel(NULL);
7639   //offset = 0 ;   
7640   //tlbl1 = newiTempLabel(NULL);
7641
7642   //reAdjustPreg(AOP(result));    
7643     
7644   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7645   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7646   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7647   //MOVA(l);
7648   //pic16_emitcode("add","a,acc");         
7649   //pic16_aopPut(AOP(result),"a",offset++);
7650   //while (--size) {
7651   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7652   //  MOVA(l);
7653   //  pic16_emitcode("rlc","a");         
7654   //  pic16_aopPut(AOP(result),"a",offset++);
7655   //}
7656   //reAdjustPreg(AOP(result));
7657
7658   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7659   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7660
7661
7662   tlbl = newiTempLabel(NULL);
7663   tlbl1= newiTempLabel(NULL);
7664
7665   size = AOP_SIZE(result);
7666   offset = 1;
7667
7668   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7669
7670   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7671
7672   /* offset should be 0, 1 or 3 */
7673   
7674   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
7675   emitSKPNZ;
7676   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7677
7678   pic16_emitpcode(POC_MOVWF, pctemp);
7679
7680
7681   pic16_emitpLabel(tlbl->key);
7682
7683   emitCLRC;
7684   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
7685   while(--size)
7686     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
7687
7688   pic16_emitpcode(POC_DECFSZ,  pctemp);
7689   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7690   pic16_emitpLabel(tlbl1->key);
7691
7692   pic16_popReleaseTempReg(pctemp);
7693
7694
7695  release:
7696   pic16_freeAsmop (right,NULL,ic,TRUE);
7697   pic16_freeAsmop(left,NULL,ic,TRUE);
7698   pic16_freeAsmop(result,NULL,ic,TRUE);
7699 }
7700
7701 /*-----------------------------------------------------------------*/
7702 /* genrshOne - right shift a one byte quantity by known count      */
7703 /*-----------------------------------------------------------------*/
7704 static void genrshOne (operand *result, operand *left,
7705                        int shCount, int sign)
7706 {
7707     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7708     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7709 }
7710
7711 /*-----------------------------------------------------------------*/
7712 /* genrshTwo - right shift two bytes by known amount != 0          */
7713 /*-----------------------------------------------------------------*/
7714 static void genrshTwo (operand *result,operand *left,
7715                        int shCount, int sign)
7716 {
7717   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7718   /* if shCount >= 8 */
7719   if (shCount >= 8) {
7720     shCount -= 8 ;
7721     if (shCount)
7722       shiftR1Left2Result(left, MSB16, result, LSB,
7723                          shCount, sign);
7724     else
7725       movLeft2Result(left, MSB16, result, LSB);
7726
7727     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7728
7729     if(sign) {
7730       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7731       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
7732     }
7733   }
7734
7735   /*  1 <= shCount <= 7 */
7736   else
7737     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7738 }
7739
7740 /*-----------------------------------------------------------------*/
7741 /* shiftRLong - shift right one long from left to result           */
7742 /* offl = LSB or MSB16                                             */
7743 /*-----------------------------------------------------------------*/
7744 static void shiftRLong (operand *left, int offl,
7745                         operand *result, int sign)
7746 {
7747     int size = AOP_SIZE(result);
7748     int same = pic16_sameRegs(AOP(left),AOP(result));
7749     int i;
7750     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7751
7752         if (same && (offl == MSB16)) { //shift one byte right
7753                 for(i=MSB16;i<size;i++) {
7754                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7755                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7756                 }
7757         }
7758
7759     if(sign)
7760                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7761         else
7762                 emitCLRC;
7763
7764         if (same) {
7765                 if (offl == LSB)
7766                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7767         } else {
7768         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7769         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7770         }
7771
7772     if(offl == MSB16) {
7773         /* add sign of "a" */
7774         pic16_addSign(result, MSB32, sign);
7775         }
7776
7777         if (same) {
7778         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7779         } else {
7780         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7781         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7782         }
7783         
7784         if (same) {
7785         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7786         } else {
7787         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7788         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7789         }
7790
7791         if (same) {
7792         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7793         } else {
7794         if(offl == LSB){
7795                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7796                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7797         }
7798         }
7799 }
7800
7801 /*-----------------------------------------------------------------*/
7802 /* genrshFour - shift four byte by a known amount != 0             */
7803 /*-----------------------------------------------------------------*/
7804 static void genrshFour (operand *result, operand *left,
7805                         int shCount, int sign)
7806 {
7807   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7808   /* if shifting more that 3 bytes */
7809   if(shCount >= 24 ) {
7810     shCount -= 24;
7811     if(shCount)
7812       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7813     else
7814       movLeft2Result(left, MSB32, result, LSB);
7815
7816     pic16_addSign(result, MSB16, sign);
7817   }
7818   else if(shCount >= 16){
7819     shCount -= 16;
7820     if(shCount)
7821       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7822     else{
7823       movLeft2Result(left, MSB24, result, LSB);
7824       movLeft2Result(left, MSB32, result, MSB16);
7825     }
7826     pic16_addSign(result, MSB24, sign);
7827   }
7828   else if(shCount >= 8){
7829     shCount -= 8;
7830     if(shCount == 1)
7831       shiftRLong(left, MSB16, result, sign);
7832     else if(shCount == 0){
7833       movLeft2Result(left, MSB16, result, LSB);
7834       movLeft2Result(left, MSB24, result, MSB16);
7835       movLeft2Result(left, MSB32, result, MSB24);
7836       pic16_addSign(result, MSB32, sign);
7837     }
7838     else{ //shcount >= 2
7839       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7840       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7841       /* the last shift is signed */
7842       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7843       pic16_addSign(result, MSB32, sign);
7844     }
7845   }
7846   else{   /* 1 <= shCount <= 7 */
7847     if(shCount <= 2){
7848       shiftRLong(left, LSB, result, sign);
7849       if(shCount == 2)
7850         shiftRLong(result, LSB, result, sign);
7851     }
7852     else{
7853       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7854       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7855       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7856     }
7857   }
7858 }
7859
7860 /*-----------------------------------------------------------------*/
7861 /* genRightShiftLiteral - right shifting by known count            */
7862 /*-----------------------------------------------------------------*/
7863 static void genRightShiftLiteral (operand *left,
7864                                   operand *right,
7865                                   operand *result,
7866                                   iCode *ic,
7867                                   int sign)
7868 {    
7869   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7870   int lsize,res_size;
7871
7872   pic16_freeAsmop(right,NULL,ic,TRUE);
7873
7874   pic16_aopOp(left,ic,FALSE);
7875   pic16_aopOp(result,ic,FALSE);
7876
7877   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7878
7879 #if VIEW_SIZE
7880   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7881                  AOP_SIZE(left));
7882 #endif
7883
7884   lsize = pic16_getDataSize(left);
7885   res_size = pic16_getDataSize(result);
7886   /* test the LEFT size !!! */
7887
7888   /* I suppose that the left size >= result size */
7889   if(shCount == 0){
7890     while(res_size--)
7891       movLeft2Result(left, lsize, result, res_size);
7892   }
7893
7894   else if(shCount >= (lsize * 8)){
7895
7896     if(res_size == 1) {
7897       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
7898       if(sign) {
7899         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7900         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
7901       }
7902     } else {
7903
7904       if(sign) {
7905         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7906         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7907         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7908         while(res_size--)
7909           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
7910
7911       } else {
7912
7913         while(res_size--)
7914           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
7915       }
7916     }
7917   } else {
7918
7919     switch (res_size) {
7920     case 1:
7921       genrshOne (result,left,shCount,sign);
7922       break;
7923
7924     case 2:
7925       genrshTwo (result,left,shCount,sign);
7926       break;
7927
7928     case 4:
7929       genrshFour (result,left,shCount,sign);
7930       break;
7931     default :
7932       break;
7933     }
7934
7935   }
7936
7937   pic16_freeAsmop(left,NULL,ic,TRUE);
7938   pic16_freeAsmop(result,NULL,ic,TRUE);
7939 }
7940
7941 /*-----------------------------------------------------------------*/
7942 /* genSignedRightShift - right shift of signed number              */
7943 /*-----------------------------------------------------------------*/
7944 static void genSignedRightShift (iCode *ic)
7945 {
7946   operand *right, *left, *result;
7947   int size, offset;
7948   //  char *l;
7949   symbol *tlbl, *tlbl1 ;
7950   pCodeOp *pctemp;
7951
7952   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7953
7954   /* we do it the hard way put the shift count in b
7955      and loop thru preserving the sign */
7956   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7957
7958   right = IC_RIGHT(ic);
7959   left  = IC_LEFT(ic);
7960   result = IC_RESULT(ic);
7961
7962   pic16_aopOp(right,ic,FALSE);  
7963   pic16_aopOp(left,ic,FALSE);
7964   pic16_aopOp(result,ic,FALSE);
7965
7966
7967   if ( AOP_TYPE(right) == AOP_LIT) {
7968     genRightShiftLiteral (left,right,result,ic,1);
7969     return ;
7970   }
7971   /* shift count is unknown then we have to form 
7972      a loop get the loop count in B : Note: we take
7973      only the lower order byte since shifting
7974      more that 32 bits make no sense anyway, ( the
7975      largest size of an object can be only 32 bits ) */  
7976
7977   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7978   //pic16_emitcode("inc","b");
7979   //pic16_freeAsmop (right,NULL,ic,TRUE);
7980   //pic16_aopOp(left,ic,FALSE);
7981   //pic16_aopOp(result,ic,FALSE);
7982
7983   /* now move the left to the result if they are not the
7984      same */
7985   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7986       AOP_SIZE(result) > 1) {
7987
7988     size = AOP_SIZE(result);
7989     offset=0;
7990     while (size--) { 
7991       /*
7992         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7993         if (*l == '@' && IS_AOP_PREG(result)) {
7994
7995         pic16_emitcode("mov","a,%s",l);
7996         pic16_aopPut(AOP(result),"a",offset);
7997         } else
7998         pic16_aopPut(AOP(result),l,offset);
7999       */
8000       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8001       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8002
8003       offset++;
8004     }
8005   }
8006
8007   /* mov the highest order bit to OVR */    
8008   tlbl = newiTempLabel(NULL);
8009   tlbl1= newiTempLabel(NULL);
8010
8011   size = AOP_SIZE(result);
8012   offset = size - 1;
8013
8014   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8015
8016   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8017
8018   /* offset should be 0, 1 or 3 */
8019   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8020   emitSKPNZ;
8021   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8022
8023   pic16_emitpcode(POC_MOVWF, pctemp);
8024
8025
8026   pic16_emitpLabel(tlbl->key);
8027
8028   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8029   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8030
8031   while(--size) {
8032     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8033   }
8034
8035   pic16_emitpcode(POC_DECFSZ,  pctemp);
8036   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8037   pic16_emitpLabel(tlbl1->key);
8038
8039   pic16_popReleaseTempReg(pctemp);
8040 #if 0
8041   size = AOP_SIZE(result);
8042   offset = size - 1;
8043   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8044   pic16_emitcode("rlc","a");
8045   pic16_emitcode("mov","ov,c");
8046   /* if it is only one byte then */
8047   if (size == 1) {
8048     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8049     MOVA(l);
8050     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8051     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8052     pic16_emitcode("mov","c,ov");
8053     pic16_emitcode("rrc","a");
8054     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8055     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8056     pic16_aopPut(AOP(result),"a",0);
8057     goto release ;
8058   }
8059
8060   reAdjustPreg(AOP(result));
8061   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8062   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8063   pic16_emitcode("mov","c,ov");
8064   while (size--) {
8065     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8066     MOVA(l);
8067     pic16_emitcode("rrc","a");         
8068     pic16_aopPut(AOP(result),"a",offset--);
8069   }
8070   reAdjustPreg(AOP(result));
8071   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8072   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8073
8074  release:
8075 #endif
8076
8077   pic16_freeAsmop(left,NULL,ic,TRUE);
8078   pic16_freeAsmop(result,NULL,ic,TRUE);
8079   pic16_freeAsmop(right,NULL,ic,TRUE);
8080 }
8081
8082 /*-----------------------------------------------------------------*/
8083 /* genRightShift - generate code for right shifting                */
8084 /*-----------------------------------------------------------------*/
8085 static void genRightShift (iCode *ic)
8086 {
8087     operand *right, *left, *result;
8088     sym_link *letype ;
8089     int size, offset;
8090     char *l;
8091     symbol *tlbl, *tlbl1 ;
8092
8093     /* if signed then we do it the hard way preserve the
8094     sign bit moving it inwards */
8095     letype = getSpec(operandType(IC_LEFT(ic)));
8096     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8097
8098     if (!SPEC_USIGN(letype)) {
8099         genSignedRightShift (ic);
8100         return ;
8101     }
8102
8103     /* signed & unsigned types are treated the same : i.e. the
8104     signed is NOT propagated inwards : quoting from the
8105     ANSI - standard : "for E1 >> E2, is equivalent to division
8106     by 2**E2 if unsigned or if it has a non-negative value,
8107     otherwise the result is implementation defined ", MY definition
8108     is that the sign does not get propagated */
8109
8110     right = IC_RIGHT(ic);
8111     left  = IC_LEFT(ic);
8112     result = IC_RESULT(ic);
8113
8114     pic16_aopOp(right,ic,FALSE);
8115
8116     /* if the shift count is known then do it 
8117     as efficiently as possible */
8118     if (AOP_TYPE(right) == AOP_LIT) {
8119         genRightShiftLiteral (left,right,result,ic, 0);
8120         return ;
8121     }
8122
8123     /* shift count is unknown then we have to form 
8124     a loop get the loop count in B : Note: we take
8125     only the lower order byte since shifting
8126     more that 32 bits make no sense anyway, ( the
8127     largest size of an object can be only 32 bits ) */  
8128
8129     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8130     pic16_emitcode("inc","b");
8131     pic16_aopOp(left,ic,FALSE);
8132     pic16_aopOp(result,ic,FALSE);
8133
8134     /* now move the left to the result if they are not the
8135     same */
8136     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8137         AOP_SIZE(result) > 1) {
8138
8139         size = AOP_SIZE(result);
8140         offset=0;
8141         while (size--) {
8142             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8143             if (*l == '@' && IS_AOP_PREG(result)) {
8144
8145                 pic16_emitcode("mov","a,%s",l);
8146                 pic16_aopPut(AOP(result),"a",offset);
8147             } else
8148                 pic16_aopPut(AOP(result),l,offset);
8149             offset++;
8150         }
8151     }
8152
8153     tlbl = newiTempLabel(NULL);
8154     tlbl1= newiTempLabel(NULL);
8155     size = AOP_SIZE(result);
8156     offset = size - 1;
8157
8158     /* if it is only one byte then */
8159     if (size == 1) {
8160
8161       tlbl = newiTempLabel(NULL);
8162       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8163         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8164         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8165       }
8166
8167       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8168       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8169       pic16_emitpLabel(tlbl->key);
8170       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8171       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8172       emitSKPC;
8173       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8174
8175       goto release ;
8176     }
8177
8178     reAdjustPreg(AOP(result));
8179     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8180     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8181     CLRC;
8182     while (size--) {
8183         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8184         MOVA(l);
8185         pic16_emitcode("rrc","a");         
8186         pic16_aopPut(AOP(result),"a",offset--);
8187     }
8188     reAdjustPreg(AOP(result));
8189
8190     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8191     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8192
8193 release:
8194     pic16_freeAsmop(left,NULL,ic,TRUE);
8195     pic16_freeAsmop (right,NULL,ic,TRUE);
8196     pic16_freeAsmop(result,NULL,ic,TRUE);
8197 }
8198
8199 /*-----------------------------------------------------------------*/
8200 /* genUnpackBits - generates code for unpacking bits               */
8201 /*-----------------------------------------------------------------*/
8202 static void genUnpackBits (operand *result, char *rname, int ptype)
8203 {    
8204     int shCnt ;
8205     int rlen = 0 ;
8206     sym_link *etype;
8207     int offset = 0 ;
8208
8209     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8210     etype = getSpec(operandType(result));
8211
8212     /* read the first byte  */
8213     switch (ptype) {
8214
8215     case POINTER:
8216     case IPOINTER:
8217         pic16_emitcode("mov","a,@%s",rname);
8218         break;
8219         
8220     case PPOINTER:
8221         pic16_emitcode("movx","a,@%s",rname);
8222         break;
8223         
8224     case FPOINTER:
8225         pic16_emitcode("movx","a,@dptr");
8226         break;
8227
8228     case CPOINTER:
8229         pic16_emitcode("clr","a");
8230         pic16_emitcode("movc","a","@a+dptr");
8231         break;
8232
8233     case GPOINTER:
8234         pic16_emitcode("lcall","__gptrget");
8235         break;
8236     }
8237
8238     /* if we have bitdisplacement then it fits   */
8239     /* into this byte completely or if length is */
8240     /* less than a byte                          */
8241     if ((shCnt = SPEC_BSTR(etype)) || 
8242         (SPEC_BLEN(etype) <= 8))  {
8243
8244         /* shift right acc */
8245         AccRsh(shCnt);
8246
8247         pic16_emitcode("anl","a,#0x%02x",
8248                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8249         pic16_aopPut(AOP(result),"a",offset);
8250         return ;
8251     }
8252
8253     /* bit field did not fit in a byte  */
8254     rlen = SPEC_BLEN(etype) - 8;
8255     pic16_aopPut(AOP(result),"a",offset++);
8256
8257     while (1)  {
8258
8259         switch (ptype) {
8260         case POINTER:
8261         case IPOINTER:
8262             pic16_emitcode("inc","%s",rname);
8263             pic16_emitcode("mov","a,@%s",rname);
8264             break;
8265             
8266         case PPOINTER:
8267             pic16_emitcode("inc","%s",rname);
8268             pic16_emitcode("movx","a,@%s",rname);
8269             break;
8270
8271         case FPOINTER:
8272             pic16_emitcode("inc","dptr");
8273             pic16_emitcode("movx","a,@dptr");
8274             break;
8275             
8276         case CPOINTER:
8277             pic16_emitcode("clr","a");
8278             pic16_emitcode("inc","dptr");
8279             pic16_emitcode("movc","a","@a+dptr");
8280             break;
8281             
8282         case GPOINTER:
8283             pic16_emitcode("inc","dptr");
8284             pic16_emitcode("lcall","__gptrget");
8285             break;
8286         }
8287
8288         rlen -= 8;            
8289         /* if we are done */
8290         if ( rlen <= 0 )
8291             break ;
8292         
8293         pic16_aopPut(AOP(result),"a",offset++);
8294                               
8295     }
8296     
8297     if (rlen) {
8298         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8299         pic16_aopPut(AOP(result),"a",offset);          
8300     }
8301     
8302     return ;
8303 }
8304
8305 #if 0
8306 /*-----------------------------------------------------------------*/
8307 /* genDataPointerGet - generates code when ptr offset is known     */
8308 /*-----------------------------------------------------------------*/
8309 static void genDataPointerGet (operand *left, 
8310                                operand *result, 
8311                                iCode *ic)
8312 {
8313   int size , offset = 0;
8314
8315
8316   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8317
8318
8319   /* optimization - most of the time, left and result are the same
8320    * address, but different types. for the pic code, we could omit
8321    * the following
8322    */
8323
8324   pic16_aopOp(result,ic,TRUE);
8325
8326   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8327
8328   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8329
8330   size = AOP_SIZE(result);
8331
8332   while (size--) {
8333     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8334     offset++;
8335   }
8336
8337   pic16_freeAsmop(left,NULL,ic,TRUE);
8338   pic16_freeAsmop(result,NULL,ic,TRUE);
8339 }
8340 #endif
8341 /*-----------------------------------------------------------------*/
8342 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8343 /*-----------------------------------------------------------------*/
8344 static void genNearPointerGet (operand *left, 
8345                                operand *result, 
8346                                iCode *ic)
8347 {
8348     asmop *aop = NULL;
8349     //regs *preg = NULL ;
8350     char *rname ;
8351     sym_link *rtype, *retype;
8352     sym_link *ltype = operandType(left);    
8353     //char buffer[80];
8354
8355     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8356
8357     rtype = operandType(result);
8358     retype= getSpec(rtype);
8359     
8360     pic16_aopOp(left,ic,FALSE);
8361     
8362     /* if left is rematerialisable and
8363        result is not bit variable type and
8364        the left is pointer to data space i.e
8365        lower 128 bytes of space */
8366     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8367         !IS_BITVAR(retype)         &&
8368         DCL_TYPE(ltype) == POINTER) {
8369       //genDataPointerGet (left,result,ic);
8370         return ;
8371     }
8372     
8373     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8374
8375         /* if the value is already in a pointer register
8376        then don't need anything more */
8377     if (!AOP_INPREG(AOP(left))) {
8378         /* otherwise get a free pointer register */
8379     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8380 /*
8381         aop = newAsmop(0);
8382         preg = getFreePtr(ic,&aop,FALSE);
8383         pic16_emitcode("mov","%s,%s",
8384                 preg->name,
8385                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8386         rname = preg->name ;
8387 */
8388     rname ="BAD";
8389     } else
8390         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8391     
8392     pic16_aopOp (result,ic,FALSE);
8393     
8394       /* if bitfield then unpack the bits */
8395     if (IS_BITFIELD(retype)) 
8396         genUnpackBits (result,rname,POINTER);
8397     else {
8398         /* we have can just get the values */
8399       int size = AOP_SIZE(result);
8400       int offset = 0 ;  
8401         
8402       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8403
8404       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8405       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8406       while(size--) {
8407         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8408         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8409         if(size)
8410           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8411       }
8412 /*
8413         while (size--) {
8414             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8415
8416                 pic16_emitcode("mov","a,@%s",rname);
8417                 pic16_aopPut(AOP(result),"a",offset);
8418             } else {
8419                 sprintf(buffer,"@%s",rname);
8420                 pic16_aopPut(AOP(result),buffer,offset);
8421             }
8422             offset++ ;
8423             if (size)
8424                 pic16_emitcode("inc","%s",rname);
8425         }
8426 */
8427     }
8428
8429     /* now some housekeeping stuff */
8430     if (aop) {
8431         /* we had to allocate for this iCode */
8432     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8433         pic16_freeAsmop(NULL,aop,ic,TRUE);
8434     } else { 
8435         /* we did not allocate which means left
8436            already in a pointer register, then
8437            if size > 0 && this could be used again
8438            we have to point it back to where it 
8439            belongs */
8440     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8441         if (AOP_SIZE(result) > 1 &&
8442             !OP_SYMBOL(left)->remat &&
8443             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8444               ic->depth )) {
8445             int size = AOP_SIZE(result) - 1;
8446             while (size--)
8447                 pic16_emitcode("dec","%s",rname);
8448         }
8449     }
8450
8451     /* done */
8452     pic16_freeAsmop(left,NULL,ic,TRUE);
8453     pic16_freeAsmop(result,NULL,ic,TRUE);
8454      
8455 }
8456
8457 /*-----------------------------------------------------------------*/
8458 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8459 /*-----------------------------------------------------------------*/
8460 static void genPagedPointerGet (operand *left, 
8461                                operand *result, 
8462                                iCode *ic)
8463 {
8464     asmop *aop = NULL;
8465     regs *preg = NULL ;
8466     char *rname ;
8467     sym_link *rtype, *retype;    
8468
8469     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8470
8471     rtype = operandType(result);
8472     retype= getSpec(rtype);
8473     
8474     pic16_aopOp(left,ic,FALSE);
8475
8476   /* if the value is already in a pointer register
8477        then don't need anything more */
8478     if (!AOP_INPREG(AOP(left))) {
8479         /* otherwise get a free pointer register */
8480         aop = newAsmop(0);
8481         preg = getFreePtr(ic,&aop,FALSE);
8482         pic16_emitcode("mov","%s,%s",
8483                 preg->name,
8484                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8485         rname = preg->name ;
8486     } else
8487         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8488     
8489     pic16_freeAsmop(left,NULL,ic,TRUE);
8490     pic16_aopOp (result,ic,FALSE);
8491
8492     /* if bitfield then unpack the bits */
8493     if (IS_BITFIELD(retype)) 
8494         genUnpackBits (result,rname,PPOINTER);
8495     else {
8496         /* we have can just get the values */
8497         int size = AOP_SIZE(result);
8498         int offset = 0 ;        
8499         
8500         while (size--) {
8501             
8502             pic16_emitcode("movx","a,@%s",rname);
8503             pic16_aopPut(AOP(result),"a",offset);
8504             
8505             offset++ ;
8506             
8507             if (size)
8508                 pic16_emitcode("inc","%s",rname);
8509         }
8510     }
8511
8512     /* now some housekeeping stuff */
8513     if (aop) {
8514         /* we had to allocate for this iCode */
8515         pic16_freeAsmop(NULL,aop,ic,TRUE);
8516     } else { 
8517         /* we did not allocate which means left
8518            already in a pointer register, then
8519            if size > 0 && this could be used again
8520            we have to point it back to where it 
8521            belongs */
8522         if (AOP_SIZE(result) > 1 &&
8523             !OP_SYMBOL(left)->remat &&
8524             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8525               ic->depth )) {
8526             int size = AOP_SIZE(result) - 1;
8527             while (size--)
8528                 pic16_emitcode("dec","%s",rname);
8529         }
8530     }
8531
8532     /* done */
8533     pic16_freeAsmop(result,NULL,ic,TRUE);
8534     
8535         
8536 }
8537
8538 /*-----------------------------------------------------------------*/
8539 /* genFarPointerGet - gget value from far space                    */
8540 /*-----------------------------------------------------------------*/
8541 static void genFarPointerGet (operand *left,
8542                               operand *result, iCode *ic)
8543 {
8544     int size, offset ;
8545     sym_link *retype = getSpec(operandType(result));
8546
8547     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8548
8549     pic16_aopOp(left,ic,FALSE);
8550
8551     /* if the operand is already in dptr 
8552     then we do nothing else we move the value to dptr */
8553     if (AOP_TYPE(left) != AOP_STR) {
8554         /* if this is remateriazable */
8555         if (AOP_TYPE(left) == AOP_IMMD)
8556             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8557         else { /* we need to get it byte by byte */
8558             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8559             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8560             if (options.model == MODEL_FLAT24)
8561             {
8562                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8563             }
8564         }
8565     }
8566     /* so dptr know contains the address */
8567     pic16_freeAsmop(left,NULL,ic,TRUE);
8568     pic16_aopOp(result,ic,FALSE);
8569
8570     /* if bit then unpack */
8571     if (IS_BITFIELD(retype)) 
8572         genUnpackBits(result,"dptr",FPOINTER);
8573     else {
8574         size = AOP_SIZE(result);
8575         offset = 0 ;
8576
8577         while (size--) {
8578             pic16_emitcode("movx","a,@dptr");
8579             pic16_aopPut(AOP(result),"a",offset++);
8580             if (size)
8581                 pic16_emitcode("inc","dptr");
8582         }
8583     }
8584
8585     pic16_freeAsmop(result,NULL,ic,TRUE);
8586 }
8587 #if 0
8588 /*-----------------------------------------------------------------*/
8589 /* genCodePointerGet - get value from code space                  */
8590 /*-----------------------------------------------------------------*/
8591 static void genCodePointerGet (operand *left,
8592                                 operand *result, iCode *ic)
8593 {
8594     int size, offset ;
8595     sym_link *retype = getSpec(operandType(result));
8596
8597     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8598
8599     pic16_aopOp(left,ic,FALSE);
8600
8601     /* if the operand is already in dptr 
8602     then we do nothing else we move the value to dptr */
8603     if (AOP_TYPE(left) != AOP_STR) {
8604         /* if this is remateriazable */
8605         if (AOP_TYPE(left) == AOP_IMMD)
8606             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8607         else { /* we need to get it byte by byte */
8608             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8609             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8610             if (options.model == MODEL_FLAT24)
8611             {
8612                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8613             }
8614         }
8615     }
8616     /* so dptr know contains the address */
8617     pic16_freeAsmop(left,NULL,ic,TRUE);
8618     pic16_aopOp(result,ic,FALSE);
8619
8620     /* if bit then unpack */
8621     if (IS_BITFIELD(retype)) 
8622         genUnpackBits(result,"dptr",CPOINTER);
8623     else {
8624         size = AOP_SIZE(result);
8625         offset = 0 ;
8626
8627         while (size--) {
8628             pic16_emitcode("clr","a");
8629             pic16_emitcode("movc","a,@a+dptr");
8630             pic16_aopPut(AOP(result),"a",offset++);
8631             if (size)
8632                 pic16_emitcode("inc","dptr");
8633         }
8634     }
8635
8636     pic16_freeAsmop(result,NULL,ic,TRUE);
8637 }
8638 #endif
8639 /*-----------------------------------------------------------------*/
8640 /* genGenPointerGet - gget value from generic pointer space        */
8641 /*-----------------------------------------------------------------*/
8642 static void genGenPointerGet (operand *left,
8643                               operand *result, iCode *ic)
8644 {
8645         int size, offset, lit;
8646         sym_link *retype = getSpec(operandType(result));
8647
8648         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8649         pic16_aopOp(left,ic,FALSE);
8650         pic16_aopOp(result,ic,FALSE);
8651         size = AOP_SIZE(result);
8652
8653         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8654
8655         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
8656
8657                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
8658                 // load FSR0 from immediate
8659                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
8660                 offset = 0;
8661                 while(size--) {
8662                         if(size) {
8663                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
8664                         } else {
8665                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
8666                         }
8667                         offset++;
8668                 }
8669                 goto release;
8670
8671         }
8672         else { /* we need to get it byte by byte */
8673                 // set up FSR0 with address from left
8674                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
8675                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
8676
8677                 offset = 0 ;
8678
8679                 while(size--) {
8680                         if(size) {
8681                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
8682                         } else {
8683                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
8684                         }
8685                         offset++;
8686                 }
8687                 goto release;
8688         }
8689
8690   /* if bit then unpack */
8691         if (IS_BITFIELD(retype)) 
8692                 genUnpackBits(result,"BAD",GPOINTER);
8693
8694         release:
8695         pic16_freeAsmop(left,NULL,ic,TRUE);
8696         pic16_freeAsmop(result,NULL,ic,TRUE);
8697
8698 }
8699
8700 /*-----------------------------------------------------------------*/
8701 /* genConstPointerGet - get value from const generic pointer space */
8702 /*-----------------------------------------------------------------*/
8703 static void genConstPointerGet (operand *left,
8704                                 operand *result, iCode *ic)
8705 {
8706   //sym_link *retype = getSpec(operandType(result));
8707   symbol *albl = newiTempLabel(NULL);
8708   symbol *blbl = newiTempLabel(NULL);
8709   PIC_OPCODE poc;
8710
8711   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8712   pic16_aopOp(left,ic,FALSE);
8713   pic16_aopOp(result,ic,FALSE);
8714
8715
8716   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8717
8718   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8719
8720   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
8721   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
8722   pic16_emitpLabel(albl->key);
8723
8724   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8725     
8726   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
8727   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
8728   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
8729   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
8730   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
8731
8732   pic16_emitpLabel(blbl->key);
8733
8734   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
8735
8736
8737   pic16_freeAsmop(left,NULL,ic,TRUE);
8738   pic16_freeAsmop(result,NULL,ic,TRUE);
8739
8740 }
8741 /*-----------------------------------------------------------------*/
8742 /* genPointerGet - generate code for pointer get                   */
8743 /*-----------------------------------------------------------------*/
8744 static void genPointerGet (iCode *ic)
8745 {
8746     operand *left, *result ;
8747     sym_link *type, *etype;
8748     int p_type;
8749
8750     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8751
8752     left = IC_LEFT(ic);
8753     result = IC_RESULT(ic) ;
8754
8755     /* depending on the type of pointer we need to
8756     move it to the correct pointer register */
8757     type = operandType(left);
8758     etype = getSpec(type);
8759
8760 #if 0
8761     if (IS_PTR_CONST(type))
8762 #else
8763     if (IS_CODEPTR(type))
8764 #endif
8765       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8766
8767     /* if left is of type of pointer then it is simple */
8768     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8769         p_type = DCL_TYPE(type);
8770     else {
8771         /* we have to go by the storage class */
8772         p_type = PTR_TYPE(SPEC_OCLS(etype));
8773
8774         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8775
8776         if (SPEC_OCLS(etype)->codesp ) {
8777           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8778           //p_type = CPOINTER ; 
8779         }
8780         else
8781             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8782               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8783                /*p_type = FPOINTER ;*/ 
8784             else
8785                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8786                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8787 /*                  p_type = PPOINTER; */
8788                 else
8789                     if (SPEC_OCLS(etype) == idata )
8790                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8791 /*                      p_type = IPOINTER; */
8792                     else
8793                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8794 /*                      p_type = POINTER ; */
8795     }
8796
8797     /* now that we have the pointer type we assign
8798     the pointer values */
8799     switch (p_type) {
8800
8801     case POINTER:       
8802     case IPOINTER:
8803         genNearPointerGet (left,result,ic);
8804         break;
8805
8806     case PPOINTER:
8807         genPagedPointerGet(left,result,ic);
8808         break;
8809
8810     case FPOINTER:
8811         genFarPointerGet (left,result,ic);
8812         break;
8813
8814     case CPOINTER:
8815         genConstPointerGet (left,result,ic);
8816         //pic16_emitcodePointerGet (left,result,ic);
8817         break;
8818
8819     case GPOINTER:
8820 #if 0
8821       if (IS_PTR_CONST(type))
8822         genConstPointerGet (left,result,ic);
8823       else
8824 #endif
8825         genGenPointerGet (left,result,ic);
8826       break;
8827     }
8828
8829 }
8830
8831 /*-----------------------------------------------------------------*/
8832 /* genPackBits - generates code for packed bit storage             */
8833 /*-----------------------------------------------------------------*/
8834 static void genPackBits (sym_link    *etype ,
8835                          operand *right ,
8836                          char *rname, int p_type)
8837 {
8838     int shCount = 0 ;
8839     int offset = 0  ;
8840     int rLen = 0 ;
8841     int blen, bstr ;   
8842     char *l ;
8843
8844     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8845     blen = SPEC_BLEN(etype);
8846     bstr = SPEC_BSTR(etype);
8847
8848     l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8849     MOVA(l);   
8850
8851     /* if the bit lenth is less than or    */
8852     /* it exactly fits a byte then         */
8853     if (SPEC_BLEN(etype) <= 8 )  {
8854         shCount = SPEC_BSTR(etype) ;
8855
8856         /* shift left acc */
8857         AccLsh(shCount);
8858
8859         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8860
8861
8862             switch (p_type) {
8863                 case POINTER:
8864                     pic16_emitcode ("mov","b,a");
8865                     pic16_emitcode("mov","a,@%s",rname);
8866                     break;
8867
8868                 case FPOINTER:
8869                     pic16_emitcode ("mov","b,a");
8870                     pic16_emitcode("movx","a,@dptr");
8871                     break;
8872
8873                 case GPOINTER:
8874                     pic16_emitcode ("push","b");
8875                     pic16_emitcode ("push","acc");
8876                     pic16_emitcode ("lcall","__gptrget");
8877                     pic16_emitcode ("pop","b");
8878                     break;
8879             }
8880
8881             pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
8882                       ((unsigned char)(0xFF << (blen+bstr)) | 
8883                        (unsigned char)(0xFF >> (8-bstr)) ) );
8884             pic16_emitcode ("orl","a,b");
8885             if (p_type == GPOINTER)
8886                 pic16_emitcode("pop","b");
8887         }
8888     }
8889
8890     switch (p_type) {
8891         case POINTER:
8892             pic16_emitcode("mov","@%s,a",rname);
8893             break;
8894
8895         case FPOINTER:
8896             pic16_emitcode("movx","@dptr,a");
8897             break;
8898
8899         case GPOINTER:
8900             DEBUGpic16_emitcode(";lcall","__gptrput");
8901             break;
8902     }
8903
8904     /* if we r done */
8905     if ( SPEC_BLEN(etype) <= 8 )
8906         return ;
8907
8908     pic16_emitcode("inc","%s",rname);
8909     rLen = SPEC_BLEN(etype) ;     
8910
8911     /* now generate for lengths greater than one byte */
8912     while (1) {
8913
8914         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
8915
8916         rLen -= 8 ;
8917         if (rLen <= 0 )
8918             break ;
8919
8920         switch (p_type) {
8921             case POINTER:
8922                 if (*l == '@') {
8923                     MOVA(l);
8924                     pic16_emitcode("mov","@%s,a",rname);
8925                 } else
8926                     pic16_emitcode("mov","@%s,%s",rname,l);
8927                 break;
8928
8929             case FPOINTER:
8930                 MOVA(l);
8931                 pic16_emitcode("movx","@dptr,a");
8932                 break;
8933
8934             case GPOINTER:
8935                 MOVA(l);
8936                 DEBUGpic16_emitcode(";lcall","__gptrput");
8937                 break;  
8938         }   
8939         pic16_emitcode ("inc","%s",rname);
8940     }
8941
8942     MOVA(l);
8943
8944     /* last last was not complete */
8945     if (rLen)   {
8946         /* save the byte & read byte */
8947         switch (p_type) {
8948             case POINTER:
8949                 pic16_emitcode ("mov","b,a");
8950                 pic16_emitcode("mov","a,@%s",rname);
8951                 break;
8952
8953             case FPOINTER:
8954                 pic16_emitcode ("mov","b,a");
8955                 pic16_emitcode("movx","a,@dptr");
8956                 break;
8957
8958             case GPOINTER:
8959                 pic16_emitcode ("push","b");
8960                 pic16_emitcode ("push","acc");
8961                 pic16_emitcode ("lcall","__gptrget");
8962                 pic16_emitcode ("pop","b");
8963                 break;
8964         }
8965
8966         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8967         pic16_emitcode ("orl","a,b");
8968     }
8969
8970     if (p_type == GPOINTER)
8971         pic16_emitcode("pop","b");
8972
8973     switch (p_type) {
8974
8975     case POINTER:
8976         pic16_emitcode("mov","@%s,a",rname);
8977         break;
8978         
8979     case FPOINTER:
8980         pic16_emitcode("movx","@dptr,a");
8981         break;
8982         
8983     case GPOINTER:
8984         DEBUGpic16_emitcode(";lcall","__gptrput");
8985         break;                  
8986     }
8987 }
8988 /*-----------------------------------------------------------------*/
8989 /* genDataPointerSet - remat pointer to data space                 */
8990 /*-----------------------------------------------------------------*/
8991 static void genDataPointerSet(operand *right,
8992                               operand *result,
8993                               iCode *ic)
8994 {
8995     int size, offset = 0 ;
8996     char *l, buffer[256];
8997
8998     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8999     pic16_aopOp(right,ic,FALSE);
9000     
9001     l = pic16_aopGet(AOP(result),0,FALSE,TRUE);
9002     size = AOP_SIZE(right);
9003 /*
9004     if ( AOP_TYPE(result) == AOP_PCODE) {
9005       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9006               AOP(result)->aopu.pcop->name,
9007               PCOI(AOP(result)->aopu.pcop)->offset);
9008     }
9009 */
9010
9011     // tsd, was l+1 - the underline `_' prefix was being stripped
9012     while (size--) {
9013       if (offset) {
9014         sprintf(buffer,"(%s + %d)",l,offset);
9015         fprintf(stderr,"%s:%d: oops  %s\n",__FILE__, __LINE__, buffer);
9016       } else
9017         sprintf(buffer,"%s",l);
9018
9019         if (AOP_TYPE(right) == AOP_LIT) {
9020           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9021           lit = lit >> (8*offset);
9022           if(lit&0xff) {
9023             pic16_emitcode("movlw","%d",lit);
9024             pic16_emitcode("movwf","%s",buffer);
9025
9026             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9027             //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
9028             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9029
9030           } else {
9031             pic16_emitcode("clrf","%s",buffer);
9032             //pic16_emitpcode(POC_CLRF, pic16_popRegFromString(buffer));
9033             pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
9034           }
9035         }else {
9036           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
9037           pic16_emitcode("movwf","%s",buffer);
9038
9039           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9040           //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
9041           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9042
9043         }
9044
9045         offset++;
9046     }
9047
9048     pic16_freeAsmop(right,NULL,ic,TRUE);
9049     pic16_freeAsmop(result,NULL,ic,TRUE);
9050 }
9051
9052 /*-----------------------------------------------------------------*/
9053 /* genNearPointerSet - pic16_emitcode for near pointer put                */
9054 /*-----------------------------------------------------------------*/
9055 static void genNearPointerSet (operand *right,
9056                                operand *result, 
9057                                iCode *ic)
9058 {
9059   asmop *aop = NULL;
9060   char *l;
9061   sym_link *retype;
9062   sym_link *ptype = operandType(result);
9063
9064     
9065   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9066   retype= getSpec(operandType(right));
9067
9068   pic16_aopOp(result,ic,FALSE);
9069
9070     
9071   /* if the result is rematerializable &
9072      in data space & not a bit variable */
9073   //if (AOP_TYPE(result) == AOP_IMMD &&
9074   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
9075       DCL_TYPE(ptype) == POINTER   &&
9076       !IS_BITVAR(retype)) {
9077     genDataPointerSet (right,result,ic);
9078     pic16_freeAsmop(result,NULL,ic,TRUE);
9079     return;
9080   }
9081
9082   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9083   pic16_aopOp(right,ic,FALSE);
9084   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9085
9086   /* if the value is already in a pointer register
9087      then don't need anything more */
9088   if (!AOP_INPREG(AOP(result))) {
9089     /* otherwise get a free pointer register */
9090     //aop = newAsmop(0);
9091     //preg = getFreePtr(ic,&aop,FALSE);
9092     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9093     //pic16_emitcode("mov","%s,%s",
9094     //         preg->name,
9095     //         pic16_aopGet(AOP(result),0,FALSE,TRUE));
9096     //rname = preg->name ;
9097     //pic16_emitcode("movwf","fsr0");
9098     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0));
9099     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_fsr0));
9100     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9101     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9102     goto release;
9103
9104   }// else
9105 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9106
9107   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9108
9109   /* if bitfield then unpack the bits */
9110   if (IS_BITFIELD(retype)) {
9111     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9112            "The programmer is obviously confused");
9113 //      genPackBits (retype,right,"BAD",POINTER);
9114     exit(1);
9115   }
9116   else {
9117     /* we have can just get the values */
9118     int size = AOP_SIZE(right);
9119     int offset = 0 ;    
9120
9121     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9122     while (size--) {
9123       l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9124       if (*l == '@' ) {
9125         //MOVA(l);
9126         //pic16_emitcode("mov","@%s,a",rname);
9127         pic16_emitcode("movf","indf0,w ;1");
9128       } else {
9129
9130         if (AOP_TYPE(right) == AOP_LIT) {
9131           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9132           if(lit) {
9133             pic16_emitcode("movlw","%s",l);
9134             pic16_emitcode("movwf","indf0 ;2");
9135           } else 
9136             pic16_emitcode("clrf","indf0");
9137         }else {
9138           pic16_emitcode("movf","%s,w",l);
9139           pic16_emitcode("movwf","indf0 ;2");
9140         }
9141         //pic16_emitcode("mov","@%s,%s",rname,l);
9142       }
9143       if (size)
9144         pic16_emitcode("incf","fsr0,f ;3");
9145       //pic16_emitcode("inc","%s",rname);
9146       offset++;
9147     }
9148   }
9149
9150   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9151   /* now some housekeeping stuff */
9152   if (aop) {
9153     /* we had to allocate for this iCode */
9154     pic16_freeAsmop(NULL,aop,ic,TRUE);
9155   } else { 
9156     /* we did not allocate which means left
9157        already in a pointer register, then
9158        if size > 0 && this could be used again
9159        we have to point it back to where it 
9160        belongs */
9161     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9162     if (AOP_SIZE(right) > 1 &&
9163         !OP_SYMBOL(result)->remat &&
9164         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9165           ic->depth )) {
9166       int size = AOP_SIZE(right) - 1;
9167       while (size--)
9168         pic16_emitcode("decf","fsr0,f");
9169       //pic16_emitcode("dec","%s",rname);
9170     }
9171   }
9172
9173   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9174   /* done */
9175  release:
9176   pic16_freeAsmop(right,NULL,ic,TRUE);
9177   pic16_freeAsmop(result,NULL,ic,TRUE);
9178 }
9179
9180 /*-----------------------------------------------------------------*/
9181 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
9182 /*-----------------------------------------------------------------*/
9183 static void genPagedPointerSet (operand *right,
9184                                operand *result, 
9185                                iCode *ic)
9186 {
9187     asmop *aop = NULL;
9188     regs *preg = NULL ;
9189     char *rname , *l;
9190     sym_link *retype;
9191        
9192     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9193
9194     retype= getSpec(operandType(right));
9195     
9196     pic16_aopOp(result,ic,FALSE);
9197     
9198     /* if the value is already in a pointer register
9199        then don't need anything more */
9200     if (!AOP_INPREG(AOP(result))) {
9201         /* otherwise get a free pointer register */
9202         aop = newAsmop(0);
9203         preg = getFreePtr(ic,&aop,FALSE);
9204         pic16_emitcode("mov","%s,%s",
9205                 preg->name,
9206                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9207         rname = preg->name ;
9208     } else
9209         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9210     
9211     pic16_freeAsmop(result,NULL,ic,TRUE);
9212     pic16_aopOp (right,ic,FALSE);
9213
9214     /* if bitfield then unpack the bits */
9215     if (IS_BITFIELD(retype)) 
9216         genPackBits (retype,right,rname,PPOINTER);
9217     else {
9218         /* we have can just get the values */
9219         int size = AOP_SIZE(right);
9220         int offset = 0 ;        
9221         
9222         while (size--) {
9223             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9224             
9225             MOVA(l);
9226             pic16_emitcode("movx","@%s,a",rname);
9227
9228             if (size)
9229                 pic16_emitcode("inc","%s",rname);
9230
9231             offset++;
9232         }
9233     }
9234     
9235     /* now some housekeeping stuff */
9236     if (aop) {
9237         /* we had to allocate for this iCode */
9238         pic16_freeAsmop(NULL,aop,ic,TRUE);
9239     } else { 
9240         /* we did not allocate which means left
9241            already in a pointer register, then
9242            if size > 0 && this could be used again
9243            we have to point it back to where it 
9244            belongs */
9245         if (AOP_SIZE(right) > 1 &&
9246             !OP_SYMBOL(result)->remat &&
9247             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9248               ic->depth )) {
9249             int size = AOP_SIZE(right) - 1;
9250             while (size--)
9251                 pic16_emitcode("dec","%s",rname);
9252         }
9253     }
9254
9255     /* done */
9256     pic16_freeAsmop(right,NULL,ic,TRUE);
9257     
9258         
9259 }
9260
9261 /*-----------------------------------------------------------------*/
9262 /* genFarPointerSet - set value from far space                     */
9263 /*-----------------------------------------------------------------*/
9264 static void genFarPointerSet (operand *right,
9265                               operand *result, iCode *ic)
9266 {
9267     int size, offset ;
9268     sym_link *retype = getSpec(operandType(right));
9269
9270     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9271     pic16_aopOp(result,ic,FALSE);
9272
9273     /* if the operand is already in dptr 
9274     then we do nothing else we move the value to dptr */
9275     if (AOP_TYPE(result) != AOP_STR) {
9276         /* if this is remateriazable */
9277         if (AOP_TYPE(result) == AOP_IMMD)
9278             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9279         else { /* we need to get it byte by byte */
9280             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9281             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9282             if (options.model == MODEL_FLAT24)
9283             {
9284                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9285             }
9286         }
9287     }
9288     /* so dptr know contains the address */
9289     pic16_freeAsmop(result,NULL,ic,TRUE);
9290     pic16_aopOp(right,ic,FALSE);
9291
9292     /* if bit then unpack */
9293     if (IS_BITFIELD(retype)) 
9294         genPackBits(retype,right,"dptr",FPOINTER);
9295     else {
9296         size = AOP_SIZE(right);
9297         offset = 0 ;
9298
9299         while (size--) {
9300             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9301             MOVA(l);
9302             pic16_emitcode("movx","@dptr,a");
9303             if (size)
9304                 pic16_emitcode("inc","dptr");
9305         }
9306     }
9307
9308     pic16_freeAsmop(right,NULL,ic,TRUE);
9309 }
9310
9311 /*-----------------------------------------------------------------*/
9312 /* genGenPointerSet - set value from generic pointer space         */
9313 /*-----------------------------------------------------------------*/
9314 static void genGenPointerSet (operand *right,
9315                               operand *result, iCode *ic)
9316 {
9317         int size, offset, lit;
9318         sym_link *retype = getSpec(operandType(right));
9319
9320         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9321
9322         pic16_aopOp(result,ic,FALSE);
9323         pic16_aopOp(right,ic,FALSE);
9324         size = AOP_SIZE(right);
9325         offset = 0;
9326
9327         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9328
9329
9330         /* if the operand is already in dptr 
9331                 then we do nothing else we move the value to dptr */
9332         if (AOP_TYPE(result) != AOP_STR) {
9333                 /* if this is remateriazable */
9334                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9335                 // WARNING: anythig until "else" is untested!
9336                 if (AOP_TYPE(result) == AOP_IMMD) {
9337                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9338                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
9339                         // load FSR0 from immediate
9340                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9341                         offset = 0;
9342                         while(size--) {
9343                                 if(size) {
9344                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9345                                 } else {
9346                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9347                                 }
9348                                 offset++;
9349                         }
9350                         goto release;
9351                 }
9352                 else { /* we need to get it byte by byte */
9353                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9354                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9355
9356                         // set up FSR0 with address of result
9357                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9358                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9359
9360                         /* hack hack! see if this the FSR. If so don't load W */
9361                         if(AOP_TYPE(right) != AOP_ACC) {
9362
9363                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9364
9365                                 while(size--) {
9366                                         if(size) {
9367                                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9368                                         } else {
9369                                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9370                                         }
9371                                         offset++;
9372                                 }
9373                                 goto release;
9374                         } 
9375                         // right = ACC
9376                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9377
9378                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9379                         goto release;
9380         } // if (AOP_TYPE(result) != AOP_IMMD)
9381
9382         } // if (AOP_TYPE(result) != AOP_STR)
9383         /* so dptr know contains the address */
9384
9385
9386         /* if bit then unpack */
9387         if (IS_BITFIELD(retype)) 
9388                 genPackBits(retype,right,"dptr",GPOINTER);
9389         else {
9390                 size = AOP_SIZE(right);
9391                 offset = 0 ;
9392
9393                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9394
9395                 // set up FSR0 with address of result
9396                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9397                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9398         
9399                 while (size--) {
9400                         if (AOP_TYPE(right) == AOP_LIT) {
9401                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9402                                 if (size) {
9403                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
9404                                 } else {
9405                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9406                                 }
9407                         } else { // no literal
9408                                 if(size) {
9409                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9410                                 } else {
9411                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9412                                 }
9413                         }
9414                         offset++;
9415         }
9416         }
9417
9418         release:
9419         pic16_freeAsmop(right,NULL,ic,TRUE);
9420         pic16_freeAsmop(result,NULL,ic,TRUE);
9421 }
9422
9423 /*-----------------------------------------------------------------*/
9424 /* genPointerSet - stores the value into a pointer location        */
9425 /*-----------------------------------------------------------------*/
9426 static void genPointerSet (iCode *ic)
9427 {    
9428     operand *right, *result ;
9429     sym_link *type, *etype;
9430     int p_type;
9431
9432     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9433
9434     right = IC_RIGHT(ic);
9435     result = IC_RESULT(ic) ;
9436
9437     /* depending on the type of pointer we need to
9438     move it to the correct pointer register */
9439     type = operandType(result);
9440     etype = getSpec(type);
9441     /* if left is of type of pointer then it is simple */
9442     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9443         p_type = DCL_TYPE(type);
9444     }
9445     else {
9446         /* we have to go by the storage class */
9447         p_type = PTR_TYPE(SPEC_OCLS(etype));
9448
9449 /*      if (SPEC_OCLS(etype)->codesp ) { */
9450 /*          p_type = CPOINTER ;  */
9451 /*      } */
9452 /*      else */
9453 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9454 /*              p_type = FPOINTER ; */
9455 /*          else */
9456 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9457 /*                  p_type = PPOINTER ; */
9458 /*              else */
9459 /*                  if (SPEC_OCLS(etype) == idata ) */
9460 /*                      p_type = IPOINTER ; */
9461 /*                  else */
9462 /*                      p_type = POINTER ; */
9463     }
9464
9465     /* now that we have the pointer type we assign
9466     the pointer values */
9467     switch (p_type) {
9468
9469     case POINTER:
9470     case IPOINTER:
9471         genNearPointerSet (right,result,ic);
9472         break;
9473
9474     case PPOINTER:
9475         genPagedPointerSet (right,result,ic);
9476         break;
9477
9478     case FPOINTER:
9479         genFarPointerSet (right,result,ic);
9480         break;
9481
9482     case GPOINTER:
9483         genGenPointerSet (right,result,ic);
9484         break;
9485
9486     default:
9487       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9488               "genPointerSet: illegal pointer type");
9489     }
9490 }
9491
9492 /*-----------------------------------------------------------------*/
9493 /* genIfx - generate code for Ifx statement                        */
9494 /*-----------------------------------------------------------------*/
9495 static void genIfx (iCode *ic, iCode *popIc)
9496 {
9497   operand *cond = IC_COND(ic);
9498   int isbit =0;
9499
9500   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9501
9502   pic16_aopOp(cond,ic,FALSE);
9503
9504   /* get the value into acc */
9505   if (AOP_TYPE(cond) != AOP_CRY)
9506     pic16_toBoolean(cond);
9507   else
9508     isbit = 1;
9509   /* the result is now in the accumulator */
9510   pic16_freeAsmop(cond,NULL,ic,TRUE);
9511
9512   /* if there was something to be popped then do it */
9513   if (popIc)
9514     genIpop(popIc);
9515
9516   /* if the condition is  a bit variable */
9517   if (isbit && IS_ITEMP(cond) && 
9518       SPIL_LOC(cond)) {
9519     genIfxJump(ic,SPIL_LOC(cond)->rname);
9520     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9521   }
9522   else {
9523     if (isbit && !IS_ITEMP(cond))
9524       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9525     else
9526       genIfxJump(ic,"a");
9527   }
9528   ic->generated = 1;
9529
9530 }
9531
9532 /*-----------------------------------------------------------------*/
9533 /* genAddrOf - generates code for address of                       */
9534 /*-----------------------------------------------------------------*/
9535 #if 0
9536 static void genAddrOf (iCode *ic)
9537 {
9538   operand *right, *result, *left;
9539   int size, offset ;
9540
9541   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9542
9543
9544   //pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9545
9546   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
9547   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9548   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9549
9550   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
9551
9552   size = AOP_SIZE(IC_RESULT(ic));
9553   offset = 0;
9554
9555
9556   while (size--) {
9557     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),offset));
9558     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9559     offset++;
9560   }
9561
9562
9563   pic16_freeAsmop(left,NULL,ic,FALSE);
9564   pic16_freeAsmop(result,NULL,ic,TRUE);
9565
9566 }
9567
9568 #else   /* new genAddrOf */
9569
9570 static void genAddrOf (iCode *ic)
9571 {
9572   operand *result, *left;
9573   int size;
9574   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
9575   pCodeOp *pcop0, *pcop1, *pcop2;
9576
9577         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9578
9579         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9580         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9581
9582         sym = OP_SYMBOL( left );
9583
9584         size = AOP_SIZE(IC_RESULT(ic));
9585
9586         if(pic16_debug_verbose) {
9587                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9588                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9589         }
9590         
9591         /* Assume that what we want the address of is in data space
9592          * since there is no stack on the PIC, yet! -- VR */
9593         /* low */
9594         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9595
9596         /* high */
9597         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9598         
9599         /* upper */
9600         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9601         
9602
9603         if (size == 3) {
9604                 pic16_emitpcode(POC_MOVLW, pcop0);
9605                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9606                 pic16_emitpcode(POC_MOVLW, pcop1);
9607                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9608                 pic16_emitpcode(POC_MOVLW, pcop2);
9609                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9610         } else
9611         if (size == 2) {
9612                 pic16_emitpcode(POC_MOVLW, pcop0);
9613                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9614                 pic16_emitpcode(POC_MOVLW, pcop1);
9615                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9616         } else {
9617                 pic16_emitpcode(POC_MOVLW, pcop0);
9618                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9619         }
9620
9621         pic16_freeAsmop(result,NULL,ic,TRUE);
9622         pic16_freeAsmop(left, NULL, ic, FALSE);
9623 }
9624
9625 #endif  /* new genAddrOf */
9626
9627 #if 0
9628 /*-----------------------------------------------------------------*/
9629 /* genFarFarAssign - assignment when both are in far space         */
9630 /*-----------------------------------------------------------------*/
9631 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9632 {
9633     int size = AOP_SIZE(right);
9634     int offset = 0;
9635     char *l ;
9636     /* first push the right side on to the stack */
9637     while (size--) {
9638         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9639         MOVA(l);
9640         pic16_emitcode ("push","acc");
9641     }
9642     
9643     pic16_freeAsmop(right,NULL,ic,FALSE);
9644     /* now assign DPTR to result */
9645     pic16_aopOp(result,ic,FALSE);
9646     size = AOP_SIZE(result);
9647     while (size--) {
9648         pic16_emitcode ("pop","acc");
9649         pic16_aopPut(AOP(result),"a",--offset);
9650     }
9651     pic16_freeAsmop(result,NULL,ic,FALSE);
9652         
9653 }
9654 #endif
9655
9656 /*-----------------------------------------------------------------*/
9657 /* genAssign - generate code for assignment                        */
9658 /*-----------------------------------------------------------------*/
9659 static void genAssign (iCode *ic)
9660 {
9661   operand *result, *right;
9662   int size, offset,know_W;
9663   unsigned long lit = 0L;
9664
9665   result = IC_RESULT(ic);
9666   right  = IC_RIGHT(ic) ;
9667
9668   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9669   
9670   /* if they are the same */
9671   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9672     return ;
9673
9674   pic16_aopOp(right,ic,FALSE);
9675   pic16_aopOp(result,ic,TRUE);
9676
9677   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9678
9679   /* if they are the same registers */
9680   if (pic16_sameRegs(AOP(right),AOP(result)))
9681     goto release;
9682
9683   /* if the result is a bit */
9684   if (AOP_TYPE(result) == AOP_CRY) {
9685     /* if the right size is a literal then
9686        we know what the value is */
9687     if (AOP_TYPE(right) == AOP_LIT) {
9688           
9689       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9690                   pic16_popGet(AOP(result),0));
9691
9692       if (((int) operandLitValue(right))) 
9693         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9694                        AOP(result)->aopu.aop_dir,
9695                        AOP(result)->aopu.aop_dir);
9696       else
9697         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9698                        AOP(result)->aopu.aop_dir,
9699                        AOP(result)->aopu.aop_dir);
9700       goto release;
9701     }
9702
9703     /* the right is also a bit variable */
9704     if (AOP_TYPE(right) == AOP_CRY) {
9705       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9706       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9707       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9708
9709       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9710                      AOP(result)->aopu.aop_dir,
9711                      AOP(result)->aopu.aop_dir);
9712       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
9713                      AOP(right)->aopu.aop_dir,
9714                      AOP(right)->aopu.aop_dir);
9715       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9716                      AOP(result)->aopu.aop_dir,
9717                      AOP(result)->aopu.aop_dir);
9718       goto release ;
9719     }
9720
9721     /* we need to or */
9722     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9723     pic16_toBoolean(right);
9724     emitSKPZ;
9725     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9726     //pic16_aopPut(AOP(result),"a",0);
9727     goto release ;
9728   }
9729
9730   /* bit variables done */
9731   /* general case */
9732   size = AOP_SIZE(result);
9733   offset = 0 ;
9734   if(AOP_TYPE(right) == AOP_LIT)
9735     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9736
9737 /* VR - What is this?! */
9738   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9739   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9740     if(aopIdx(AOP(result),0) == 4) {
9741   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9742       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9743       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9744       goto release;
9745     } else
9746       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9747   }
9748
9749   know_W=-1;
9750   while (size--) {
9751   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9752     if(AOP_TYPE(right) == AOP_LIT) {
9753       if(lit&0xff) {
9754         if(know_W != (lit&0xff))
9755           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9756         know_W = lit&0xff;
9757         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9758       } else
9759         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9760
9761       lit >>= 8;
9762
9763     } else if (AOP_TYPE(right) == AOP_CRY) {
9764       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9765       if(offset == 0) {
9766         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
9767         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9768       }
9769     } else {
9770   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9771
9772 #if 1
9773         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
9774            normally should work, but mind that the W register live range
9775            is not checked, so if the code generator assumes that the W
9776            is already loaded after such a pair, wrong code will be generated.
9777            
9778            Checking the live range is the next step.
9779            This is experimental code yet and has not been fully tested yet.
9780            USE WITH CARE. Revert to old code by setting 0 to the condition above.
9781            Vangelis Rokas 030603 (vrokas@otenet.gr) */
9782            
9783         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9784 #else   
9785         /* This is the old code, which is assumed(?!) that works fine(!?) */
9786
9787         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9788         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9789 #endif
9790     }
9791             
9792     offset++;
9793   }
9794
9795     
9796  release:
9797   pic16_freeAsmop (right,NULL,ic,FALSE);
9798   pic16_freeAsmop (result,NULL,ic,TRUE);
9799 }   
9800
9801 /*-----------------------------------------------------------------*/
9802 /* genJumpTab - generates code for jump table                       */
9803 /*-----------------------------------------------------------------*/
9804 static void genJumpTab (iCode *ic)
9805 {
9806     symbol *jtab;
9807     char *l;
9808
9809     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9810
9811     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9812     /* get the condition into accumulator */
9813     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9814     MOVA(l);
9815     /* multiply by three */
9816     pic16_emitcode("add","a,acc");
9817     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9818
9819     jtab = newiTempLabel(NULL);
9820     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9821     pic16_emitcode("jmp","@a+dptr");
9822     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9823
9824     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9825     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9826     emitSKPNC;
9827     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9828     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9829     pic16_emitpLabel(jtab->key);
9830
9831     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9832
9833     /* now generate the jump labels */
9834     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9835          jtab = setNextItem(IC_JTLABELS(ic))) {
9836         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9837         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9838         
9839     }
9840
9841 }
9842
9843 /*-----------------------------------------------------------------*/
9844 /* genMixedOperation - gen code for operators between mixed types  */
9845 /*-----------------------------------------------------------------*/
9846 /*
9847   TSD - Written for the PIC port - but this unfortunately is buggy.
9848   This routine is good in that it is able to efficiently promote 
9849   types to different (larger) sizes. Unfortunately, the temporary
9850   variables that are optimized out by this routine are sometimes
9851   used in other places. So until I know how to really parse the 
9852   iCode tree, I'm going to not be using this routine :(.
9853 */
9854 static int genMixedOperation (iCode *ic)
9855 {
9856 #if 0
9857   operand *result = IC_RESULT(ic);
9858   sym_link *ctype = operandType(IC_LEFT(ic));
9859   operand *right = IC_RIGHT(ic);
9860   int ret = 0;
9861   int big,small;
9862   int offset;
9863
9864   iCode *nextic;
9865   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9866
9867   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9868
9869   nextic = ic->next;
9870   if(!nextic)
9871     return 0;
9872
9873   nextright = IC_RIGHT(nextic);
9874   nextleft  = IC_LEFT(nextic);
9875   nextresult = IC_RESULT(nextic);
9876
9877   pic16_aopOp(right,ic,FALSE);
9878   pic16_aopOp(result,ic,FALSE);
9879   pic16_aopOp(nextright,  nextic, FALSE);
9880   pic16_aopOp(nextleft,   nextic, FALSE);
9881   pic16_aopOp(nextresult, nextic, FALSE);
9882
9883   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9884
9885     operand *t = right;
9886     right = nextright;
9887     nextright = t; 
9888
9889     pic16_emitcode(";remove right +","");
9890
9891   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9892 /*
9893     operand *t = right;
9894     right = nextleft;
9895     nextleft = t; 
9896 */
9897     pic16_emitcode(";remove left +","");
9898   } else
9899     return 0;
9900
9901   big = AOP_SIZE(nextleft);
9902   small = AOP_SIZE(nextright);
9903
9904   switch(nextic->op) {
9905
9906   case '+':
9907     pic16_emitcode(";optimize a +","");
9908     /* if unsigned or not an integral type */
9909     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9910       pic16_emitcode(";add a bit to something","");
9911     } else {
9912
9913       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9914
9915       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9916         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9917         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9918       } else
9919         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9920
9921       offset = 0;
9922       while(--big) {
9923
9924         offset++;
9925
9926         if(--small) {
9927           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9928             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9929             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9930           }
9931
9932           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9933           emitSKPNC;
9934           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9935                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9936                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9937           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9938           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9939
9940         } else {
9941           pic16_emitcode("rlf","known_zero,w");
9942
9943           /*
9944             if right is signed
9945               btfsc  right,7
9946                addlw ff
9947           */
9948           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9949             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9950             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9951           } else {
9952             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9953           }
9954         }
9955       }
9956       ret = 1;
9957     }
9958   }
9959   ret = 1;
9960
9961 release:
9962   pic16_freeAsmop(right,NULL,ic,TRUE);
9963   pic16_freeAsmop(result,NULL,ic,TRUE);
9964   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9965   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9966   if(ret)
9967     nextic->generated = 1;
9968
9969   return ret;
9970 #else
9971   return 0;
9972 #endif
9973 }
9974 /*-----------------------------------------------------------------*/
9975 /* genCast - gen code for casting                                  */
9976 /*-----------------------------------------------------------------*/
9977 static void genCast (iCode *ic)
9978 {
9979   operand *result = IC_RESULT(ic);
9980   sym_link *ctype = operandType(IC_LEFT(ic));
9981   sym_link *rtype = operandType(IC_RIGHT(ic));
9982   operand *right = IC_RIGHT(ic);
9983   int size, offset ;
9984
9985         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9986         /* if they are equivalent then do nothing */
9987         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9988                 return ;
9989
9990         pic16_aopOp(right,ic,FALSE) ;
9991         pic16_aopOp(result,ic,FALSE);
9992
9993         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9994
9995         /* if the result is a bit */
9996         if (AOP_TYPE(result) == AOP_CRY) {
9997         
9998                 /* if the right size is a literal then
9999                  * we know what the value is */
10000                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10001
10002                 if (AOP_TYPE(right) == AOP_LIT) {
10003                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10004                                 pic16_popGet(AOP(result),0));
10005
10006                         if (((int) operandLitValue(right))) 
10007                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10008                                         AOP(result)->aopu.aop_dir,
10009                                         AOP(result)->aopu.aop_dir);
10010                         else
10011                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10012                                         AOP(result)->aopu.aop_dir,
10013                                         AOP(result)->aopu.aop_dir);
10014                         goto release;
10015                 }
10016
10017                 /* the right is also a bit variable */
10018                 if (AOP_TYPE(right) == AOP_CRY) {
10019                         emitCLRC;
10020                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10021
10022                         pic16_emitcode("clrc","");
10023                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10024                                 AOP(right)->aopu.aop_dir,
10025                                 AOP(right)->aopu.aop_dir);
10026                         pic16_aopPut(AOP(result),"c",0);
10027                         goto release ;
10028                 }
10029
10030                 /* we need to or */
10031                 if (AOP_TYPE(right) == AOP_REG) {
10032                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10033                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10034                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10035                 }
10036                 pic16_toBoolean(right);
10037                 pic16_aopPut(AOP(result),"a",0);
10038                 goto release ;
10039         }
10040
10041         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10042           int offset = 1;
10043
10044                 size = AOP_SIZE(result);
10045
10046                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10047
10048                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10049                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10050                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10051
10052                 while (size--)
10053                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10054
10055                 goto release;
10056         }
10057
10058         /* if they are the same size : or less */
10059         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10060
10061                 /* if they are in the same place */
10062                 if (pic16_sameRegs(AOP(right),AOP(result)))
10063                         goto release;
10064
10065                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10066 #if 0
10067                 if (IS_PTR_CONST(rtype))
10068 #else
10069                 if (IS_CODEPTR(rtype))
10070 #endif
10071                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10072
10073 #if 0
10074                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10075 #else
10076                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10077 #endif
10078                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10079
10080 #if 0
10081                 if(AOP_TYPE(right) == AOP_IMMD) {
10082                   pCodeOp *pcop0, *pcop1, *pcop2;
10083                   symbol *sym = OP_SYMBOL( right );
10084
10085                         size = AOP_SIZE(result);
10086                         /* low */
10087                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10088                         /* high */
10089                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10090                         /* upper */
10091                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10092         
10093                         if (size == 3) {
10094                                 pic16_emitpcode(POC_MOVLW, pcop0);
10095                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10096                                 pic16_emitpcode(POC_MOVLW, pcop1);
10097                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10098                                 pic16_emitpcode(POC_MOVLW, pcop2);
10099                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10100                         } else
10101                         if (size == 2) {
10102                                 pic16_emitpcode(POC_MOVLW, pcop0);
10103                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10104                                 pic16_emitpcode(POC_MOVLW, pcop1);
10105                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10106                         } else {
10107                                 pic16_emitpcode(POC_MOVLW, pcop0);
10108                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10109                         }
10110                 } else
10111 #endif
10112                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10113                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10114                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10115                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10116                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10117                         if(AOP_SIZE(result) <2)
10118                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10119                 } else {
10120                         /* if they in different places then copy */
10121                         size = AOP_SIZE(result);
10122                         offset = 0 ;
10123                         while (size--) {
10124                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10125                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10126                                 offset++;
10127                         }
10128                 }
10129                 goto release;
10130         }
10131
10132         /* if the result is of type pointer */
10133         if (IS_PTR(ctype)) {
10134           int p_type;
10135           sym_link *type = operandType(right);
10136           sym_link *etype = getSpec(type);
10137
10138                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10139
10140                 /* pointer to generic pointer */
10141                 if (IS_GENPTR(ctype)) {
10142                   char *l = zero;
10143             
10144                         if (IS_PTR(type)) 
10145                                 p_type = DCL_TYPE(type);
10146                         else {
10147                 /* we have to go by the storage class */
10148                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10149
10150 /*              if (SPEC_OCLS(etype)->codesp )  */
10151 /*                  p_type = CPOINTER ;  */
10152 /*              else */
10153 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10154 /*                      p_type = FPOINTER ; */
10155 /*                  else */
10156 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10157 /*                          p_type = PPOINTER; */
10158 /*                      else */
10159 /*                          if (SPEC_OCLS(etype) == idata ) */
10160 /*                              p_type = IPOINTER ; */
10161 /*                          else */
10162 /*                              p_type = POINTER ; */
10163             }
10164                 
10165             /* the first two bytes are known */
10166       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10167             size = GPTRSIZE - 1; 
10168             offset = 0 ;
10169             while (size--) {
10170               if(offset < AOP_SIZE(right)) {
10171       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10172                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10173                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10174                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10175                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10176                 } else { 
10177                   pic16_aopPut(AOP(result),
10178                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10179                          offset);
10180                 }
10181               } else 
10182                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10183               offset++;
10184             }
10185             /* the last byte depending on type */
10186             switch (p_type) {
10187             case IPOINTER:
10188             case POINTER:
10189                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10190                 break;
10191             case FPOINTER:
10192               pic16_emitcode(";BUG!? ","%d",__LINE__);
10193                 l = one;
10194                 break;
10195             case CPOINTER:
10196               pic16_emitcode(";BUG!? ","%d",__LINE__);
10197                 l = "#0x02";
10198                 break;                          
10199             case PPOINTER:
10200               pic16_emitcode(";BUG!? ","%d",__LINE__);
10201                 l = "#0x03";
10202                 break;
10203                 
10204             default:
10205                 /* this should never happen */
10206                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10207                        "got unknown pointer type");
10208                 exit(1);
10209             }
10210             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
10211             goto release ;
10212         }
10213         
10214         /* just copy the pointers */
10215         size = AOP_SIZE(result);
10216         offset = 0 ;
10217         while (size--) {
10218             pic16_aopPut(AOP(result),
10219                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10220                    offset);
10221             offset++;
10222         }
10223         goto release ;
10224     }
10225     
10226
10227
10228     /* so we now know that the size of destination is greater
10229     than the size of the source.
10230     Now, if the next iCode is an operator then we might be
10231     able to optimize the operation without performing a cast.
10232     */
10233     if(genMixedOperation(ic))
10234       goto release;
10235
10236     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10237     
10238     /* we move to result for the size of source */
10239     size = AOP_SIZE(right);
10240     offset = 0 ;
10241     while (size--) {
10242       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
10243       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
10244       offset++;
10245     }
10246
10247     /* now depending on the sign of the destination */
10248     size = AOP_SIZE(result) - AOP_SIZE(right);
10249     /* if unsigned or not an integral type */
10250     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10251       while (size--)
10252         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10253     } else {
10254       /* we need to extend the sign :( */
10255
10256       if(size == 1) {
10257         /* Save one instruction of casting char to int */
10258         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
10259         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10260         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
10261       } else {
10262         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10263
10264         if(offset)
10265           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10266         else
10267           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10268         
10269         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
10270
10271         while (size--)
10272           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
10273       }
10274     }
10275
10276 release:
10277     pic16_freeAsmop(right,NULL,ic,TRUE);
10278     pic16_freeAsmop(result,NULL,ic,TRUE);
10279
10280 }
10281
10282 /*-----------------------------------------------------------------*/
10283 /* genDjnz - generate decrement & jump if not zero instrucion      */
10284 /*-----------------------------------------------------------------*/
10285 static int genDjnz (iCode *ic, iCode *ifx)
10286 {
10287     symbol *lbl, *lbl1;
10288     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10289
10290     if (!ifx)
10291         return 0;
10292     
10293     /* if the if condition has a false label
10294        then we cannot save */
10295     if (IC_FALSE(ifx))
10296         return 0;
10297
10298     /* if the minus is not of the form 
10299        a = a - 1 */
10300     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10301         !IS_OP_LITERAL(IC_RIGHT(ic)))
10302         return 0;
10303
10304     if (operandLitValue(IC_RIGHT(ic)) != 1)
10305         return 0;
10306
10307     /* if the size of this greater than one then no
10308        saving */
10309     if (getSize(operandType(IC_RESULT(ic))) > 1)
10310         return 0;
10311
10312     /* otherwise we can save BIG */
10313     lbl = newiTempLabel(NULL);
10314     lbl1= newiTempLabel(NULL);
10315
10316     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10317     
10318     if (IS_AOP_PREG(IC_RESULT(ic))) {
10319         pic16_emitcode("dec","%s",
10320                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10321         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10322         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10323     } else {    
10324
10325
10326       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10327       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10328
10329       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10330       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10331
10332     }
10333 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10334 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10335 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10336 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10337
10338     
10339     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10340     ifx->generated = 1;
10341     return 1;
10342 }
10343
10344 /*-----------------------------------------------------------------*/
10345 /* genReceive - generate code for a receive iCode                  */
10346 /*-----------------------------------------------------------------*/
10347 static void genReceive (iCode *ic)
10348 {    
10349         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10350
10351         if (isOperandInFarSpace(IC_RESULT(ic)) && 
10352                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10353                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10354
10355           int size = getSize(operandType(IC_RESULT(ic)));
10356           int offset =  pic16_fReturnSizePic - size;
10357
10358                 while (size--) {
10359                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10360                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10361                         offset++;
10362                 }
10363
10364                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10365
10366                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10367                 size = AOP_SIZE(IC_RESULT(ic));
10368                 offset = 0;
10369                 while (size--) {
10370                         pic16_emitcode ("pop","acc");
10371                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10372                 }
10373         } else {
10374                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
10375
10376                 _G.accInUse++;
10377                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10378                 _G.accInUse--;
10379                 assignResultValue(IC_RESULT(ic));       
10380         }
10381
10382         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10383 }
10384
10385 /*-----------------------------------------------------------------*/
10386 /* genDummyRead - generate code for dummy read of volatiles        */
10387 /*-----------------------------------------------------------------*/
10388 static void
10389 genDummyRead (iCode * ic)
10390 {
10391   pic16_emitcode ("; genDummyRead","");
10392   pic16_emitcode ("; not implemented","");
10393
10394   ic = ic;
10395 }
10396
10397 /*-----------------------------------------------------------------*/
10398 /* genpic16Code - generate code for pic16 based controllers        */
10399 /*-----------------------------------------------------------------*/
10400 /*
10401  * At this point, ralloc.c has gone through the iCode and attempted
10402  * to optimize in a way suitable for a PIC. Now we've got to generate
10403  * PIC instructions that correspond to the iCode.
10404  *
10405  * Once the instructions are generated, we'll pass through both the
10406  * peep hole optimizer and the pCode optimizer.
10407  *-----------------------------------------------------------------*/
10408
10409 void genpic16Code (iCode *lic)
10410 {
10411     iCode *ic;
10412     int cln = 0;
10413
10414     lineHead = lineCurr = NULL;
10415
10416     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10417     pic16_addpBlock(pb);
10418
10419 #if 0
10420     /* if debug information required */
10421     if (options.debug && currFunc) {
10422       if (currFunc) {
10423         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10424         _G.debugLine = 1;
10425         if (IS_STATIC(currFunc->etype)) {
10426           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
10427           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10428         } else {
10429           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
10430           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10431         }
10432         _G.debugLine = 0;
10433       }
10434     }
10435 #endif
10436
10437 //    dumpiCode(lic);
10438
10439     for (ic = lic ; ic ; ic = ic->next ) {
10440
10441 //      fprintf(stderr, "; VR = %c %x\n", ic->op, ic->op);
10442 //      DEBUGpic16_emitcode("; VR", "");
10443       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10444         if ( cln != ic->lineno ) {
10445             if ( options.debug ) {
10446                 _G.debugLine = 1;
10447                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10448                          FileBaseName(ic->filename),ic->lineno,
10449                          ic->level,ic->block);
10450                 _G.debugLine = 0;
10451             }
10452             
10453             if(!options.noCcodeInAsm) {
10454                 pic16_addpCode2pBlock(pb,
10455                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
10456                                 printCLine(ic->filename, ic->lineno)));
10457             }
10458
10459             cln = ic->lineno ;
10460         }
10461         
10462         if(options.iCodeInAsm) {
10463                 /* insert here code to print iCode as comment */
10464                 pic16_emitcomment("; ic:%d: %s", ic->seq, printILine(ic));
10465         }
10466         
10467         /* if the result is marked as
10468            spilt and rematerializable or code for
10469            this has already been generated then
10470            do nothing */
10471         if (resultRemat(ic) || ic->generated ) 
10472             continue ;
10473         
10474         /* depending on the operation */
10475         switch (ic->op) {
10476         case '!' :
10477             pic16_genNot(ic);
10478             break;
10479             
10480         case '~' :
10481             pic16_genCpl(ic);
10482             break;
10483             
10484         case UNARYMINUS:
10485             genUminus (ic);
10486             break;
10487             
10488         case IPUSH:
10489             genIpush (ic);
10490             break;
10491             
10492         case IPOP:
10493             /* IPOP happens only when trying to restore a 
10494                spilt live range, if there is an ifx statement
10495                following this pop then the if statement might
10496                be using some of the registers being popped which
10497                would destroy the contents of the register so
10498                we need to check for this condition and handle it */
10499             if (ic->next            && 
10500                 ic->next->op == IFX &&
10501                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10502                 genIfx (ic->next,ic);
10503             else
10504                 genIpop (ic);
10505             break; 
10506             
10507         case CALL:
10508             genCall (ic);
10509             break;
10510             
10511         case PCALL:
10512             genPcall (ic);
10513             break;
10514             
10515         case FUNCTION:
10516             genFunction (ic);
10517             break;
10518             
10519         case ENDFUNCTION:
10520             genEndFunction (ic);
10521             break;
10522             
10523         case RETURN:
10524             genRet (ic);
10525             break;
10526             
10527         case LABEL:
10528             genLabel (ic);
10529             break;
10530             
10531         case GOTO:
10532             genGoto (ic);
10533             break;
10534             
10535         case '+' :
10536             pic16_genPlus (ic) ;
10537             break;
10538             
10539         case '-' :
10540             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10541                 pic16_genMinus (ic);
10542             break;
10543             
10544         case '*' :
10545             genMult (ic);
10546             break;
10547             
10548         case '/' :
10549             genDiv (ic) ;
10550             break;
10551             
10552         case '%' :
10553             genMod (ic);
10554             break;
10555             
10556         case '>' :
10557             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10558             break;
10559             
10560         case '<' :
10561             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10562             break;
10563             
10564         case LE_OP:
10565         case GE_OP:
10566         case NE_OP:
10567             
10568             /* note these two are xlated by algebraic equivalence
10569                during parsing SDCC.y */
10570             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10571                    "got '>=' or '<=' shouldn't have come here");
10572             break;      
10573             
10574         case EQ_OP:
10575             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10576             break;          
10577             
10578         case AND_OP:
10579             genAndOp (ic);
10580             break;
10581             
10582         case OR_OP:
10583             genOrOp (ic);
10584             break;
10585             
10586         case '^' :
10587             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10588             break;
10589             
10590         case '|' :
10591                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10592             break;
10593             
10594         case BITWISEAND:
10595             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10596             break;
10597             
10598         case INLINEASM:
10599             genInline (ic);
10600             break;
10601             
10602         case RRC:
10603             genRRC (ic);
10604             break;
10605             
10606         case RLC:
10607             genRLC (ic);
10608             break;
10609             
10610         case GETHBIT:
10611             genGetHbit (ic);
10612             break;
10613             
10614         case LEFT_OP:
10615             genLeftShift (ic);
10616             break;
10617             
10618         case RIGHT_OP:
10619             genRightShift (ic);
10620             break;
10621             
10622         case GET_VALUE_AT_ADDRESS:
10623             genPointerGet(ic);
10624             break;
10625             
10626         case '=' :
10627             if (POINTER_SET(ic))
10628                 genPointerSet(ic);
10629             else
10630                 genAssign(ic);
10631             break;
10632             
10633         case IFX:
10634             genIfx (ic,NULL);
10635             break;
10636             
10637         case ADDRESS_OF:
10638             genAddrOf (ic);
10639             break;
10640             
10641         case JUMPTABLE:
10642             genJumpTab (ic);
10643             break;
10644             
10645         case CAST:
10646             genCast (ic);
10647             break;
10648             
10649         case RECEIVE:
10650             genReceive(ic);
10651             break;
10652             
10653         case SEND:
10654             addSet(&_G.sendSet,ic);
10655             break;
10656
10657         case DUMMY_READ_VOLATILE:
10658           genDummyRead (ic);
10659           break;
10660
10661         default :
10662             ic = ic;
10663         }
10664     }
10665
10666
10667     /* now we are ready to call the
10668        peep hole optimizer */
10669     if (!options.nopeep) {
10670       peepHole (&lineHead);
10671     }
10672     /* now do the actual printing */
10673     printLine (lineHead,codeOutFile);
10674
10675 #ifdef PCODE_DEBUG
10676     DFPRINTF((stderr,"printing pBlock\n\n"));
10677     pic16_printpBlock(stdout,pb);
10678 #endif
10679
10680     return;
10681 }
10682