* src/pic16/gen.c (genInline): fixed bug #896482 with inline assembly
[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         _G.inLine += (!options.asmpeep);
6342
6343         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6344         strcpy(buffer,IC_INLINE(ic));
6345
6346         /* emit each line as a code */
6347         while (*bp) {
6348                 if (*bp == '\n') {
6349                         *bp++ = '\0';
6350                         
6351                         if(*bp1)
6352 #if 0
6353                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL));
6354 #else
6355                                 pic16_addpCode2pBlock(pb, pic16_AssembleLine(bp1, 1));
6356 #endif
6357                         bp1 = bp;
6358                 } else {
6359                         if (*bp == ':') {
6360                                 bp++;
6361                                 *bp = '\0';
6362                                 bp++;
6363                                 pic16_emitcode(bp1,"");
6364                                 bp1 = bp;
6365                         } else
6366                                 bp++;
6367                 }
6368         }
6369
6370         if ((bp1 != bp) && *bp1)
6371 #if 0
6372                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL));
6373 #else
6374                 pic16_addpCode2pBlock(pb, pic16_AssembleLine(bp1, 1));
6375 #endif
6376
6377         Safe_free(buffer);
6378         _G.inLine -= (!options.asmpeep);
6379 }
6380
6381 /*-----------------------------------------------------------------*/
6382 /* genRRC - rotate right with carry                                */
6383 /*-----------------------------------------------------------------*/
6384 static void genRRC (iCode *ic)
6385 {
6386   operand *left , *result ;
6387   int size, offset = 0, same;
6388
6389   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6390
6391   /* rotate right with carry */
6392   left = IC_LEFT(ic);
6393   result=IC_RESULT(ic);
6394   pic16_aopOp (left,ic,FALSE);
6395   pic16_aopOp (result,ic,FALSE);
6396
6397   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6398
6399   same = pic16_sameRegs(AOP(result),AOP(left));
6400
6401   size = AOP_SIZE(result);    
6402
6403   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6404
6405   /* get the lsb and put it into the carry */
6406   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6407
6408   offset = 0 ;
6409
6410   while(size--) {
6411
6412     if(same) {
6413       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6414     } else {
6415       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6416       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6417     }
6418
6419     offset++;
6420   }
6421
6422   pic16_freeAsmop(left,NULL,ic,TRUE);
6423   pic16_freeAsmop(result,NULL,ic,TRUE);
6424 }
6425
6426 /*-----------------------------------------------------------------*/
6427 /* genRLC - generate code for rotate left with carry               */
6428 /*-----------------------------------------------------------------*/
6429 static void genRLC (iCode *ic)
6430 {    
6431   operand *left , *result ;
6432   int size, offset = 0;
6433   int same;
6434
6435   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6436   /* rotate right with carry */
6437   left = IC_LEFT(ic);
6438   result=IC_RESULT(ic);
6439   pic16_aopOp (left,ic,FALSE);
6440   pic16_aopOp (result,ic,FALSE);
6441
6442   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6443
6444   same = pic16_sameRegs(AOP(result),AOP(left));
6445
6446   /* move it to the result */
6447   size = AOP_SIZE(result);    
6448
6449   /* get the msb and put it into the carry */
6450   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6451
6452   offset = 0 ;
6453
6454   while(size--) {
6455
6456     if(same) {
6457       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6458     } else {
6459       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6460       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6461     }
6462
6463     offset++;
6464   }
6465
6466
6467   pic16_freeAsmop(left,NULL,ic,TRUE);
6468   pic16_freeAsmop(result,NULL,ic,TRUE);
6469 }
6470
6471 /*-----------------------------------------------------------------*/
6472 /* genGetHbit - generates code get highest order bit               */
6473 /*-----------------------------------------------------------------*/
6474 static void genGetHbit (iCode *ic)
6475 {
6476     operand *left, *result;
6477     left = IC_LEFT(ic);
6478     result=IC_RESULT(ic);
6479     pic16_aopOp (left,ic,FALSE);
6480     pic16_aopOp (result,ic,FALSE);
6481
6482     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6483     /* get the highest order byte into a */
6484     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6485     if(AOP_TYPE(result) == AOP_CRY){
6486         pic16_emitcode("rlc","a");
6487         pic16_outBitC(result);
6488     }
6489     else{
6490         pic16_emitcode("rl","a");
6491         pic16_emitcode("anl","a,#0x01");
6492         pic16_outAcc(result);
6493     }
6494
6495
6496     pic16_freeAsmop(left,NULL,ic,TRUE);
6497     pic16_freeAsmop(result,NULL,ic,TRUE);
6498 }
6499
6500 #if 0
6501 /*-----------------------------------------------------------------*/
6502 /* AccRol - rotate left accumulator by known count                 */
6503 /*-----------------------------------------------------------------*/
6504 static void AccRol (int shCount)
6505 {
6506     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6507     shCount &= 0x0007;              // shCount : 0..7
6508     switch(shCount){
6509         case 0 :
6510             break;
6511         case 1 :
6512             pic16_emitcode("rl","a");
6513             break;
6514         case 2 :
6515             pic16_emitcode("rl","a");
6516             pic16_emitcode("rl","a");
6517             break;
6518         case 3 :
6519             pic16_emitcode("swap","a");
6520             pic16_emitcode("rr","a");
6521             break;
6522         case 4 :
6523             pic16_emitcode("swap","a");
6524             break;
6525         case 5 :
6526             pic16_emitcode("swap","a");
6527             pic16_emitcode("rl","a");
6528             break;
6529         case 6 :
6530             pic16_emitcode("rr","a");
6531             pic16_emitcode("rr","a");
6532             break;
6533         case 7 :
6534             pic16_emitcode("rr","a");
6535             break;
6536     }
6537 }
6538 #endif
6539
6540 /*-----------------------------------------------------------------*/
6541 /* AccLsh - left shift accumulator by known count                  */
6542 /*-----------------------------------------------------------------*/
6543 static void AccLsh (int shCount)
6544 {
6545     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6546     switch(shCount){
6547         case 0 :
6548                         return;
6549             break;
6550         case 1 :
6551             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6552             break;
6553         case 2 :
6554             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6555             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6556             break;
6557         case 3 :
6558             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6559             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6560             break;
6561         case 4 :
6562             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6563             break;
6564         case 5 :
6565             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6566             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6567             break;
6568         case 6 :
6569             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6570             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6571             break;
6572         case 7 :
6573             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6574             break;
6575     }
6576     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6577
6578 }
6579
6580 /*-----------------------------------------------------------------*/
6581 /* AccRsh - right shift accumulator by known count                 */
6582 /*-----------------------------------------------------------------*/
6583 static void AccRsh (int shCount)
6584 {
6585     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6586     switch(shCount){
6587         case 0 :
6588                         return;
6589             break;
6590         case 1 :
6591             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6592             break;
6593         case 2 :
6594             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6595             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6596             break;
6597         case 3 :
6598             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6599             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6600             break;
6601         case 4 :
6602             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6603             break;
6604         case 5 :
6605             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6606             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6607             break;
6608         case 6 :
6609             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6610             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6611             break;
6612         case 7 :
6613             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6614             break;
6615     }
6616     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6617 }
6618
6619 #if 0
6620 /*-----------------------------------------------------------------*/
6621 /* AccSRsh - signed right shift accumulator by known count                 */
6622 /*-----------------------------------------------------------------*/
6623 static void AccSRsh (int shCount)
6624 {
6625     symbol *tlbl ;
6626     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6627     if(shCount != 0){
6628         if(shCount == 1){
6629             pic16_emitcode("mov","c,acc.7");
6630             pic16_emitcode("rrc","a");
6631         } else if(shCount == 2){
6632             pic16_emitcode("mov","c,acc.7");
6633             pic16_emitcode("rrc","a");
6634             pic16_emitcode("mov","c,acc.7");
6635             pic16_emitcode("rrc","a");
6636         } else {
6637             tlbl = newiTempLabel(NULL);
6638             /* rotate right accumulator */
6639             AccRol(8 - shCount);
6640             /* and kill the higher order bits */
6641             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6642             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6643             pic16_emitcode("orl","a,#0x%02x",
6644                      (unsigned char)~SRMask[shCount]);
6645             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6646         }
6647     }
6648 }
6649 #endif
6650 /*-----------------------------------------------------------------*/
6651 /* shiftR1Left2Result - shift right one byte from left to result   */
6652 /*-----------------------------------------------------------------*/
6653 static void shiftR1Left2ResultSigned (operand *left, int offl,
6654                                 operand *result, int offr,
6655                                 int shCount)
6656 {
6657   int same;
6658
6659   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6660
6661   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6662
6663   switch(shCount) {
6664   case 1:
6665     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6666     if(same) 
6667       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6668     else {
6669       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6670       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6671     }
6672
6673     break;
6674   case 2:
6675
6676     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6677     if(same) 
6678       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6679     else {
6680       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6681       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6682     }
6683     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6684     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6685
6686     break;
6687
6688   case 3:
6689     if(same)
6690       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6691     else {
6692       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6693       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6694     }
6695
6696     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6697     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6698     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6699
6700     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6701     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
6702
6703     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6704     break;
6705
6706   case 4:
6707     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6708     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
6709     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6710     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
6711     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6712     break;
6713   case 5:
6714     if(same) {
6715       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
6716     } else {
6717       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
6718       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6719     }
6720     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
6721     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
6722     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6723     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
6724     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6725     break;
6726
6727   case 6:
6728     if(same) {
6729       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6730       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6731       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
6732       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6733       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
6734       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6735     } else {
6736       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6737       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6738       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6739       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6740       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6741     }
6742     break;
6743
6744   case 7:
6745     if(same) {
6746       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6747       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6748       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6749       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6750     } else {
6751       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6752       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6753       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6754     }
6755
6756   default:
6757     break;
6758   }
6759 }
6760
6761 /*-----------------------------------------------------------------*/
6762 /* shiftR1Left2Result - shift right one byte from left to result   */
6763 /*-----------------------------------------------------------------*/
6764 static void shiftR1Left2Result (operand *left, int offl,
6765                                 operand *result, int offr,
6766                                 int shCount, int sign)
6767 {
6768   int same;
6769
6770   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6771
6772   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6773
6774   /* Copy the msb into the carry if signed. */
6775   if(sign) {
6776     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6777     return;
6778   }
6779
6780
6781
6782   switch(shCount) {
6783   case 1:
6784     emitCLRC;
6785     if(same) 
6786       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6787     else {
6788       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6789       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6790     }
6791     break;
6792   case 2:
6793     emitCLRC;
6794     if(same) {
6795       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6796     } else {
6797       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6798       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6799     }
6800     emitCLRC;
6801     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6802
6803     break;
6804   case 3:
6805     if(same)
6806       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6807     else {
6808       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6809       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6810     }
6811
6812     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6813     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6814     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6815     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6816     break;
6817       
6818   case 4:
6819     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6820     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6821     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6822     break;
6823
6824   case 5:
6825     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6826     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6827     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6828     emitCLRC;
6829     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6830
6831     break;
6832   case 6:
6833
6834     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
6835     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6836     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6837     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6838     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6839     break;
6840
6841   case 7:
6842
6843     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6844     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6845     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6846
6847     break;
6848
6849   default:
6850     break;
6851   }
6852 }
6853
6854 /*-----------------------------------------------------------------*/
6855 /* shiftL1Left2Result - shift left one byte from left to result    */
6856 /*-----------------------------------------------------------------*/
6857 static void shiftL1Left2Result (operand *left, int offl,
6858                                 operand *result, int offr, int shCount)
6859 {
6860   int same;
6861
6862   //    char *l;
6863   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6864
6865   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6866   DEBUGpic16_emitcode ("; ***","same =  %d",same);
6867     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6868     //    MOVA(l);
6869     /* shift left accumulator */
6870     //AccLsh(shCount); // don't comment out just yet...
6871   //    pic16_aopPut(AOP(result),"a",offr);
6872
6873   switch(shCount) {
6874   case 1:
6875     /* Shift left 1 bit position */
6876     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6877     if(same) {
6878       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
6879     } else {
6880       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
6881       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6882     }
6883     break;
6884   case 2:
6885     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6886     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
6887     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6888     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6889     break;
6890   case 3:
6891     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6892     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
6893     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6894     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6895     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6896     break;
6897   case 4:
6898     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6899     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6900     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6901     break;
6902   case 5:
6903     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6904     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6905     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6906     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6907     break;
6908   case 6:
6909     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6910     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
6911     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6912     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6913     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6914     break;
6915   case 7:
6916     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6917     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6918     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6919     break;
6920
6921   default:
6922     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6923   }
6924
6925 }
6926
6927 /*-----------------------------------------------------------------*/
6928 /* movLeft2Result - move byte from left to result                  */
6929 /*-----------------------------------------------------------------*/
6930 static void movLeft2Result (operand *left, int offl,
6931                             operand *result, int offr)
6932 {
6933   char *l;
6934   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6935   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6936     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6937
6938     if (*l == '@' && (IS_AOP_PREG(result))) {
6939       pic16_emitcode("mov","a,%s",l);
6940       pic16_aopPut(AOP(result),"a",offr);
6941     } else {
6942       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6943       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6944     }
6945   }
6946 }
6947
6948 /*-----------------------------------------------------------------*/
6949 /* shiftL2Left2Result - shift left two bytes from left to result   */
6950 /*-----------------------------------------------------------------*/
6951 static void shiftL2Left2Result (operand *left, int offl,
6952                                 operand *result, int offr, int shCount)
6953 {
6954   int same = pic16_sameRegs(AOP(result), AOP(left));
6955   int i;
6956
6957   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6958
6959   if (same && (offl != offr)) { // shift bytes
6960     if (offr > offl) {
6961        for(i=1;i>-1;i--) {
6962          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6963          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6964        }
6965     } else { // just treat as different later on
6966                 same = 0;
6967     }
6968   }
6969
6970   if(same) {
6971     switch(shCount) {
6972     case 0:
6973       break;
6974     case 1:
6975     case 2:
6976     case 3:
6977
6978       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6979       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6980       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6981
6982       while(--shCount) {
6983                 emitCLRC;
6984                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6985                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6986       }
6987
6988       break;
6989     case 4:
6990     case 5:
6991       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6992       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6993       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6994       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6995       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6996       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6997       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6998       if(shCount >=5) {
6999                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7000                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7001       }
7002       break;
7003     case 6:
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_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7007       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7008       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7009       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7010       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7011       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7012       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7013       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7014       break;
7015     case 7:
7016       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7017       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7018       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7019       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7020       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7021     }
7022
7023   } else {
7024     switch(shCount) {
7025     case 0:
7026       break;
7027     case 1:
7028     case 2:
7029     case 3:
7030       /* note, use a mov/add for the shift since the mov has a
7031          chance of getting optimized out */
7032       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7033       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7034       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7035       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7036       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7037
7038       while(--shCount) {
7039                 emitCLRC;
7040                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7041                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7042       }
7043       break;
7044
7045     case 4:
7046     case 5:
7047       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7048       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7049       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7050       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7051       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7052       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7053       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7054       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7055
7056
7057       if(shCount == 5) {
7058                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7059                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7060       }
7061       break;
7062     case 6:
7063       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7064       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7065       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7066       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7067
7068       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7069       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7070       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7071       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7072       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7073       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7074       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7075       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7076       break;
7077     case 7:
7078       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7079       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7080       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7081       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7082       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7083     }
7084   }
7085
7086 }
7087 /*-----------------------------------------------------------------*/
7088 /* shiftR2Left2Result - shift right two bytes from left to result  */
7089 /*-----------------------------------------------------------------*/
7090 static void shiftR2Left2Result (operand *left, int offl,
7091                                 operand *result, int offr,
7092                                 int shCount, int sign)
7093 {
7094   int same = pic16_sameRegs(AOP(result), AOP(left));
7095   int i;
7096   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7097
7098   if (same && (offl != offr)) { // shift right bytes
7099     if (offr < offl) {
7100        for(i=0;i<2;i++) {
7101          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7102          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7103        }
7104     } else { // just treat as different later on
7105                 same = 0;
7106     }
7107   }
7108
7109   switch(shCount) {
7110   case 0:
7111     break;
7112   case 1:
7113   case 2:
7114   case 3:
7115     if(sign)
7116       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7117     else
7118       emitCLRC;
7119
7120     if(same) {
7121       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7122       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7123     } else {
7124       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7125       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7126       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7127       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7128     }
7129
7130     while(--shCount) {
7131       if(sign)
7132                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7133       else
7134                 emitCLRC;
7135       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7136       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7137     }
7138     break;
7139   case 4:
7140   case 5:
7141     if(same) {
7142
7143       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7144       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7145       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7146
7147       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7148       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7149       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7150       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7151     } else {
7152       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7153       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7154       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7155
7156       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7157       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7158       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7159       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7160       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7161     }
7162
7163     if(shCount >=5) {
7164       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7165       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7166     }
7167
7168     if(sign) {
7169       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7170       pic16_emitpcode(POC_BTFSC, 
7171                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7172       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7173     }
7174
7175     break;
7176
7177   case 6:
7178     if(same) {
7179
7180       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7181       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7182
7183       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7184       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7185       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7186       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7187       if(sign) {
7188         pic16_emitpcode(POC_BTFSC, 
7189                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7190         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7191       }
7192       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7193       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7194       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7195       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7196     } else {
7197       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7198       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7199       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7200       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7201       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7202       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7203       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7204       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7205       if(sign) {
7206         pic16_emitpcode(POC_BTFSC, 
7207                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7208         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7209       }
7210       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7211       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7212
7213         
7214     }
7215
7216     break;
7217   case 7:
7218     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7219     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7220     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7221     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7222     if(sign) {
7223       emitSKPNC;
7224       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7225     } else 
7226       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7227   }
7228 }
7229
7230
7231 /*-----------------------------------------------------------------*/
7232 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7233 /*-----------------------------------------------------------------*/
7234 static void shiftLLeftOrResult (operand *left, int offl,
7235                                 operand *result, int offr, int shCount)
7236 {
7237     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7238
7239     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7240     /* shift left accumulator */
7241     AccLsh(shCount);
7242     /* or with result */
7243     /* back to result */
7244     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7245 }
7246
7247 /*-----------------------------------------------------------------*/
7248 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7249 /*-----------------------------------------------------------------*/
7250 static void shiftRLeftOrResult (operand *left, int offl,
7251                                 operand *result, int offr, int shCount)
7252 {
7253     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7254     
7255     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7256     /* shift right accumulator */
7257     AccRsh(shCount);
7258     /* or with result */
7259     /* back to result */
7260     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7261 }
7262
7263 /*-----------------------------------------------------------------*/
7264 /* genlshOne - left shift a one byte quantity by known count       */
7265 /*-----------------------------------------------------------------*/
7266 static void genlshOne (operand *result, operand *left, int shCount)
7267 {       
7268     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7269     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7270 }
7271
7272 /*-----------------------------------------------------------------*/
7273 /* genlshTwo - left shift two bytes by known amount != 0           */
7274 /*-----------------------------------------------------------------*/
7275 static void genlshTwo (operand *result,operand *left, int shCount)
7276 {
7277     int size;
7278     
7279     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7280     size = pic16_getDataSize(result);
7281
7282     /* if shCount >= 8 */
7283     if (shCount >= 8) {
7284         shCount -= 8 ;
7285
7286         if (size > 1){
7287             if (shCount)
7288                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7289             else 
7290                 movLeft2Result(left, LSB, result, MSB16);
7291         }
7292         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7293     }
7294
7295     /*  1 <= shCount <= 7 */
7296     else {  
7297         if(size == 1)
7298             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7299         else 
7300             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7301     }
7302 }
7303
7304 /*-----------------------------------------------------------------*/
7305 /* shiftLLong - shift left one long from left to result            */
7306 /* offr = LSB or MSB16                                             */
7307 /*-----------------------------------------------------------------*/
7308 static void shiftLLong (operand *left, operand *result, int offr )
7309 {
7310     int size = AOP_SIZE(result);
7311     int same = pic16_sameRegs(AOP(left),AOP(result));
7312         int i;
7313
7314     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7315
7316         if (same && (offr == MSB16)) { //shift one byte
7317                 for(i=size-1;i>=MSB16;i--) {
7318                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7319                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7320                 }
7321         } else {
7322                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7323         }
7324         
7325     if (size >= LSB+offr ){
7326                 if (same) {
7327                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7328                 } else {
7329                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7330                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7331                 }
7332          }
7333
7334     if(size >= MSB16+offr){
7335                 if (same) {
7336                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7337                 } else {
7338                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7339                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7340                 }
7341     }
7342
7343     if(size >= MSB24+offr){
7344                 if (same) {
7345                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7346                 } else {
7347                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7348                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7349                 }
7350     }
7351
7352     if(size > MSB32+offr){
7353                 if (same) {
7354                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7355                 } else {
7356                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7357                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7358                 }
7359     }
7360     if(offr != LSB)
7361                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7362
7363 }
7364
7365 /*-----------------------------------------------------------------*/
7366 /* genlshFour - shift four byte by a known amount != 0             */
7367 /*-----------------------------------------------------------------*/
7368 static void genlshFour (operand *result, operand *left, int shCount)
7369 {
7370     int size;
7371
7372     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7373     size = AOP_SIZE(result);
7374
7375     /* if shifting more that 3 bytes */
7376     if (shCount >= 24 ) {
7377         shCount -= 24;
7378         if (shCount)
7379             /* lowest order of left goes to the highest
7380             order of the destination */
7381             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7382         else
7383             movLeft2Result(left, LSB, result, MSB32);
7384
7385                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7386                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7387                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7388
7389         return;
7390     }
7391
7392     /* more than two bytes */
7393     else if ( shCount >= 16 ) {
7394         /* lower order two bytes goes to higher order two bytes */
7395         shCount -= 16;
7396         /* if some more remaining */
7397         if (shCount)
7398             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7399         else {
7400             movLeft2Result(left, MSB16, result, MSB32);
7401             movLeft2Result(left, LSB, result, MSB24);
7402         }
7403                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7404                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7405         return;
7406     }    
7407
7408     /* if more than 1 byte */
7409     else if ( shCount >= 8 ) {
7410         /* lower order three bytes goes to higher order  three bytes */
7411         shCount -= 8;
7412         if(size == 2){
7413             if(shCount)
7414                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7415             else
7416                 movLeft2Result(left, LSB, result, MSB16);
7417         }
7418         else{   /* size = 4 */
7419             if(shCount == 0){
7420                 movLeft2Result(left, MSB24, result, MSB32);
7421                 movLeft2Result(left, MSB16, result, MSB24);
7422                 movLeft2Result(left, LSB, result, MSB16);
7423                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7424             }
7425             else if(shCount == 1)
7426                 shiftLLong(left, result, MSB16);
7427             else{
7428                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7429                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7430                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7431                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7432             }
7433         }
7434     }
7435
7436     /* 1 <= shCount <= 7 */
7437     else if(shCount <= 3)
7438     { 
7439         shiftLLong(left, result, LSB);
7440         while(--shCount >= 1)
7441             shiftLLong(result, result, LSB);
7442     }
7443     /* 3 <= shCount <= 7, optimize */
7444     else{
7445         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7446         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7447         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7448     }
7449 }
7450
7451 /*-----------------------------------------------------------------*/
7452 /* genLeftShiftLiteral - left shifting by known count              */
7453 /*-----------------------------------------------------------------*/
7454 static void genLeftShiftLiteral (operand *left,
7455                                  operand *right,
7456                                  operand *result,
7457                                  iCode *ic)
7458 {    
7459     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7460     int size;
7461
7462     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7463     pic16_freeAsmop(right,NULL,ic,TRUE);
7464
7465     pic16_aopOp(left,ic,FALSE);
7466     pic16_aopOp(result,ic,FALSE);
7467
7468     size = getSize(operandType(result));
7469
7470 #if VIEW_SIZE
7471     pic16_emitcode("; shift left ","result %d, left %d",size,
7472              AOP_SIZE(left));
7473 #endif
7474
7475     /* I suppose that the left size >= result size */
7476     if(shCount == 0){
7477         while(size--){
7478             movLeft2Result(left, size, result, size);
7479         }
7480     }
7481
7482     else if(shCount >= (size * 8))
7483         while(size--)
7484             pic16_aopPut(AOP(result),zero,size);
7485     else{
7486         switch (size) {
7487             case 1:
7488                 genlshOne (result,left,shCount);
7489                 break;
7490
7491             case 2:
7492             case 3:
7493                 genlshTwo (result,left,shCount);
7494                 break;
7495
7496             case 4:
7497                 genlshFour (result,left,shCount);
7498                 break;
7499         }
7500     }
7501     pic16_freeAsmop(left,NULL,ic,TRUE);
7502     pic16_freeAsmop(result,NULL,ic,TRUE);
7503 }
7504
7505 /*-----------------------------------------------------------------*
7506  * genMultiAsm - repeat assembly instruction for size of register.
7507  * if endian == 1, then the high byte (i.e base address + size of 
7508  * register) is used first else the low byte is used first;
7509  *-----------------------------------------------------------------*/
7510 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7511 {
7512
7513   int offset = 0;
7514
7515   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7516
7517   if(!reg)
7518     return;
7519
7520   if(!endian) {
7521     endian = 1;
7522   } else {
7523     endian = -1;
7524     offset = size-1;
7525   }
7526
7527   while(size--) {
7528     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7529     offset += endian;
7530   }
7531
7532 }
7533 /*-----------------------------------------------------------------*/
7534 /* genLeftShift - generates code for left shifting                 */
7535 /*-----------------------------------------------------------------*/
7536 static void genLeftShift (iCode *ic)
7537 {
7538   operand *left,*right, *result;
7539   int size, offset;
7540   char *l;
7541   symbol *tlbl , *tlbl1;
7542   pCodeOp *pctemp;
7543
7544   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7545
7546   right = IC_RIGHT(ic);
7547   left  = IC_LEFT(ic);
7548   result = IC_RESULT(ic);
7549
7550   pic16_aopOp(right,ic,FALSE);
7551
7552   /* if the shift count is known then do it 
7553      as efficiently as possible */
7554   if (AOP_TYPE(right) == AOP_LIT) {
7555     genLeftShiftLiteral (left,right,result,ic);
7556     return ;
7557   }
7558
7559   /* shift count is unknown then we have to form 
7560      a loop get the loop count in B : Note: we take
7561      only the lower order byte since shifting
7562      more that 32 bits make no sense anyway, ( the
7563      largest size of an object can be only 32 bits ) */  
7564
7565     
7566   pic16_aopOp(left,ic,FALSE);
7567   pic16_aopOp(result,ic,FALSE);
7568
7569   /* now move the left to the result if they are not the
7570      same */
7571   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7572       AOP_SIZE(result) > 1) {
7573
7574     size = AOP_SIZE(result);
7575     offset=0;
7576     while (size--) {
7577       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7578       if (*l == '@' && (IS_AOP_PREG(result))) {
7579
7580         pic16_emitcode("mov","a,%s",l);
7581         pic16_aopPut(AOP(result),"a",offset);
7582       } else {
7583         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7584         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7585         //pic16_aopPut(AOP(result),l,offset);
7586       }
7587       offset++;
7588     }
7589   }
7590
7591   size = AOP_SIZE(result);
7592
7593   /* if it is only one byte then */
7594   if (size == 1) {
7595     if(optimized_for_speed) {
7596       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7597       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7598       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7599       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7600       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7601       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7602       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7603       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7604       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7605       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7606       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7607       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7608     } else {
7609
7610       tlbl = newiTempLabel(NULL);
7611       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7612                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7613                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7614       }
7615
7616       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7617       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7618       pic16_emitpLabel(tlbl->key);
7619       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7620       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7621       emitSKPC;
7622       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7623     }
7624     goto release ;
7625   }
7626     
7627   if (pic16_sameRegs(AOP(left),AOP(result))) {
7628
7629     tlbl = newiTempLabel(NULL);
7630     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7631     genMultiAsm(POC_RRCF, result, size,1);
7632     pic16_emitpLabel(tlbl->key);
7633     genMultiAsm(POC_RLCF, result, size,0);
7634     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7635     emitSKPC;
7636     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7637     goto release;
7638   }
7639
7640   //tlbl = newiTempLabel(NULL);
7641   //offset = 0 ;   
7642   //tlbl1 = newiTempLabel(NULL);
7643
7644   //reAdjustPreg(AOP(result));    
7645     
7646   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7647   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7648   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7649   //MOVA(l);
7650   //pic16_emitcode("add","a,acc");         
7651   //pic16_aopPut(AOP(result),"a",offset++);
7652   //while (--size) {
7653   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7654   //  MOVA(l);
7655   //  pic16_emitcode("rlc","a");         
7656   //  pic16_aopPut(AOP(result),"a",offset++);
7657   //}
7658   //reAdjustPreg(AOP(result));
7659
7660   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7661   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7662
7663
7664   tlbl = newiTempLabel(NULL);
7665   tlbl1= newiTempLabel(NULL);
7666
7667   size = AOP_SIZE(result);
7668   offset = 1;
7669
7670   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7671
7672   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7673
7674   /* offset should be 0, 1 or 3 */
7675   
7676   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
7677   emitSKPNZ;
7678   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7679
7680   pic16_emitpcode(POC_MOVWF, pctemp);
7681
7682
7683   pic16_emitpLabel(tlbl->key);
7684
7685   emitCLRC;
7686   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
7687   while(--size)
7688     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
7689
7690   pic16_emitpcode(POC_DECFSZ,  pctemp);
7691   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7692   pic16_emitpLabel(tlbl1->key);
7693
7694   pic16_popReleaseTempReg(pctemp);
7695
7696
7697  release:
7698   pic16_freeAsmop (right,NULL,ic,TRUE);
7699   pic16_freeAsmop(left,NULL,ic,TRUE);
7700   pic16_freeAsmop(result,NULL,ic,TRUE);
7701 }
7702
7703 /*-----------------------------------------------------------------*/
7704 /* genrshOne - right shift a one byte quantity by known count      */
7705 /*-----------------------------------------------------------------*/
7706 static void genrshOne (operand *result, operand *left,
7707                        int shCount, int sign)
7708 {
7709     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7710     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7711 }
7712
7713 /*-----------------------------------------------------------------*/
7714 /* genrshTwo - right shift two bytes by known amount != 0          */
7715 /*-----------------------------------------------------------------*/
7716 static void genrshTwo (operand *result,operand *left,
7717                        int shCount, int sign)
7718 {
7719   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7720   /* if shCount >= 8 */
7721   if (shCount >= 8) {
7722     shCount -= 8 ;
7723     if (shCount)
7724       shiftR1Left2Result(left, MSB16, result, LSB,
7725                          shCount, sign);
7726     else
7727       movLeft2Result(left, MSB16, result, LSB);
7728
7729     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7730
7731     if(sign) {
7732       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7733       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
7734     }
7735   }
7736
7737   /*  1 <= shCount <= 7 */
7738   else
7739     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7740 }
7741
7742 /*-----------------------------------------------------------------*/
7743 /* shiftRLong - shift right one long from left to result           */
7744 /* offl = LSB or MSB16                                             */
7745 /*-----------------------------------------------------------------*/
7746 static void shiftRLong (operand *left, int offl,
7747                         operand *result, int sign)
7748 {
7749     int size = AOP_SIZE(result);
7750     int same = pic16_sameRegs(AOP(left),AOP(result));
7751     int i;
7752     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7753
7754         if (same && (offl == MSB16)) { //shift one byte right
7755                 for(i=MSB16;i<size;i++) {
7756                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7757                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7758                 }
7759         }
7760
7761     if(sign)
7762                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7763         else
7764                 emitCLRC;
7765
7766         if (same) {
7767                 if (offl == LSB)
7768                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7769         } else {
7770         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7771         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7772         }
7773
7774     if(offl == MSB16) {
7775         /* add sign of "a" */
7776         pic16_addSign(result, MSB32, sign);
7777         }
7778
7779         if (same) {
7780         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7781         } else {
7782         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7783         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7784         }
7785         
7786         if (same) {
7787         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7788         } else {
7789         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7790         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7791         }
7792
7793         if (same) {
7794         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7795         } else {
7796         if(offl == LSB){
7797                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7798                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7799         }
7800         }
7801 }
7802
7803 /*-----------------------------------------------------------------*/
7804 /* genrshFour - shift four byte by a known amount != 0             */
7805 /*-----------------------------------------------------------------*/
7806 static void genrshFour (operand *result, operand *left,
7807                         int shCount, int sign)
7808 {
7809   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7810   /* if shifting more that 3 bytes */
7811   if(shCount >= 24 ) {
7812     shCount -= 24;
7813     if(shCount)
7814       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7815     else
7816       movLeft2Result(left, MSB32, result, LSB);
7817
7818     pic16_addSign(result, MSB16, sign);
7819   }
7820   else if(shCount >= 16){
7821     shCount -= 16;
7822     if(shCount)
7823       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7824     else{
7825       movLeft2Result(left, MSB24, result, LSB);
7826       movLeft2Result(left, MSB32, result, MSB16);
7827     }
7828     pic16_addSign(result, MSB24, sign);
7829   }
7830   else if(shCount >= 8){
7831     shCount -= 8;
7832     if(shCount == 1)
7833       shiftRLong(left, MSB16, result, sign);
7834     else if(shCount == 0){
7835       movLeft2Result(left, MSB16, result, LSB);
7836       movLeft2Result(left, MSB24, result, MSB16);
7837       movLeft2Result(left, MSB32, result, MSB24);
7838       pic16_addSign(result, MSB32, sign);
7839     }
7840     else{ //shcount >= 2
7841       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7842       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7843       /* the last shift is signed */
7844       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7845       pic16_addSign(result, MSB32, sign);
7846     }
7847   }
7848   else{   /* 1 <= shCount <= 7 */
7849     if(shCount <= 2){
7850       shiftRLong(left, LSB, result, sign);
7851       if(shCount == 2)
7852         shiftRLong(result, LSB, result, sign);
7853     }
7854     else{
7855       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7856       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7857       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7858     }
7859   }
7860 }
7861
7862 /*-----------------------------------------------------------------*/
7863 /* genRightShiftLiteral - right shifting by known count            */
7864 /*-----------------------------------------------------------------*/
7865 static void genRightShiftLiteral (operand *left,
7866                                   operand *right,
7867                                   operand *result,
7868                                   iCode *ic,
7869                                   int sign)
7870 {    
7871   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7872   int lsize,res_size;
7873
7874   pic16_freeAsmop(right,NULL,ic,TRUE);
7875
7876   pic16_aopOp(left,ic,FALSE);
7877   pic16_aopOp(result,ic,FALSE);
7878
7879   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7880
7881 #if VIEW_SIZE
7882   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7883                  AOP_SIZE(left));
7884 #endif
7885
7886   lsize = pic16_getDataSize(left);
7887   res_size = pic16_getDataSize(result);
7888   /* test the LEFT size !!! */
7889
7890   /* I suppose that the left size >= result size */
7891   if(shCount == 0){
7892     while(res_size--)
7893       movLeft2Result(left, lsize, result, res_size);
7894   }
7895
7896   else if(shCount >= (lsize * 8)){
7897
7898     if(res_size == 1) {
7899       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
7900       if(sign) {
7901         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7902         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
7903       }
7904     } else {
7905
7906       if(sign) {
7907         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7908         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7909         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7910         while(res_size--)
7911           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
7912
7913       } else {
7914
7915         while(res_size--)
7916           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
7917       }
7918     }
7919   } else {
7920
7921     switch (res_size) {
7922     case 1:
7923       genrshOne (result,left,shCount,sign);
7924       break;
7925
7926     case 2:
7927       genrshTwo (result,left,shCount,sign);
7928       break;
7929
7930     case 4:
7931       genrshFour (result,left,shCount,sign);
7932       break;
7933     default :
7934       break;
7935     }
7936
7937   }
7938
7939   pic16_freeAsmop(left,NULL,ic,TRUE);
7940   pic16_freeAsmop(result,NULL,ic,TRUE);
7941 }
7942
7943 /*-----------------------------------------------------------------*/
7944 /* genSignedRightShift - right shift of signed number              */
7945 /*-----------------------------------------------------------------*/
7946 static void genSignedRightShift (iCode *ic)
7947 {
7948   operand *right, *left, *result;
7949   int size, offset;
7950   //  char *l;
7951   symbol *tlbl, *tlbl1 ;
7952   pCodeOp *pctemp;
7953
7954   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7955
7956   /* we do it the hard way put the shift count in b
7957      and loop thru preserving the sign */
7958   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7959
7960   right = IC_RIGHT(ic);
7961   left  = IC_LEFT(ic);
7962   result = IC_RESULT(ic);
7963
7964   pic16_aopOp(right,ic,FALSE);  
7965   pic16_aopOp(left,ic,FALSE);
7966   pic16_aopOp(result,ic,FALSE);
7967
7968
7969   if ( AOP_TYPE(right) == AOP_LIT) {
7970     genRightShiftLiteral (left,right,result,ic,1);
7971     return ;
7972   }
7973   /* shift count is unknown then we have to form 
7974      a loop get the loop count in B : Note: we take
7975      only the lower order byte since shifting
7976      more that 32 bits make no sense anyway, ( the
7977      largest size of an object can be only 32 bits ) */  
7978
7979   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7980   //pic16_emitcode("inc","b");
7981   //pic16_freeAsmop (right,NULL,ic,TRUE);
7982   //pic16_aopOp(left,ic,FALSE);
7983   //pic16_aopOp(result,ic,FALSE);
7984
7985   /* now move the left to the result if they are not the
7986      same */
7987   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7988       AOP_SIZE(result) > 1) {
7989
7990     size = AOP_SIZE(result);
7991     offset=0;
7992     while (size--) { 
7993       /*
7994         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7995         if (*l == '@' && IS_AOP_PREG(result)) {
7996
7997         pic16_emitcode("mov","a,%s",l);
7998         pic16_aopPut(AOP(result),"a",offset);
7999         } else
8000         pic16_aopPut(AOP(result),l,offset);
8001       */
8002       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8003       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8004
8005       offset++;
8006     }
8007   }
8008
8009   /* mov the highest order bit to OVR */    
8010   tlbl = newiTempLabel(NULL);
8011   tlbl1= newiTempLabel(NULL);
8012
8013   size = AOP_SIZE(result);
8014   offset = size - 1;
8015
8016   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8017
8018   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8019
8020   /* offset should be 0, 1 or 3 */
8021   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8022   emitSKPNZ;
8023   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8024
8025   pic16_emitpcode(POC_MOVWF, pctemp);
8026
8027
8028   pic16_emitpLabel(tlbl->key);
8029
8030   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8031   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8032
8033   while(--size) {
8034     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8035   }
8036
8037   pic16_emitpcode(POC_DECFSZ,  pctemp);
8038   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8039   pic16_emitpLabel(tlbl1->key);
8040
8041   pic16_popReleaseTempReg(pctemp);
8042 #if 0
8043   size = AOP_SIZE(result);
8044   offset = size - 1;
8045   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8046   pic16_emitcode("rlc","a");
8047   pic16_emitcode("mov","ov,c");
8048   /* if it is only one byte then */
8049   if (size == 1) {
8050     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8051     MOVA(l);
8052     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8053     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8054     pic16_emitcode("mov","c,ov");
8055     pic16_emitcode("rrc","a");
8056     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8057     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8058     pic16_aopPut(AOP(result),"a",0);
8059     goto release ;
8060   }
8061
8062   reAdjustPreg(AOP(result));
8063   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8064   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8065   pic16_emitcode("mov","c,ov");
8066   while (size--) {
8067     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8068     MOVA(l);
8069     pic16_emitcode("rrc","a");         
8070     pic16_aopPut(AOP(result),"a",offset--);
8071   }
8072   reAdjustPreg(AOP(result));
8073   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8074   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8075
8076  release:
8077 #endif
8078
8079   pic16_freeAsmop(left,NULL,ic,TRUE);
8080   pic16_freeAsmop(result,NULL,ic,TRUE);
8081   pic16_freeAsmop(right,NULL,ic,TRUE);
8082 }
8083
8084 /*-----------------------------------------------------------------*/
8085 /* genRightShift - generate code for right shifting                */
8086 /*-----------------------------------------------------------------*/
8087 static void genRightShift (iCode *ic)
8088 {
8089     operand *right, *left, *result;
8090     sym_link *letype ;
8091     int size, offset;
8092     char *l;
8093     symbol *tlbl, *tlbl1 ;
8094
8095     /* if signed then we do it the hard way preserve the
8096     sign bit moving it inwards */
8097     letype = getSpec(operandType(IC_LEFT(ic)));
8098     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8099
8100     if (!SPEC_USIGN(letype)) {
8101         genSignedRightShift (ic);
8102         return ;
8103     }
8104
8105     /* signed & unsigned types are treated the same : i.e. the
8106     signed is NOT propagated inwards : quoting from the
8107     ANSI - standard : "for E1 >> E2, is equivalent to division
8108     by 2**E2 if unsigned or if it has a non-negative value,
8109     otherwise the result is implementation defined ", MY definition
8110     is that the sign does not get propagated */
8111
8112     right = IC_RIGHT(ic);
8113     left  = IC_LEFT(ic);
8114     result = IC_RESULT(ic);
8115
8116     pic16_aopOp(right,ic,FALSE);
8117
8118     /* if the shift count is known then do it 
8119     as efficiently as possible */
8120     if (AOP_TYPE(right) == AOP_LIT) {
8121         genRightShiftLiteral (left,right,result,ic, 0);
8122         return ;
8123     }
8124
8125     /* shift count is unknown then we have to form 
8126     a loop get the loop count in B : Note: we take
8127     only the lower order byte since shifting
8128     more that 32 bits make no sense anyway, ( the
8129     largest size of an object can be only 32 bits ) */  
8130
8131     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8132     pic16_emitcode("inc","b");
8133     pic16_aopOp(left,ic,FALSE);
8134     pic16_aopOp(result,ic,FALSE);
8135
8136     /* now move the left to the result if they are not the
8137     same */
8138     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8139         AOP_SIZE(result) > 1) {
8140
8141         size = AOP_SIZE(result);
8142         offset=0;
8143         while (size--) {
8144             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8145             if (*l == '@' && IS_AOP_PREG(result)) {
8146
8147                 pic16_emitcode("mov","a,%s",l);
8148                 pic16_aopPut(AOP(result),"a",offset);
8149             } else
8150                 pic16_aopPut(AOP(result),l,offset);
8151             offset++;
8152         }
8153     }
8154
8155     tlbl = newiTempLabel(NULL);
8156     tlbl1= newiTempLabel(NULL);
8157     size = AOP_SIZE(result);
8158     offset = size - 1;
8159
8160     /* if it is only one byte then */
8161     if (size == 1) {
8162
8163       tlbl = newiTempLabel(NULL);
8164       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8165         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8166         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8167       }
8168
8169       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8170       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8171       pic16_emitpLabel(tlbl->key);
8172       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8173       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8174       emitSKPC;
8175       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8176
8177       goto release ;
8178     }
8179
8180     reAdjustPreg(AOP(result));
8181     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8182     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8183     CLRC;
8184     while (size--) {
8185         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8186         MOVA(l);
8187         pic16_emitcode("rrc","a");         
8188         pic16_aopPut(AOP(result),"a",offset--);
8189     }
8190     reAdjustPreg(AOP(result));
8191
8192     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8193     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8194
8195 release:
8196     pic16_freeAsmop(left,NULL,ic,TRUE);
8197     pic16_freeAsmop (right,NULL,ic,TRUE);
8198     pic16_freeAsmop(result,NULL,ic,TRUE);
8199 }
8200
8201 /*-----------------------------------------------------------------*/
8202 /* genUnpackBits - generates code for unpacking bits               */
8203 /*-----------------------------------------------------------------*/
8204 static void genUnpackBits (operand *result, char *rname, int ptype)
8205 {    
8206     int shCnt ;
8207     int rlen = 0 ;
8208     sym_link *etype;
8209     int offset = 0 ;
8210
8211     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8212     etype = getSpec(operandType(result));
8213
8214     /* read the first byte  */
8215     switch (ptype) {
8216
8217     case POINTER:
8218     case IPOINTER:
8219         pic16_emitcode("mov","a,@%s",rname);
8220         break;
8221         
8222     case PPOINTER:
8223         pic16_emitcode("movx","a,@%s",rname);
8224         break;
8225         
8226     case FPOINTER:
8227         pic16_emitcode("movx","a,@dptr");
8228         break;
8229
8230     case CPOINTER:
8231         pic16_emitcode("clr","a");
8232         pic16_emitcode("movc","a","@a+dptr");
8233         break;
8234
8235     case GPOINTER:
8236         pic16_emitcode("lcall","__gptrget");
8237         break;
8238     }
8239
8240     /* if we have bitdisplacement then it fits   */
8241     /* into this byte completely or if length is */
8242     /* less than a byte                          */
8243     if ((shCnt = SPEC_BSTR(etype)) || 
8244         (SPEC_BLEN(etype) <= 8))  {
8245
8246         /* shift right acc */
8247         AccRsh(shCnt);
8248
8249         pic16_emitcode("anl","a,#0x%02x",
8250                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8251         pic16_aopPut(AOP(result),"a",offset);
8252         return ;
8253     }
8254
8255     /* bit field did not fit in a byte  */
8256     rlen = SPEC_BLEN(etype) - 8;
8257     pic16_aopPut(AOP(result),"a",offset++);
8258
8259     while (1)  {
8260
8261         switch (ptype) {
8262         case POINTER:
8263         case IPOINTER:
8264             pic16_emitcode("inc","%s",rname);
8265             pic16_emitcode("mov","a,@%s",rname);
8266             break;
8267             
8268         case PPOINTER:
8269             pic16_emitcode("inc","%s",rname);
8270             pic16_emitcode("movx","a,@%s",rname);
8271             break;
8272
8273         case FPOINTER:
8274             pic16_emitcode("inc","dptr");
8275             pic16_emitcode("movx","a,@dptr");
8276             break;
8277             
8278         case CPOINTER:
8279             pic16_emitcode("clr","a");
8280             pic16_emitcode("inc","dptr");
8281             pic16_emitcode("movc","a","@a+dptr");
8282             break;
8283             
8284         case GPOINTER:
8285             pic16_emitcode("inc","dptr");
8286             pic16_emitcode("lcall","__gptrget");
8287             break;
8288         }
8289
8290         rlen -= 8;            
8291         /* if we are done */
8292         if ( rlen <= 0 )
8293             break ;
8294         
8295         pic16_aopPut(AOP(result),"a",offset++);
8296                               
8297     }
8298     
8299     if (rlen) {
8300         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8301         pic16_aopPut(AOP(result),"a",offset);          
8302     }
8303     
8304     return ;
8305 }
8306
8307 #if 0
8308 /*-----------------------------------------------------------------*/
8309 /* genDataPointerGet - generates code when ptr offset is known     */
8310 /*-----------------------------------------------------------------*/
8311 static void genDataPointerGet (operand *left, 
8312                                operand *result, 
8313                                iCode *ic)
8314 {
8315   int size , offset = 0;
8316
8317
8318   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8319
8320
8321   /* optimization - most of the time, left and result are the same
8322    * address, but different types. for the pic code, we could omit
8323    * the following
8324    */
8325
8326   pic16_aopOp(result,ic,TRUE);
8327
8328   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8329
8330   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8331
8332   size = AOP_SIZE(result);
8333
8334   while (size--) {
8335     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8336     offset++;
8337   }
8338
8339   pic16_freeAsmop(left,NULL,ic,TRUE);
8340   pic16_freeAsmop(result,NULL,ic,TRUE);
8341 }
8342 #endif
8343 /*-----------------------------------------------------------------*/
8344 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8345 /*-----------------------------------------------------------------*/
8346 static void genNearPointerGet (operand *left, 
8347                                operand *result, 
8348                                iCode *ic)
8349 {
8350     asmop *aop = NULL;
8351     //regs *preg = NULL ;
8352     char *rname ;
8353     sym_link *rtype, *retype;
8354     sym_link *ltype = operandType(left);    
8355     //char buffer[80];
8356
8357     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8358
8359     rtype = operandType(result);
8360     retype= getSpec(rtype);
8361     
8362     pic16_aopOp(left,ic,FALSE);
8363     
8364     /* if left is rematerialisable and
8365        result is not bit variable type and
8366        the left is pointer to data space i.e
8367        lower 128 bytes of space */
8368     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8369         !IS_BITVAR(retype)         &&
8370         DCL_TYPE(ltype) == POINTER) {
8371       //genDataPointerGet (left,result,ic);
8372         return ;
8373     }
8374     
8375     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8376
8377         /* if the value is already in a pointer register
8378        then don't need anything more */
8379     if (!AOP_INPREG(AOP(left))) {
8380         /* otherwise get a free pointer register */
8381     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8382 /*
8383         aop = newAsmop(0);
8384         preg = getFreePtr(ic,&aop,FALSE);
8385         pic16_emitcode("mov","%s,%s",
8386                 preg->name,
8387                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8388         rname = preg->name ;
8389 */
8390     rname ="BAD";
8391     } else
8392         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8393     
8394     pic16_aopOp (result,ic,FALSE);
8395     
8396       /* if bitfield then unpack the bits */
8397     if (IS_BITFIELD(retype)) 
8398         genUnpackBits (result,rname,POINTER);
8399     else {
8400         /* we have can just get the values */
8401       int size = AOP_SIZE(result);
8402       int offset = 0 ;  
8403         
8404       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8405
8406       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8407       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8408       while(size--) {
8409         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8410         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8411         if(size)
8412           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8413       }
8414 /*
8415         while (size--) {
8416             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8417
8418                 pic16_emitcode("mov","a,@%s",rname);
8419                 pic16_aopPut(AOP(result),"a",offset);
8420             } else {
8421                 sprintf(buffer,"@%s",rname);
8422                 pic16_aopPut(AOP(result),buffer,offset);
8423             }
8424             offset++ ;
8425             if (size)
8426                 pic16_emitcode("inc","%s",rname);
8427         }
8428 */
8429     }
8430
8431     /* now some housekeeping stuff */
8432     if (aop) {
8433         /* we had to allocate for this iCode */
8434     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8435         pic16_freeAsmop(NULL,aop,ic,TRUE);
8436     } else { 
8437         /* we did not allocate which means left
8438            already in a pointer register, then
8439            if size > 0 && this could be used again
8440            we have to point it back to where it 
8441            belongs */
8442     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8443         if (AOP_SIZE(result) > 1 &&
8444             !OP_SYMBOL(left)->remat &&
8445             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8446               ic->depth )) {
8447             int size = AOP_SIZE(result) - 1;
8448             while (size--)
8449                 pic16_emitcode("dec","%s",rname);
8450         }
8451     }
8452
8453     /* done */
8454     pic16_freeAsmop(left,NULL,ic,TRUE);
8455     pic16_freeAsmop(result,NULL,ic,TRUE);
8456      
8457 }
8458
8459 /*-----------------------------------------------------------------*/
8460 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8461 /*-----------------------------------------------------------------*/
8462 static void genPagedPointerGet (operand *left, 
8463                                operand *result, 
8464                                iCode *ic)
8465 {
8466     asmop *aop = NULL;
8467     regs *preg = NULL ;
8468     char *rname ;
8469     sym_link *rtype, *retype;    
8470
8471     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8472
8473     rtype = operandType(result);
8474     retype= getSpec(rtype);
8475     
8476     pic16_aopOp(left,ic,FALSE);
8477
8478   /* if the value is already in a pointer register
8479        then don't need anything more */
8480     if (!AOP_INPREG(AOP(left))) {
8481         /* otherwise get a free pointer register */
8482         aop = newAsmop(0);
8483         preg = getFreePtr(ic,&aop,FALSE);
8484         pic16_emitcode("mov","%s,%s",
8485                 preg->name,
8486                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8487         rname = preg->name ;
8488     } else
8489         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8490     
8491     pic16_freeAsmop(left,NULL,ic,TRUE);
8492     pic16_aopOp (result,ic,FALSE);
8493
8494     /* if bitfield then unpack the bits */
8495     if (IS_BITFIELD(retype)) 
8496         genUnpackBits (result,rname,PPOINTER);
8497     else {
8498         /* we have can just get the values */
8499         int size = AOP_SIZE(result);
8500         int offset = 0 ;        
8501         
8502         while (size--) {
8503             
8504             pic16_emitcode("movx","a,@%s",rname);
8505             pic16_aopPut(AOP(result),"a",offset);
8506             
8507             offset++ ;
8508             
8509             if (size)
8510                 pic16_emitcode("inc","%s",rname);
8511         }
8512     }
8513
8514     /* now some housekeeping stuff */
8515     if (aop) {
8516         /* we had to allocate for this iCode */
8517         pic16_freeAsmop(NULL,aop,ic,TRUE);
8518     } else { 
8519         /* we did not allocate which means left
8520            already in a pointer register, then
8521            if size > 0 && this could be used again
8522            we have to point it back to where it 
8523            belongs */
8524         if (AOP_SIZE(result) > 1 &&
8525             !OP_SYMBOL(left)->remat &&
8526             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8527               ic->depth )) {
8528             int size = AOP_SIZE(result) - 1;
8529             while (size--)
8530                 pic16_emitcode("dec","%s",rname);
8531         }
8532     }
8533
8534     /* done */
8535     pic16_freeAsmop(result,NULL,ic,TRUE);
8536     
8537         
8538 }
8539
8540 /*-----------------------------------------------------------------*/
8541 /* genFarPointerGet - gget value from far space                    */
8542 /*-----------------------------------------------------------------*/
8543 static void genFarPointerGet (operand *left,
8544                               operand *result, iCode *ic)
8545 {
8546     int size, offset ;
8547     sym_link *retype = getSpec(operandType(result));
8548
8549     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8550
8551     pic16_aopOp(left,ic,FALSE);
8552
8553     /* if the operand is already in dptr 
8554     then we do nothing else we move the value to dptr */
8555     if (AOP_TYPE(left) != AOP_STR) {
8556         /* if this is remateriazable */
8557         if (AOP_TYPE(left) == AOP_IMMD)
8558             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8559         else { /* we need to get it byte by byte */
8560             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8561             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8562             if (options.model == MODEL_FLAT24)
8563             {
8564                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8565             }
8566         }
8567     }
8568     /* so dptr know contains the address */
8569     pic16_freeAsmop(left,NULL,ic,TRUE);
8570     pic16_aopOp(result,ic,FALSE);
8571
8572     /* if bit then unpack */
8573     if (IS_BITFIELD(retype)) 
8574         genUnpackBits(result,"dptr",FPOINTER);
8575     else {
8576         size = AOP_SIZE(result);
8577         offset = 0 ;
8578
8579         while (size--) {
8580             pic16_emitcode("movx","a,@dptr");
8581             pic16_aopPut(AOP(result),"a",offset++);
8582             if (size)
8583                 pic16_emitcode("inc","dptr");
8584         }
8585     }
8586
8587     pic16_freeAsmop(result,NULL,ic,TRUE);
8588 }
8589 #if 0
8590 /*-----------------------------------------------------------------*/
8591 /* genCodePointerGet - get value from code space                  */
8592 /*-----------------------------------------------------------------*/
8593 static void genCodePointerGet (operand *left,
8594                                 operand *result, iCode *ic)
8595 {
8596     int size, offset ;
8597     sym_link *retype = getSpec(operandType(result));
8598
8599     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8600
8601     pic16_aopOp(left,ic,FALSE);
8602
8603     /* if the operand is already in dptr 
8604     then we do nothing else we move the value to dptr */
8605     if (AOP_TYPE(left) != AOP_STR) {
8606         /* if this is remateriazable */
8607         if (AOP_TYPE(left) == AOP_IMMD)
8608             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8609         else { /* we need to get it byte by byte */
8610             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8611             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8612             if (options.model == MODEL_FLAT24)
8613             {
8614                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8615             }
8616         }
8617     }
8618     /* so dptr know contains the address */
8619     pic16_freeAsmop(left,NULL,ic,TRUE);
8620     pic16_aopOp(result,ic,FALSE);
8621
8622     /* if bit then unpack */
8623     if (IS_BITFIELD(retype)) 
8624         genUnpackBits(result,"dptr",CPOINTER);
8625     else {
8626         size = AOP_SIZE(result);
8627         offset = 0 ;
8628
8629         while (size--) {
8630             pic16_emitcode("clr","a");
8631             pic16_emitcode("movc","a,@a+dptr");
8632             pic16_aopPut(AOP(result),"a",offset++);
8633             if (size)
8634                 pic16_emitcode("inc","dptr");
8635         }
8636     }
8637
8638     pic16_freeAsmop(result,NULL,ic,TRUE);
8639 }
8640 #endif
8641 /*-----------------------------------------------------------------*/
8642 /* genGenPointerGet - gget value from generic pointer space        */
8643 /*-----------------------------------------------------------------*/
8644 static void genGenPointerGet (operand *left,
8645                               operand *result, iCode *ic)
8646 {
8647         int size, offset, lit;
8648         sym_link *retype = getSpec(operandType(result));
8649
8650         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8651         pic16_aopOp(left,ic,FALSE);
8652         pic16_aopOp(result,ic,FALSE);
8653         size = AOP_SIZE(result);
8654
8655         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8656
8657         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
8658
8659                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
8660                 // load FSR0 from immediate
8661                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
8662                 offset = 0;
8663                 while(size--) {
8664                         if(size) {
8665                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
8666                         } else {
8667                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
8668                         }
8669                         offset++;
8670                 }
8671                 goto release;
8672
8673         }
8674         else { /* we need to get it byte by byte */
8675                 // set up FSR0 with address from left
8676                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
8677                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
8678
8679                 offset = 0 ;
8680
8681                 while(size--) {
8682                         if(size) {
8683                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
8684                         } else {
8685                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
8686                         }
8687                         offset++;
8688                 }
8689                 goto release;
8690         }
8691
8692   /* if bit then unpack */
8693         if (IS_BITFIELD(retype)) 
8694                 genUnpackBits(result,"BAD",GPOINTER);
8695
8696         release:
8697         pic16_freeAsmop(left,NULL,ic,TRUE);
8698         pic16_freeAsmop(result,NULL,ic,TRUE);
8699
8700 }
8701
8702 /*-----------------------------------------------------------------*/
8703 /* genConstPointerGet - get value from const generic pointer space */
8704 /*-----------------------------------------------------------------*/
8705 static void genConstPointerGet (operand *left,
8706                                 operand *result, iCode *ic)
8707 {
8708   //sym_link *retype = getSpec(operandType(result));
8709   symbol *albl = newiTempLabel(NULL);
8710   symbol *blbl = newiTempLabel(NULL);
8711   PIC_OPCODE poc;
8712
8713   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8714   pic16_aopOp(left,ic,FALSE);
8715   pic16_aopOp(result,ic,FALSE);
8716
8717
8718   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8719
8720   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8721
8722   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
8723   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
8724   pic16_emitpLabel(albl->key);
8725
8726   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8727     
8728   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
8729   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
8730   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
8731   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
8732   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
8733
8734   pic16_emitpLabel(blbl->key);
8735
8736   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
8737
8738
8739   pic16_freeAsmop(left,NULL,ic,TRUE);
8740   pic16_freeAsmop(result,NULL,ic,TRUE);
8741
8742 }
8743 /*-----------------------------------------------------------------*/
8744 /* genPointerGet - generate code for pointer get                   */
8745 /*-----------------------------------------------------------------*/
8746 static void genPointerGet (iCode *ic)
8747 {
8748     operand *left, *result ;
8749     sym_link *type, *etype;
8750     int p_type;
8751
8752     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8753
8754     left = IC_LEFT(ic);
8755     result = IC_RESULT(ic) ;
8756
8757     /* depending on the type of pointer we need to
8758     move it to the correct pointer register */
8759     type = operandType(left);
8760     etype = getSpec(type);
8761
8762 #if 0
8763     if (IS_PTR_CONST(type))
8764 #else
8765     if (IS_CODEPTR(type))
8766 #endif
8767       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8768
8769     /* if left is of type of pointer then it is simple */
8770     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8771         p_type = DCL_TYPE(type);
8772     else {
8773         /* we have to go by the storage class */
8774         p_type = PTR_TYPE(SPEC_OCLS(etype));
8775
8776         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8777
8778         if (SPEC_OCLS(etype)->codesp ) {
8779           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8780           //p_type = CPOINTER ; 
8781         }
8782         else
8783             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8784               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8785                /*p_type = FPOINTER ;*/ 
8786             else
8787                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8788                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8789 /*                  p_type = PPOINTER; */
8790                 else
8791                     if (SPEC_OCLS(etype) == idata )
8792                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8793 /*                      p_type = IPOINTER; */
8794                     else
8795                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8796 /*                      p_type = POINTER ; */
8797     }
8798
8799     /* now that we have the pointer type we assign
8800     the pointer values */
8801     switch (p_type) {
8802
8803     case POINTER:       
8804     case IPOINTER:
8805         genNearPointerGet (left,result,ic);
8806         break;
8807
8808     case PPOINTER:
8809         genPagedPointerGet(left,result,ic);
8810         break;
8811
8812     case FPOINTER:
8813         genFarPointerGet (left,result,ic);
8814         break;
8815
8816     case CPOINTER:
8817         genConstPointerGet (left,result,ic);
8818         //pic16_emitcodePointerGet (left,result,ic);
8819         break;
8820
8821     case GPOINTER:
8822 #if 0
8823       if (IS_PTR_CONST(type))
8824         genConstPointerGet (left,result,ic);
8825       else
8826 #endif
8827         genGenPointerGet (left,result,ic);
8828       break;
8829     }
8830
8831 }
8832
8833 /*-----------------------------------------------------------------*/
8834 /* genPackBits - generates code for packed bit storage             */
8835 /*-----------------------------------------------------------------*/
8836 static void genPackBits (sym_link    *etype ,
8837                          operand *right ,
8838                          char *rname, int p_type)
8839 {
8840     int shCount = 0 ;
8841     int offset = 0  ;
8842     int rLen = 0 ;
8843     int blen, bstr ;   
8844     char *l ;
8845
8846     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8847     blen = SPEC_BLEN(etype);
8848     bstr = SPEC_BSTR(etype);
8849
8850     l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8851     MOVA(l);   
8852
8853     /* if the bit lenth is less than or    */
8854     /* it exactly fits a byte then         */
8855     if (SPEC_BLEN(etype) <= 8 )  {
8856         shCount = SPEC_BSTR(etype) ;
8857
8858         /* shift left acc */
8859         AccLsh(shCount);
8860
8861         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8862
8863
8864             switch (p_type) {
8865                 case POINTER:
8866                     pic16_emitcode ("mov","b,a");
8867                     pic16_emitcode("mov","a,@%s",rname);
8868                     break;
8869
8870                 case FPOINTER:
8871                     pic16_emitcode ("mov","b,a");
8872                     pic16_emitcode("movx","a,@dptr");
8873                     break;
8874
8875                 case GPOINTER:
8876                     pic16_emitcode ("push","b");
8877                     pic16_emitcode ("push","acc");
8878                     pic16_emitcode ("lcall","__gptrget");
8879                     pic16_emitcode ("pop","b");
8880                     break;
8881             }
8882
8883             pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
8884                       ((unsigned char)(0xFF << (blen+bstr)) | 
8885                        (unsigned char)(0xFF >> (8-bstr)) ) );
8886             pic16_emitcode ("orl","a,b");
8887             if (p_type == GPOINTER)
8888                 pic16_emitcode("pop","b");
8889         }
8890     }
8891
8892     switch (p_type) {
8893         case POINTER:
8894             pic16_emitcode("mov","@%s,a",rname);
8895             break;
8896
8897         case FPOINTER:
8898             pic16_emitcode("movx","@dptr,a");
8899             break;
8900
8901         case GPOINTER:
8902             DEBUGpic16_emitcode(";lcall","__gptrput");
8903             break;
8904     }
8905
8906     /* if we r done */
8907     if ( SPEC_BLEN(etype) <= 8 )
8908         return ;
8909
8910     pic16_emitcode("inc","%s",rname);
8911     rLen = SPEC_BLEN(etype) ;     
8912
8913     /* now generate for lengths greater than one byte */
8914     while (1) {
8915
8916         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
8917
8918         rLen -= 8 ;
8919         if (rLen <= 0 )
8920             break ;
8921
8922         switch (p_type) {
8923             case POINTER:
8924                 if (*l == '@') {
8925                     MOVA(l);
8926                     pic16_emitcode("mov","@%s,a",rname);
8927                 } else
8928                     pic16_emitcode("mov","@%s,%s",rname,l);
8929                 break;
8930
8931             case FPOINTER:
8932                 MOVA(l);
8933                 pic16_emitcode("movx","@dptr,a");
8934                 break;
8935
8936             case GPOINTER:
8937                 MOVA(l);
8938                 DEBUGpic16_emitcode(";lcall","__gptrput");
8939                 break;  
8940         }   
8941         pic16_emitcode ("inc","%s",rname);
8942     }
8943
8944     MOVA(l);
8945
8946     /* last last was not complete */
8947     if (rLen)   {
8948         /* save the byte & read byte */
8949         switch (p_type) {
8950             case POINTER:
8951                 pic16_emitcode ("mov","b,a");
8952                 pic16_emitcode("mov","a,@%s",rname);
8953                 break;
8954
8955             case FPOINTER:
8956                 pic16_emitcode ("mov","b,a");
8957                 pic16_emitcode("movx","a,@dptr");
8958                 break;
8959
8960             case GPOINTER:
8961                 pic16_emitcode ("push","b");
8962                 pic16_emitcode ("push","acc");
8963                 pic16_emitcode ("lcall","__gptrget");
8964                 pic16_emitcode ("pop","b");
8965                 break;
8966         }
8967
8968         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8969         pic16_emitcode ("orl","a,b");
8970     }
8971
8972     if (p_type == GPOINTER)
8973         pic16_emitcode("pop","b");
8974
8975     switch (p_type) {
8976
8977     case POINTER:
8978         pic16_emitcode("mov","@%s,a",rname);
8979         break;
8980         
8981     case FPOINTER:
8982         pic16_emitcode("movx","@dptr,a");
8983         break;
8984         
8985     case GPOINTER:
8986         DEBUGpic16_emitcode(";lcall","__gptrput");
8987         break;                  
8988     }
8989 }
8990 /*-----------------------------------------------------------------*/
8991 /* genDataPointerSet - remat pointer to data space                 */
8992 /*-----------------------------------------------------------------*/
8993 static void genDataPointerSet(operand *right,
8994                               operand *result,
8995                               iCode *ic)
8996 {
8997     int size, offset = 0 ;
8998     char *l, buffer[256];
8999
9000     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9001     pic16_aopOp(right,ic,FALSE);
9002     
9003     l = pic16_aopGet(AOP(result),0,FALSE,TRUE);
9004     size = AOP_SIZE(right);
9005 /*
9006     if ( AOP_TYPE(result) == AOP_PCODE) {
9007       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9008               AOP(result)->aopu.pcop->name,
9009               PCOI(AOP(result)->aopu.pcop)->offset);
9010     }
9011 */
9012
9013     // tsd, was l+1 - the underline `_' prefix was being stripped
9014     while (size--) {
9015       if (offset) {
9016         sprintf(buffer,"(%s + %d)",l,offset);
9017         fprintf(stderr,"%s:%d: oops  %s\n",__FILE__, __LINE__, buffer);
9018       } else
9019         sprintf(buffer,"%s",l);
9020
9021         if (AOP_TYPE(right) == AOP_LIT) {
9022           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9023           lit = lit >> (8*offset);
9024           if(lit&0xff) {
9025             pic16_emitcode("movlw","%d",lit);
9026             pic16_emitcode("movwf","%s",buffer);
9027
9028             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9029             //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
9030             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9031
9032           } else {
9033             pic16_emitcode("clrf","%s",buffer);
9034             //pic16_emitpcode(POC_CLRF, pic16_popRegFromString(buffer));
9035             pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
9036           }
9037         }else {
9038           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
9039           pic16_emitcode("movwf","%s",buffer);
9040
9041           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9042           //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
9043           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9044
9045         }
9046
9047         offset++;
9048     }
9049
9050     pic16_freeAsmop(right,NULL,ic,TRUE);
9051     pic16_freeAsmop(result,NULL,ic,TRUE);
9052 }
9053
9054 /*-----------------------------------------------------------------*/
9055 /* genNearPointerSet - pic16_emitcode for near pointer put                */
9056 /*-----------------------------------------------------------------*/
9057 static void genNearPointerSet (operand *right,
9058                                operand *result, 
9059                                iCode *ic)
9060 {
9061   asmop *aop = NULL;
9062   char *l;
9063   sym_link *retype;
9064   sym_link *ptype = operandType(result);
9065
9066     
9067   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9068   retype= getSpec(operandType(right));
9069
9070   pic16_aopOp(result,ic,FALSE);
9071
9072     
9073   /* if the result is rematerializable &
9074      in data space & not a bit variable */
9075   //if (AOP_TYPE(result) == AOP_IMMD &&
9076   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
9077       DCL_TYPE(ptype) == POINTER   &&
9078       !IS_BITVAR(retype)) {
9079     genDataPointerSet (right,result,ic);
9080     pic16_freeAsmop(result,NULL,ic,TRUE);
9081     return;
9082   }
9083
9084   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9085   pic16_aopOp(right,ic,FALSE);
9086   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9087
9088   /* if the value is already in a pointer register
9089      then don't need anything more */
9090   if (!AOP_INPREG(AOP(result))) {
9091     /* otherwise get a free pointer register */
9092     //aop = newAsmop(0);
9093     //preg = getFreePtr(ic,&aop,FALSE);
9094     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9095     //pic16_emitcode("mov","%s,%s",
9096     //         preg->name,
9097     //         pic16_aopGet(AOP(result),0,FALSE,TRUE));
9098     //rname = preg->name ;
9099     //pic16_emitcode("movwf","fsr0");
9100     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0));
9101     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_fsr0));
9102     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9103     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9104     goto release;
9105
9106   }// else
9107 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9108
9109   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9110
9111   /* if bitfield then unpack the bits */
9112   if (IS_BITFIELD(retype)) {
9113     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9114            "The programmer is obviously confused");
9115 //      genPackBits (retype,right,"BAD",POINTER);
9116     exit(1);
9117   }
9118   else {
9119     /* we have can just get the values */
9120     int size = AOP_SIZE(right);
9121     int offset = 0 ;    
9122
9123     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9124     while (size--) {
9125       l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9126       if (*l == '@' ) {
9127         //MOVA(l);
9128         //pic16_emitcode("mov","@%s,a",rname);
9129         pic16_emitcode("movf","indf0,w ;1");
9130       } else {
9131
9132         if (AOP_TYPE(right) == AOP_LIT) {
9133           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9134           if(lit) {
9135             pic16_emitcode("movlw","%s",l);
9136             pic16_emitcode("movwf","indf0 ;2");
9137           } else 
9138             pic16_emitcode("clrf","indf0");
9139         }else {
9140           pic16_emitcode("movf","%s,w",l);
9141           pic16_emitcode("movwf","indf0 ;2");
9142         }
9143         //pic16_emitcode("mov","@%s,%s",rname,l);
9144       }
9145       if (size)
9146         pic16_emitcode("incf","fsr0,f ;3");
9147       //pic16_emitcode("inc","%s",rname);
9148       offset++;
9149     }
9150   }
9151
9152   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9153   /* now some housekeeping stuff */
9154   if (aop) {
9155     /* we had to allocate for this iCode */
9156     pic16_freeAsmop(NULL,aop,ic,TRUE);
9157   } else { 
9158     /* we did not allocate which means left
9159        already in a pointer register, then
9160        if size > 0 && this could be used again
9161        we have to point it back to where it 
9162        belongs */
9163     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9164     if (AOP_SIZE(right) > 1 &&
9165         !OP_SYMBOL(result)->remat &&
9166         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9167           ic->depth )) {
9168       int size = AOP_SIZE(right) - 1;
9169       while (size--)
9170         pic16_emitcode("decf","fsr0,f");
9171       //pic16_emitcode("dec","%s",rname);
9172     }
9173   }
9174
9175   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9176   /* done */
9177  release:
9178   pic16_freeAsmop(right,NULL,ic,TRUE);
9179   pic16_freeAsmop(result,NULL,ic,TRUE);
9180 }
9181
9182 /*-----------------------------------------------------------------*/
9183 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
9184 /*-----------------------------------------------------------------*/
9185 static void genPagedPointerSet (operand *right,
9186                                operand *result, 
9187                                iCode *ic)
9188 {
9189     asmop *aop = NULL;
9190     regs *preg = NULL ;
9191     char *rname , *l;
9192     sym_link *retype;
9193        
9194     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9195
9196     retype= getSpec(operandType(right));
9197     
9198     pic16_aopOp(result,ic,FALSE);
9199     
9200     /* if the value is already in a pointer register
9201        then don't need anything more */
9202     if (!AOP_INPREG(AOP(result))) {
9203         /* otherwise get a free pointer register */
9204         aop = newAsmop(0);
9205         preg = getFreePtr(ic,&aop,FALSE);
9206         pic16_emitcode("mov","%s,%s",
9207                 preg->name,
9208                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9209         rname = preg->name ;
9210     } else
9211         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9212     
9213     pic16_freeAsmop(result,NULL,ic,TRUE);
9214     pic16_aopOp (right,ic,FALSE);
9215
9216     /* if bitfield then unpack the bits */
9217     if (IS_BITFIELD(retype)) 
9218         genPackBits (retype,right,rname,PPOINTER);
9219     else {
9220         /* we have can just get the values */
9221         int size = AOP_SIZE(right);
9222         int offset = 0 ;        
9223         
9224         while (size--) {
9225             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9226             
9227             MOVA(l);
9228             pic16_emitcode("movx","@%s,a",rname);
9229
9230             if (size)
9231                 pic16_emitcode("inc","%s",rname);
9232
9233             offset++;
9234         }
9235     }
9236     
9237     /* now some housekeeping stuff */
9238     if (aop) {
9239         /* we had to allocate for this iCode */
9240         pic16_freeAsmop(NULL,aop,ic,TRUE);
9241     } else { 
9242         /* we did not allocate which means left
9243            already in a pointer register, then
9244            if size > 0 && this could be used again
9245            we have to point it back to where it 
9246            belongs */
9247         if (AOP_SIZE(right) > 1 &&
9248             !OP_SYMBOL(result)->remat &&
9249             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9250               ic->depth )) {
9251             int size = AOP_SIZE(right) - 1;
9252             while (size--)
9253                 pic16_emitcode("dec","%s",rname);
9254         }
9255     }
9256
9257     /* done */
9258     pic16_freeAsmop(right,NULL,ic,TRUE);
9259     
9260         
9261 }
9262
9263 /*-----------------------------------------------------------------*/
9264 /* genFarPointerSet - set value from far space                     */
9265 /*-----------------------------------------------------------------*/
9266 static void genFarPointerSet (operand *right,
9267                               operand *result, iCode *ic)
9268 {
9269     int size, offset ;
9270     sym_link *retype = getSpec(operandType(right));
9271
9272     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9273     pic16_aopOp(result,ic,FALSE);
9274
9275     /* if the operand is already in dptr 
9276     then we do nothing else we move the value to dptr */
9277     if (AOP_TYPE(result) != AOP_STR) {
9278         /* if this is remateriazable */
9279         if (AOP_TYPE(result) == AOP_IMMD)
9280             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9281         else { /* we need to get it byte by byte */
9282             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9283             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9284             if (options.model == MODEL_FLAT24)
9285             {
9286                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9287             }
9288         }
9289     }
9290     /* so dptr know contains the address */
9291     pic16_freeAsmop(result,NULL,ic,TRUE);
9292     pic16_aopOp(right,ic,FALSE);
9293
9294     /* if bit then unpack */
9295     if (IS_BITFIELD(retype)) 
9296         genPackBits(retype,right,"dptr",FPOINTER);
9297     else {
9298         size = AOP_SIZE(right);
9299         offset = 0 ;
9300
9301         while (size--) {
9302             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9303             MOVA(l);
9304             pic16_emitcode("movx","@dptr,a");
9305             if (size)
9306                 pic16_emitcode("inc","dptr");
9307         }
9308     }
9309
9310     pic16_freeAsmop(right,NULL,ic,TRUE);
9311 }
9312
9313 /*-----------------------------------------------------------------*/
9314 /* genGenPointerSet - set value from generic pointer space         */
9315 /*-----------------------------------------------------------------*/
9316 static void genGenPointerSet (operand *right,
9317                               operand *result, iCode *ic)
9318 {
9319         int size, offset, lit;
9320         sym_link *retype = getSpec(operandType(right));
9321
9322         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9323
9324         pic16_aopOp(result,ic,FALSE);
9325         pic16_aopOp(right,ic,FALSE);
9326         size = AOP_SIZE(right);
9327         offset = 0;
9328
9329         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9330
9331
9332         /* if the operand is already in dptr 
9333                 then we do nothing else we move the value to dptr */
9334         if (AOP_TYPE(result) != AOP_STR) {
9335                 /* if this is remateriazable */
9336                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9337                 // WARNING: anythig until "else" is untested!
9338                 if (AOP_TYPE(result) == AOP_IMMD) {
9339                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9340                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
9341                         // load FSR0 from immediate
9342                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9343                         offset = 0;
9344                         while(size--) {
9345                                 if(size) {
9346                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9347                                 } else {
9348                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9349                                 }
9350                                 offset++;
9351                         }
9352                         goto release;
9353                 }
9354                 else { /* we need to get it byte by byte */
9355                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9356                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9357
9358                         // set up FSR0 with address of result
9359                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9360                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9361
9362                         /* hack hack! see if this the FSR. If so don't load W */
9363                         if(AOP_TYPE(right) != AOP_ACC) {
9364
9365                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9366
9367                                 while(size--) {
9368                                         if(size) {
9369                                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9370                                         } else {
9371                                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9372                                         }
9373                                         offset++;
9374                                 }
9375                                 goto release;
9376                         } 
9377                         // right = ACC
9378                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9379
9380                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9381                         goto release;
9382         } // if (AOP_TYPE(result) != AOP_IMMD)
9383
9384         } // if (AOP_TYPE(result) != AOP_STR)
9385         /* so dptr know contains the address */
9386
9387
9388         /* if bit then unpack */
9389         if (IS_BITFIELD(retype)) 
9390                 genPackBits(retype,right,"dptr",GPOINTER);
9391         else {
9392                 size = AOP_SIZE(right);
9393                 offset = 0 ;
9394
9395                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9396
9397                 // set up FSR0 with address of result
9398                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9399                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9400         
9401                 while (size--) {
9402                         if (AOP_TYPE(right) == AOP_LIT) {
9403                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9404                                 if (size) {
9405                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
9406                                 } else {
9407                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9408                                 }
9409                         } else { // no literal
9410                                 if(size) {
9411                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9412                                 } else {
9413                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9414                                 }
9415                         }
9416                         offset++;
9417         }
9418         }
9419
9420         release:
9421         pic16_freeAsmop(right,NULL,ic,TRUE);
9422         pic16_freeAsmop(result,NULL,ic,TRUE);
9423 }
9424
9425 /*-----------------------------------------------------------------*/
9426 /* genPointerSet - stores the value into a pointer location        */
9427 /*-----------------------------------------------------------------*/
9428 static void genPointerSet (iCode *ic)
9429 {    
9430     operand *right, *result ;
9431     sym_link *type, *etype;
9432     int p_type;
9433
9434     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9435
9436     right = IC_RIGHT(ic);
9437     result = IC_RESULT(ic) ;
9438
9439     /* depending on the type of pointer we need to
9440     move it to the correct pointer register */
9441     type = operandType(result);
9442     etype = getSpec(type);
9443     /* if left is of type of pointer then it is simple */
9444     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9445         p_type = DCL_TYPE(type);
9446     }
9447     else {
9448         /* we have to go by the storage class */
9449         p_type = PTR_TYPE(SPEC_OCLS(etype));
9450
9451 /*      if (SPEC_OCLS(etype)->codesp ) { */
9452 /*          p_type = CPOINTER ;  */
9453 /*      } */
9454 /*      else */
9455 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9456 /*              p_type = FPOINTER ; */
9457 /*          else */
9458 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9459 /*                  p_type = PPOINTER ; */
9460 /*              else */
9461 /*                  if (SPEC_OCLS(etype) == idata ) */
9462 /*                      p_type = IPOINTER ; */
9463 /*                  else */
9464 /*                      p_type = POINTER ; */
9465     }
9466
9467     /* now that we have the pointer type we assign
9468     the pointer values */
9469     switch (p_type) {
9470
9471     case POINTER:
9472     case IPOINTER:
9473         genNearPointerSet (right,result,ic);
9474         break;
9475
9476     case PPOINTER:
9477         genPagedPointerSet (right,result,ic);
9478         break;
9479
9480     case FPOINTER:
9481         genFarPointerSet (right,result,ic);
9482         break;
9483
9484     case GPOINTER:
9485         genGenPointerSet (right,result,ic);
9486         break;
9487
9488     default:
9489       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9490               "genPointerSet: illegal pointer type");
9491     }
9492 }
9493
9494 /*-----------------------------------------------------------------*/
9495 /* genIfx - generate code for Ifx statement                        */
9496 /*-----------------------------------------------------------------*/
9497 static void genIfx (iCode *ic, iCode *popIc)
9498 {
9499   operand *cond = IC_COND(ic);
9500   int isbit =0;
9501
9502   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9503
9504   pic16_aopOp(cond,ic,FALSE);
9505
9506   /* get the value into acc */
9507   if (AOP_TYPE(cond) != AOP_CRY)
9508     pic16_toBoolean(cond);
9509   else
9510     isbit = 1;
9511   /* the result is now in the accumulator */
9512   pic16_freeAsmop(cond,NULL,ic,TRUE);
9513
9514   /* if there was something to be popped then do it */
9515   if (popIc)
9516     genIpop(popIc);
9517
9518   /* if the condition is  a bit variable */
9519   if (isbit && IS_ITEMP(cond) && 
9520       SPIL_LOC(cond)) {
9521     genIfxJump(ic,SPIL_LOC(cond)->rname);
9522     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9523   }
9524   else {
9525     if (isbit && !IS_ITEMP(cond))
9526       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9527     else
9528       genIfxJump(ic,"a");
9529   }
9530   ic->generated = 1;
9531
9532 }
9533
9534 /*-----------------------------------------------------------------*/
9535 /* genAddrOf - generates code for address of                       */
9536 /*-----------------------------------------------------------------*/
9537 #if 0
9538 static void genAddrOf (iCode *ic)
9539 {
9540   operand *right, *result, *left;
9541   int size, offset ;
9542
9543   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9544
9545
9546   //pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9547
9548   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
9549   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9550   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9551
9552   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
9553
9554   size = AOP_SIZE(IC_RESULT(ic));
9555   offset = 0;
9556
9557
9558   while (size--) {
9559     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),offset));
9560     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9561     offset++;
9562   }
9563
9564
9565   pic16_freeAsmop(left,NULL,ic,FALSE);
9566   pic16_freeAsmop(result,NULL,ic,TRUE);
9567
9568 }
9569
9570 #else   /* new genAddrOf */
9571
9572 static void genAddrOf (iCode *ic)
9573 {
9574   operand *result, *left;
9575   int size;
9576   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
9577   pCodeOp *pcop0, *pcop1, *pcop2;
9578
9579         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9580
9581         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9582         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9583
9584         sym = OP_SYMBOL( left );
9585
9586         size = AOP_SIZE(IC_RESULT(ic));
9587
9588         if(pic16_debug_verbose) {
9589                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9590                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9591         }
9592         
9593         /* Assume that what we want the address of is in data space
9594          * since there is no stack on the PIC, yet! -- VR */
9595         /* low */
9596         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9597
9598         /* high */
9599         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9600         
9601         /* upper */
9602         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9603         
9604
9605         if (size == 3) {
9606                 pic16_emitpcode(POC_MOVLW, pcop0);
9607                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9608                 pic16_emitpcode(POC_MOVLW, pcop1);
9609                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9610                 pic16_emitpcode(POC_MOVLW, pcop2);
9611                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9612         } else
9613         if (size == 2) {
9614                 pic16_emitpcode(POC_MOVLW, pcop0);
9615                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9616                 pic16_emitpcode(POC_MOVLW, pcop1);
9617                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9618         } else {
9619                 pic16_emitpcode(POC_MOVLW, pcop0);
9620                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9621         }
9622
9623         pic16_freeAsmop(result,NULL,ic,TRUE);
9624         pic16_freeAsmop(left, NULL, ic, FALSE);
9625 }
9626
9627 #endif  /* new genAddrOf */
9628
9629 #if 0
9630 /*-----------------------------------------------------------------*/
9631 /* genFarFarAssign - assignment when both are in far space         */
9632 /*-----------------------------------------------------------------*/
9633 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9634 {
9635     int size = AOP_SIZE(right);
9636     int offset = 0;
9637     char *l ;
9638     /* first push the right side on to the stack */
9639     while (size--) {
9640         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9641         MOVA(l);
9642         pic16_emitcode ("push","acc");
9643     }
9644     
9645     pic16_freeAsmop(right,NULL,ic,FALSE);
9646     /* now assign DPTR to result */
9647     pic16_aopOp(result,ic,FALSE);
9648     size = AOP_SIZE(result);
9649     while (size--) {
9650         pic16_emitcode ("pop","acc");
9651         pic16_aopPut(AOP(result),"a",--offset);
9652     }
9653     pic16_freeAsmop(result,NULL,ic,FALSE);
9654         
9655 }
9656 #endif
9657
9658 /*-----------------------------------------------------------------*/
9659 /* genAssign - generate code for assignment                        */
9660 /*-----------------------------------------------------------------*/
9661 static void genAssign (iCode *ic)
9662 {
9663   operand *result, *right;
9664   int size, offset,know_W;
9665   unsigned long lit = 0L;
9666
9667   result = IC_RESULT(ic);
9668   right  = IC_RIGHT(ic) ;
9669
9670   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9671   
9672   /* if they are the same */
9673   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9674     return ;
9675
9676   pic16_aopOp(right,ic,FALSE);
9677   pic16_aopOp(result,ic,TRUE);
9678
9679   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9680
9681   /* if they are the same registers */
9682   if (pic16_sameRegs(AOP(right),AOP(result)))
9683     goto release;
9684
9685   /* if the result is a bit */
9686   if (AOP_TYPE(result) == AOP_CRY) {
9687     /* if the right size is a literal then
9688        we know what the value is */
9689     if (AOP_TYPE(right) == AOP_LIT) {
9690           
9691       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9692                   pic16_popGet(AOP(result),0));
9693
9694       if (((int) operandLitValue(right))) 
9695         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9696                        AOP(result)->aopu.aop_dir,
9697                        AOP(result)->aopu.aop_dir);
9698       else
9699         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9700                        AOP(result)->aopu.aop_dir,
9701                        AOP(result)->aopu.aop_dir);
9702       goto release;
9703     }
9704
9705     /* the right is also a bit variable */
9706     if (AOP_TYPE(right) == AOP_CRY) {
9707       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9708       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9709       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9710
9711       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9712                      AOP(result)->aopu.aop_dir,
9713                      AOP(result)->aopu.aop_dir);
9714       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
9715                      AOP(right)->aopu.aop_dir,
9716                      AOP(right)->aopu.aop_dir);
9717       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9718                      AOP(result)->aopu.aop_dir,
9719                      AOP(result)->aopu.aop_dir);
9720       goto release ;
9721     }
9722
9723     /* we need to or */
9724     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9725     pic16_toBoolean(right);
9726     emitSKPZ;
9727     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9728     //pic16_aopPut(AOP(result),"a",0);
9729     goto release ;
9730   }
9731
9732   /* bit variables done */
9733   /* general case */
9734   size = AOP_SIZE(result);
9735   offset = 0 ;
9736   if(AOP_TYPE(right) == AOP_LIT)
9737     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9738
9739 /* VR - What is this?! */
9740   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9741   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9742     if(aopIdx(AOP(result),0) == 4) {
9743   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9744       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9745       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9746       goto release;
9747     } else
9748       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9749   }
9750
9751   know_W=-1;
9752   while (size--) {
9753   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9754     if(AOP_TYPE(right) == AOP_LIT) {
9755       if(lit&0xff) {
9756         if(know_W != (lit&0xff))
9757           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9758         know_W = lit&0xff;
9759         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9760       } else
9761         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9762
9763       lit >>= 8;
9764
9765     } else if (AOP_TYPE(right) == AOP_CRY) {
9766       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9767       if(offset == 0) {
9768         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
9769         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9770       }
9771     } else {
9772   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9773
9774 #if 1
9775         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
9776            normally should work, but mind that the W register live range
9777            is not checked, so if the code generator assumes that the W
9778            is already loaded after such a pair, wrong code will be generated.
9779            
9780            Checking the live range is the next step.
9781            This is experimental code yet and has not been fully tested yet.
9782            USE WITH CARE. Revert to old code by setting 0 to the condition above.
9783            Vangelis Rokas 030603 (vrokas@otenet.gr) */
9784            
9785         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9786 #else   
9787         /* This is the old code, which is assumed(?!) that works fine(!?) */
9788
9789         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9790         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9791 #endif
9792     }
9793             
9794     offset++;
9795   }
9796
9797     
9798  release:
9799   pic16_freeAsmop (right,NULL,ic,FALSE);
9800   pic16_freeAsmop (result,NULL,ic,TRUE);
9801 }   
9802
9803 /*-----------------------------------------------------------------*/
9804 /* genJumpTab - generates code for jump table                       */
9805 /*-----------------------------------------------------------------*/
9806 static void genJumpTab (iCode *ic)
9807 {
9808     symbol *jtab;
9809     char *l;
9810
9811     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9812
9813     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9814     /* get the condition into accumulator */
9815     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9816     MOVA(l);
9817     /* multiply by three */
9818     pic16_emitcode("add","a,acc");
9819     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9820
9821     jtab = newiTempLabel(NULL);
9822     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9823     pic16_emitcode("jmp","@a+dptr");
9824     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9825
9826     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9827     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9828     emitSKPNC;
9829     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9830     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9831     pic16_emitpLabel(jtab->key);
9832
9833     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9834
9835     /* now generate the jump labels */
9836     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9837          jtab = setNextItem(IC_JTLABELS(ic))) {
9838         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9839         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9840         
9841     }
9842
9843 }
9844
9845 /*-----------------------------------------------------------------*/
9846 /* genMixedOperation - gen code for operators between mixed types  */
9847 /*-----------------------------------------------------------------*/
9848 /*
9849   TSD - Written for the PIC port - but this unfortunately is buggy.
9850   This routine is good in that it is able to efficiently promote 
9851   types to different (larger) sizes. Unfortunately, the temporary
9852   variables that are optimized out by this routine are sometimes
9853   used in other places. So until I know how to really parse the 
9854   iCode tree, I'm going to not be using this routine :(.
9855 */
9856 static int genMixedOperation (iCode *ic)
9857 {
9858 #if 0
9859   operand *result = IC_RESULT(ic);
9860   sym_link *ctype = operandType(IC_LEFT(ic));
9861   operand *right = IC_RIGHT(ic);
9862   int ret = 0;
9863   int big,small;
9864   int offset;
9865
9866   iCode *nextic;
9867   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9868
9869   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9870
9871   nextic = ic->next;
9872   if(!nextic)
9873     return 0;
9874
9875   nextright = IC_RIGHT(nextic);
9876   nextleft  = IC_LEFT(nextic);
9877   nextresult = IC_RESULT(nextic);
9878
9879   pic16_aopOp(right,ic,FALSE);
9880   pic16_aopOp(result,ic,FALSE);
9881   pic16_aopOp(nextright,  nextic, FALSE);
9882   pic16_aopOp(nextleft,   nextic, FALSE);
9883   pic16_aopOp(nextresult, nextic, FALSE);
9884
9885   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9886
9887     operand *t = right;
9888     right = nextright;
9889     nextright = t; 
9890
9891     pic16_emitcode(";remove right +","");
9892
9893   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9894 /*
9895     operand *t = right;
9896     right = nextleft;
9897     nextleft = t; 
9898 */
9899     pic16_emitcode(";remove left +","");
9900   } else
9901     return 0;
9902
9903   big = AOP_SIZE(nextleft);
9904   small = AOP_SIZE(nextright);
9905
9906   switch(nextic->op) {
9907
9908   case '+':
9909     pic16_emitcode(";optimize a +","");
9910     /* if unsigned or not an integral type */
9911     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9912       pic16_emitcode(";add a bit to something","");
9913     } else {
9914
9915       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9916
9917       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9918         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9919         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9920       } else
9921         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9922
9923       offset = 0;
9924       while(--big) {
9925
9926         offset++;
9927
9928         if(--small) {
9929           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9930             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9931             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9932           }
9933
9934           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9935           emitSKPNC;
9936           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9937                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9938                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9939           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9940           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9941
9942         } else {
9943           pic16_emitcode("rlf","known_zero,w");
9944
9945           /*
9946             if right is signed
9947               btfsc  right,7
9948                addlw ff
9949           */
9950           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9951             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9952             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9953           } else {
9954             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9955           }
9956         }
9957       }
9958       ret = 1;
9959     }
9960   }
9961   ret = 1;
9962
9963 release:
9964   pic16_freeAsmop(right,NULL,ic,TRUE);
9965   pic16_freeAsmop(result,NULL,ic,TRUE);
9966   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9967   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9968   if(ret)
9969     nextic->generated = 1;
9970
9971   return ret;
9972 #else
9973   return 0;
9974 #endif
9975 }
9976 /*-----------------------------------------------------------------*/
9977 /* genCast - gen code for casting                                  */
9978 /*-----------------------------------------------------------------*/
9979 static void genCast (iCode *ic)
9980 {
9981   operand *result = IC_RESULT(ic);
9982   sym_link *ctype = operandType(IC_LEFT(ic));
9983   sym_link *rtype = operandType(IC_RIGHT(ic));
9984   operand *right = IC_RIGHT(ic);
9985   int size, offset ;
9986
9987         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9988         /* if they are equivalent then do nothing */
9989         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9990                 return ;
9991
9992         pic16_aopOp(right,ic,FALSE) ;
9993         pic16_aopOp(result,ic,FALSE);
9994
9995         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9996
9997         /* if the result is a bit */
9998         if (AOP_TYPE(result) == AOP_CRY) {
9999         
10000                 /* if the right size is a literal then
10001                  * we know what the value is */
10002                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10003
10004                 if (AOP_TYPE(right) == AOP_LIT) {
10005                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10006                                 pic16_popGet(AOP(result),0));
10007
10008                         if (((int) operandLitValue(right))) 
10009                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10010                                         AOP(result)->aopu.aop_dir,
10011                                         AOP(result)->aopu.aop_dir);
10012                         else
10013                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10014                                         AOP(result)->aopu.aop_dir,
10015                                         AOP(result)->aopu.aop_dir);
10016                         goto release;
10017                 }
10018
10019                 /* the right is also a bit variable */
10020                 if (AOP_TYPE(right) == AOP_CRY) {
10021                         emitCLRC;
10022                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10023
10024                         pic16_emitcode("clrc","");
10025                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10026                                 AOP(right)->aopu.aop_dir,
10027                                 AOP(right)->aopu.aop_dir);
10028                         pic16_aopPut(AOP(result),"c",0);
10029                         goto release ;
10030                 }
10031
10032                 /* we need to or */
10033                 if (AOP_TYPE(right) == AOP_REG) {
10034                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10035                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10036                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10037                 }
10038                 pic16_toBoolean(right);
10039                 pic16_aopPut(AOP(result),"a",0);
10040                 goto release ;
10041         }
10042
10043         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10044           int offset = 1;
10045
10046                 size = AOP_SIZE(result);
10047
10048                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10049
10050                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10051                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10052                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10053
10054                 while (size--)
10055                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10056
10057                 goto release;
10058         }
10059
10060         /* if they are the same size : or less */
10061         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10062
10063                 /* if they are in the same place */
10064                 if (pic16_sameRegs(AOP(right),AOP(result)))
10065                         goto release;
10066
10067                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10068 #if 0
10069                 if (IS_PTR_CONST(rtype))
10070 #else
10071                 if (IS_CODEPTR(rtype))
10072 #endif
10073                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10074
10075 #if 0
10076                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10077 #else
10078                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10079 #endif
10080                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10081
10082 #if 0
10083                 if(AOP_TYPE(right) == AOP_IMMD) {
10084                   pCodeOp *pcop0, *pcop1, *pcop2;
10085                   symbol *sym = OP_SYMBOL( right );
10086
10087                         size = AOP_SIZE(result);
10088                         /* low */
10089                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10090                         /* high */
10091                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10092                         /* upper */
10093                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10094         
10095                         if (size == 3) {
10096                                 pic16_emitpcode(POC_MOVLW, pcop0);
10097                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10098                                 pic16_emitpcode(POC_MOVLW, pcop1);
10099                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10100                                 pic16_emitpcode(POC_MOVLW, pcop2);
10101                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10102                         } else
10103                         if (size == 2) {
10104                                 pic16_emitpcode(POC_MOVLW, pcop0);
10105                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10106                                 pic16_emitpcode(POC_MOVLW, pcop1);
10107                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10108                         } else {
10109                                 pic16_emitpcode(POC_MOVLW, pcop0);
10110                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10111                         }
10112                 } else
10113 #endif
10114                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10115                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10116                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10117                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10118                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10119                         if(AOP_SIZE(result) <2)
10120                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10121                 } else {
10122                         /* if they in different places then copy */
10123                         size = AOP_SIZE(result);
10124                         offset = 0 ;
10125                         while (size--) {
10126                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10127                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10128                                 offset++;
10129                         }
10130                 }
10131                 goto release;
10132         }
10133
10134         /* if the result is of type pointer */
10135         if (IS_PTR(ctype)) {
10136           int p_type;
10137           sym_link *type = operandType(right);
10138           sym_link *etype = getSpec(type);
10139
10140                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10141
10142                 /* pointer to generic pointer */
10143                 if (IS_GENPTR(ctype)) {
10144                   char *l = zero;
10145             
10146                         if (IS_PTR(type)) 
10147                                 p_type = DCL_TYPE(type);
10148                         else {
10149                 /* we have to go by the storage class */
10150                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10151
10152 /*              if (SPEC_OCLS(etype)->codesp )  */
10153 /*                  p_type = CPOINTER ;  */
10154 /*              else */
10155 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10156 /*                      p_type = FPOINTER ; */
10157 /*                  else */
10158 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10159 /*                          p_type = PPOINTER; */
10160 /*                      else */
10161 /*                          if (SPEC_OCLS(etype) == idata ) */
10162 /*                              p_type = IPOINTER ; */
10163 /*                          else */
10164 /*                              p_type = POINTER ; */
10165             }
10166                 
10167             /* the first two bytes are known */
10168       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10169             size = GPTRSIZE - 1; 
10170             offset = 0 ;
10171             while (size--) {
10172               if(offset < AOP_SIZE(right)) {
10173       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10174                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10175                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10176                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10177                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10178                 } else { 
10179                   pic16_aopPut(AOP(result),
10180                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10181                          offset);
10182                 }
10183               } else 
10184                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10185               offset++;
10186             }
10187             /* the last byte depending on type */
10188             switch (p_type) {
10189             case IPOINTER:
10190             case POINTER:
10191                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10192                 break;
10193             case FPOINTER:
10194               pic16_emitcode(";BUG!? ","%d",__LINE__);
10195                 l = one;
10196                 break;
10197             case CPOINTER:
10198               pic16_emitcode(";BUG!? ","%d",__LINE__);
10199                 l = "#0x02";
10200                 break;                          
10201             case PPOINTER:
10202               pic16_emitcode(";BUG!? ","%d",__LINE__);
10203                 l = "#0x03";
10204                 break;
10205                 
10206             default:
10207                 /* this should never happen */
10208                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10209                        "got unknown pointer type");
10210                 exit(1);
10211             }
10212             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
10213             goto release ;
10214         }
10215         
10216         /* just copy the pointers */
10217         size = AOP_SIZE(result);
10218         offset = 0 ;
10219         while (size--) {
10220             pic16_aopPut(AOP(result),
10221                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10222                    offset);
10223             offset++;
10224         }
10225         goto release ;
10226     }
10227     
10228
10229
10230     /* so we now know that the size of destination is greater
10231     than the size of the source.
10232     Now, if the next iCode is an operator then we might be
10233     able to optimize the operation without performing a cast.
10234     */
10235     if(genMixedOperation(ic))
10236       goto release;
10237
10238     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10239     
10240     /* we move to result for the size of source */
10241     size = AOP_SIZE(right);
10242     offset = 0 ;
10243     while (size--) {
10244       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
10245       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
10246       offset++;
10247     }
10248
10249     /* now depending on the sign of the destination */
10250     size = AOP_SIZE(result) - AOP_SIZE(right);
10251     /* if unsigned or not an integral type */
10252     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10253       while (size--)
10254         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10255     } else {
10256       /* we need to extend the sign :( */
10257
10258       if(size == 1) {
10259         /* Save one instruction of casting char to int */
10260         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
10261         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10262         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
10263       } else {
10264         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10265
10266         if(offset)
10267           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10268         else
10269           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10270         
10271         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
10272
10273         while (size--)
10274           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
10275       }
10276     }
10277
10278 release:
10279     pic16_freeAsmop(right,NULL,ic,TRUE);
10280     pic16_freeAsmop(result,NULL,ic,TRUE);
10281
10282 }
10283
10284 /*-----------------------------------------------------------------*/
10285 /* genDjnz - generate decrement & jump if not zero instrucion      */
10286 /*-----------------------------------------------------------------*/
10287 static int genDjnz (iCode *ic, iCode *ifx)
10288 {
10289     symbol *lbl, *lbl1;
10290     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10291
10292     if (!ifx)
10293         return 0;
10294     
10295     /* if the if condition has a false label
10296        then we cannot save */
10297     if (IC_FALSE(ifx))
10298         return 0;
10299
10300     /* if the minus is not of the form 
10301        a = a - 1 */
10302     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10303         !IS_OP_LITERAL(IC_RIGHT(ic)))
10304         return 0;
10305
10306     if (operandLitValue(IC_RIGHT(ic)) != 1)
10307         return 0;
10308
10309     /* if the size of this greater than one then no
10310        saving */
10311     if (getSize(operandType(IC_RESULT(ic))) > 1)
10312         return 0;
10313
10314     /* otherwise we can save BIG */
10315     lbl = newiTempLabel(NULL);
10316     lbl1= newiTempLabel(NULL);
10317
10318     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10319     
10320     if (IS_AOP_PREG(IC_RESULT(ic))) {
10321         pic16_emitcode("dec","%s",
10322                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10323         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10324         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10325     } else {    
10326
10327
10328       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10329       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10330
10331       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10332       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10333
10334     }
10335 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10336 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10337 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10338 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10339
10340     
10341     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10342     ifx->generated = 1;
10343     return 1;
10344 }
10345
10346 /*-----------------------------------------------------------------*/
10347 /* genReceive - generate code for a receive iCode                  */
10348 /*-----------------------------------------------------------------*/
10349 static void genReceive (iCode *ic)
10350 {    
10351         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10352
10353         if (isOperandInFarSpace(IC_RESULT(ic)) && 
10354                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10355                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10356
10357           int size = getSize(operandType(IC_RESULT(ic)));
10358           int offset =  pic16_fReturnSizePic - size;
10359
10360                 while (size--) {
10361                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10362                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10363                         offset++;
10364                 }
10365
10366                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10367
10368                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10369                 size = AOP_SIZE(IC_RESULT(ic));
10370                 offset = 0;
10371                 while (size--) {
10372                         pic16_emitcode ("pop","acc");
10373                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10374                 }
10375         } else {
10376                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
10377
10378                 _G.accInUse++;
10379                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10380                 _G.accInUse--;
10381                 assignResultValue(IC_RESULT(ic));       
10382         }
10383
10384         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10385 }
10386
10387 /*-----------------------------------------------------------------*/
10388 /* genDummyRead - generate code for dummy read of volatiles        */
10389 /*-----------------------------------------------------------------*/
10390 static void
10391 genDummyRead (iCode * ic)
10392 {
10393   pic16_emitcode ("; genDummyRead","");
10394   pic16_emitcode ("; not implemented","");
10395
10396   ic = ic;
10397 }
10398
10399 /*-----------------------------------------------------------------*/
10400 /* genpic16Code - generate code for pic16 based controllers        */
10401 /*-----------------------------------------------------------------*/
10402 /*
10403  * At this point, ralloc.c has gone through the iCode and attempted
10404  * to optimize in a way suitable for a PIC. Now we've got to generate
10405  * PIC instructions that correspond to the iCode.
10406  *
10407  * Once the instructions are generated, we'll pass through both the
10408  * peep hole optimizer and the pCode optimizer.
10409  *-----------------------------------------------------------------*/
10410
10411 void genpic16Code (iCode *lic)
10412 {
10413     iCode *ic;
10414     int cln = 0;
10415
10416     lineHead = lineCurr = NULL;
10417
10418     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10419     pic16_addpBlock(pb);
10420
10421 #if 0
10422     /* if debug information required */
10423     if (options.debug && currFunc) {
10424       if (currFunc) {
10425         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10426         _G.debugLine = 1;
10427         if (IS_STATIC(currFunc->etype)) {
10428           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
10429           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10430         } else {
10431           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
10432           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10433         }
10434         _G.debugLine = 0;
10435       }
10436     }
10437 #endif
10438
10439 //    dumpiCode(lic);
10440
10441     for (ic = lic ; ic ; ic = ic->next ) {
10442
10443 //      fprintf(stderr, "; VR = %c %x\n", ic->op, ic->op);
10444 //      DEBUGpic16_emitcode("; VR", "");
10445       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10446         if ( cln != ic->lineno ) {
10447             if ( options.debug ) {
10448                 _G.debugLine = 1;
10449                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10450                          FileBaseName(ic->filename),ic->lineno,
10451                          ic->level,ic->block);
10452                 _G.debugLine = 0;
10453             }
10454             
10455             if(!options.noCcodeInAsm) {
10456                 pic16_addpCode2pBlock(pb,
10457                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
10458                                 printCLine(ic->filename, ic->lineno)));
10459             }
10460
10461             cln = ic->lineno ;
10462         }
10463         
10464         if(options.iCodeInAsm) {
10465                 /* insert here code to print iCode as comment */
10466                 pic16_emitcomment("; ic:%d: %s", ic->seq, printILine(ic));
10467         }
10468         
10469         /* if the result is marked as
10470            spilt and rematerializable or code for
10471            this has already been generated then
10472            do nothing */
10473         if (resultRemat(ic) || ic->generated ) 
10474             continue ;
10475         
10476         /* depending on the operation */
10477         switch (ic->op) {
10478         case '!' :
10479             pic16_genNot(ic);
10480             break;
10481             
10482         case '~' :
10483             pic16_genCpl(ic);
10484             break;
10485             
10486         case UNARYMINUS:
10487             genUminus (ic);
10488             break;
10489             
10490         case IPUSH:
10491             genIpush (ic);
10492             break;
10493             
10494         case IPOP:
10495             /* IPOP happens only when trying to restore a 
10496                spilt live range, if there is an ifx statement
10497                following this pop then the if statement might
10498                be using some of the registers being popped which
10499                would destroy the contents of the register so
10500                we need to check for this condition and handle it */
10501             if (ic->next            && 
10502                 ic->next->op == IFX &&
10503                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10504                 genIfx (ic->next,ic);
10505             else
10506                 genIpop (ic);
10507             break; 
10508             
10509         case CALL:
10510             genCall (ic);
10511             break;
10512             
10513         case PCALL:
10514             genPcall (ic);
10515             break;
10516             
10517         case FUNCTION:
10518             genFunction (ic);
10519             break;
10520             
10521         case ENDFUNCTION:
10522             genEndFunction (ic);
10523             break;
10524             
10525         case RETURN:
10526             genRet (ic);
10527             break;
10528             
10529         case LABEL:
10530             genLabel (ic);
10531             break;
10532             
10533         case GOTO:
10534             genGoto (ic);
10535             break;
10536             
10537         case '+' :
10538             pic16_genPlus (ic) ;
10539             break;
10540             
10541         case '-' :
10542             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10543                 pic16_genMinus (ic);
10544             break;
10545             
10546         case '*' :
10547             genMult (ic);
10548             break;
10549             
10550         case '/' :
10551             genDiv (ic) ;
10552             break;
10553             
10554         case '%' :
10555             genMod (ic);
10556             break;
10557             
10558         case '>' :
10559             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10560             break;
10561             
10562         case '<' :
10563             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10564             break;
10565             
10566         case LE_OP:
10567         case GE_OP:
10568         case NE_OP:
10569             
10570             /* note these two are xlated by algebraic equivalence
10571                during parsing SDCC.y */
10572             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10573                    "got '>=' or '<=' shouldn't have come here");
10574             break;      
10575             
10576         case EQ_OP:
10577             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10578             break;          
10579             
10580         case AND_OP:
10581             genAndOp (ic);
10582             break;
10583             
10584         case OR_OP:
10585             genOrOp (ic);
10586             break;
10587             
10588         case '^' :
10589             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10590             break;
10591             
10592         case '|' :
10593                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10594             break;
10595             
10596         case BITWISEAND:
10597             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10598             break;
10599             
10600         case INLINEASM:
10601             genInline (ic);
10602             break;
10603             
10604         case RRC:
10605             genRRC (ic);
10606             break;
10607             
10608         case RLC:
10609             genRLC (ic);
10610             break;
10611             
10612         case GETHBIT:
10613             genGetHbit (ic);
10614             break;
10615             
10616         case LEFT_OP:
10617             genLeftShift (ic);
10618             break;
10619             
10620         case RIGHT_OP:
10621             genRightShift (ic);
10622             break;
10623             
10624         case GET_VALUE_AT_ADDRESS:
10625             genPointerGet(ic);
10626             break;
10627             
10628         case '=' :
10629             if (POINTER_SET(ic))
10630                 genPointerSet(ic);
10631             else
10632                 genAssign(ic);
10633             break;
10634             
10635         case IFX:
10636             genIfx (ic,NULL);
10637             break;
10638             
10639         case ADDRESS_OF:
10640             genAddrOf (ic);
10641             break;
10642             
10643         case JUMPTABLE:
10644             genJumpTab (ic);
10645             break;
10646             
10647         case CAST:
10648             genCast (ic);
10649             break;
10650             
10651         case RECEIVE:
10652             genReceive(ic);
10653             break;
10654             
10655         case SEND:
10656             addSet(&_G.sendSet,ic);
10657             break;
10658
10659         case DUMMY_READ_VOLATILE:
10660           genDummyRead (ic);
10661           break;
10662
10663         default :
10664             ic = ic;
10665         }
10666     }
10667
10668
10669     /* now we are ready to call the
10670        peep hole optimizer */
10671     if (!options.nopeep) {
10672       peepHole (&lineHead);
10673     }
10674     /* now do the actual printing */
10675     printLine (lineHead,codeOutFile);
10676
10677 #ifdef PCODE_DEBUG
10678     DFPRINTF((stderr,"printing pBlock\n\n"));
10679     pic16_printpBlock(stdout,pb);
10680 #endif
10681
10682     return;
10683 }
10684