* src/mcs51/gen.c (genNearPointerGet, genPagedPointerGet,
[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 /*-----------------------------------------------------------------*/
469 /* pointerCode - returns the code for a pointer type               */
470 /*-----------------------------------------------------------------*/
471 static int pointerCode (sym_link *etype)
472 {
473
474     return PTR_TYPE(SPEC_OCLS(etype));
475
476 }
477
478 /*-----------------------------------------------------------------*/
479 /* aopForSym - for a true symbol                                   */
480 /*-----------------------------------------------------------------*/
481 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
482 {
483     asmop *aop;
484     memmap *space= SPEC_OCLS(sym->etype);
485
486     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
487     /* if already has one */
488     if (sym->aop) {
489             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
490         return sym->aop;
491     }
492
493     /* assign depending on the storage class */
494     /* if it is on the stack or indirectly addressable */
495     /* space we need to assign either r0 or r1 to it   */    
496     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
497         sym->aop = aop = newAsmop(0);
498         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
499         aop->size = getSize(sym->type);
500
501         /* now assign the address of the variable to 
502         the pointer register */
503         if (aop->type != AOP_STK) {
504
505             if (sym->onStack) {
506                     if ( _G.accInUse )
507                         pic16_emitcode("push","acc");
508
509                     pic16_emitcode("mov","a,_bp");
510                     pic16_emitcode("add","a,#0x%02x",
511                              ((sym->stack < 0) ?
512                               ((char)(sym->stack - _G.nRegsSaved )) :
513                               ((char)sym->stack)) & 0xff);
514                     pic16_emitcode("mov","%s,a",
515                              aop->aopu.aop_ptr->name);
516
517                     if ( _G.accInUse )
518                         pic16_emitcode("pop","acc");
519             } else
520                 pic16_emitcode("mov","%s,#%s",
521                          aop->aopu.aop_ptr->name,
522                          sym->rname);
523             aop->paged = space->paged;
524         } else
525             aop->aopu.aop_stk = sym->stack;
526         return aop;
527     }
528     
529     if (sym->onStack && options.stack10bit)
530     {
531         /* It's on the 10 bit stack, which is located in
532          * far data space.
533          */
534          
535       //DEBUGpic16_emitcode(";","%d",__LINE__);
536
537         if ( _G.accInUse )
538                 pic16_emitcode("push","acc");
539
540         pic16_emitcode("mov","a,_bp");
541         pic16_emitcode("add","a,#0x%02x",
542                  ((sym->stack < 0) ?
543                    ((char)(sym->stack - _G.nRegsSaved )) :
544                    ((char)sym->stack)) & 0xff);
545         
546         genSetDPTR(1);
547         pic16_emitcode ("mov","dpx1,#0x40");
548         pic16_emitcode ("mov","dph1,#0x00");
549         pic16_emitcode ("mov","dpl1, a");
550         genSetDPTR(0);
551         
552         if ( _G.accInUse )
553             pic16_emitcode("pop","acc");
554             
555         sym->aop = aop = newAsmop(AOP_DPTR2);
556         aop->size = getSize(sym->type); 
557         return aop;
558     }
559
560     //DEBUGpic16_emitcode(";","%d",__LINE__);
561     /* if in bit space */
562     if (IN_BITSPACE(space)) {
563         sym->aop = aop = newAsmop (AOP_CRY);
564         aop->aopu.aop_dir = sym->rname ;
565         aop->size = getSize(sym->type);
566         //DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
567         return aop;
568     }
569     /* if it is in direct space */
570     if (IN_DIRSPACE(space)) {
571         sym->aop = aop = newAsmop (AOP_DIR);
572         aop->aopu.aop_dir = sym->rname ;
573         aop->size = getSize(sym->type);
574         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
575         return aop;
576     }
577
578     /* special case for a function */
579     if (IS_FUNC(sym->type)) {   
580         sym->aop = aop = newAsmop(AOP_IMMD);    
581         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
582         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
583         strcpy(aop->aopu.aop_immd,sym->rname);
584         aop->size = FPTRSIZE; 
585         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
586         return aop;
587     }
588
589
590     /* only remaining is far space */
591     /* in which case DPTR gets the address */
592     sym->aop = aop = newAsmop(AOP_PCODE);
593
594     aop->aopu.pcop = pic16_popGetImmd(sym->rname,0,0);
595     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
596     PCOI(aop->aopu.pcop)->index = 0;
597
598     DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
599                         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
600
601     pic16_allocDirReg (IC_LEFT(ic));
602
603     aop->size = FPTRSIZE; 
604 /*
605     DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
606     sym->aop = aop = newAsmop(AOP_DPTR);
607     pic16_emitcode ("mov","dptr,#%s", sym->rname);
608     aop->size = getSize(sym->type);
609
610     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
611 */
612
613     /* if it is in code space */
614     if (IN_CODESPACE(space))
615         aop->code = 1;
616
617     return aop;     
618 }
619
620 /*-----------------------------------------------------------------*/
621 /* aopForRemat - rematerialzes an object                           */
622 /*-----------------------------------------------------------------*/
623 static asmop *aopForRemat (operand *op) // x symbol *sym)
624 {
625   symbol *sym = OP_SYMBOL(op);
626   iCode *ic = NULL;
627   asmop *aop = newAsmop(AOP_PCODE);
628   int val = 0;
629   int offset = 0;
630
631   ic = sym->rematiCode;
632
633   DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
634   if(IS_OP_POINTER(op)) {
635     DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
636   }
637   for (;;) {
638     if (ic->op == '+') {
639       val += (int) operandLitValue(IC_RIGHT(ic));
640     } else if (ic->op == '-') {
641       val -= (int) operandLitValue(IC_RIGHT(ic));
642     } else
643       break;
644         
645     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
646   }
647
648   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
649   aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
650 #if 0
651   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
652 #else
653   PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
654 #endif
655   PCOI(aop->aopu.pcop)->index = val;
656
657   DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
658                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
659 #if 0
660                       val, IS_PTR_CONST(operandType(op)));
661 #else
662                       val, IS_CODEPTR(operandType(op)));
663 #endif
664
665   //    DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
666
667   pic16_allocDirReg (IC_LEFT(ic));
668
669   return aop;        
670 }
671
672 static int aopIdx (asmop *aop, int offset)
673 {
674   if(!aop)
675     return -1;
676
677   if(aop->type !=  AOP_REG)
678     return -2;
679         
680   return aop->aopu.aop_reg[offset]->rIdx;
681
682 }
683 /*-----------------------------------------------------------------*/
684 /* regsInCommon - two operands have some registers in common       */
685 /*-----------------------------------------------------------------*/
686 static bool regsInCommon (operand *op1, operand *op2)
687 {
688     symbol *sym1, *sym2;
689     int i;
690
691     /* if they have registers in common */
692     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
693         return FALSE ;
694
695     sym1 = OP_SYMBOL(op1);
696     sym2 = OP_SYMBOL(op2);
697
698     if (sym1->nRegs == 0 || sym2->nRegs == 0)
699         return FALSE ;
700
701     for (i = 0 ; i < sym1->nRegs ; i++) {
702         int j;
703         if (!sym1->regs[i])
704             continue ;
705
706         for (j = 0 ; j < sym2->nRegs ;j++ ) {
707             if (!sym2->regs[j])
708                 continue ;
709
710             if (sym2->regs[j] == sym1->regs[i])
711                 return TRUE ;
712         }
713     }
714
715     return FALSE ;
716 }
717
718 /*-----------------------------------------------------------------*/
719 /* operandsEqu - equivalent                                        */
720 /*-----------------------------------------------------------------*/
721 static bool operandsEqu ( operand *op1, operand *op2)
722 {
723     symbol *sym1, *sym2;
724
725     /* if they not symbols */
726     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
727         return FALSE;
728
729     sym1 = OP_SYMBOL(op1);
730     sym2 = OP_SYMBOL(op2);
731
732     /* if both are itemps & one is spilt
733        and the other is not then false */
734     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
735         sym1->isspilt != sym2->isspilt )
736         return FALSE ;
737
738     /* if they are the same */
739     if (sym1 == sym2)
740         return TRUE ;
741
742     if (strcmp(sym1->rname,sym2->rname) == 0)
743         return TRUE;
744
745
746     /* if left is a tmp & right is not */
747     if (IS_ITEMP(op1)  && 
748         !IS_ITEMP(op2) &&
749         sym1->isspilt  &&
750         (sym1->usl.spillLoc == sym2))
751         return TRUE;
752
753     if (IS_ITEMP(op2)  && 
754         !IS_ITEMP(op1) &&
755         sym2->isspilt  &&
756         sym1->level > 0 &&
757         (sym2->usl.spillLoc == sym1))
758         return TRUE ;
759
760     return FALSE ;
761 }
762
763 /*-----------------------------------------------------------------*/
764 /* pic16_sameRegs - two asmops have the same registers                   */
765 /*-----------------------------------------------------------------*/
766 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
767 {
768     int i;
769
770     if (aop1 == aop2)
771         return TRUE ;
772
773     if (aop1->type != AOP_REG ||
774         aop2->type != AOP_REG )
775         return FALSE ;
776
777     if (aop1->size != aop2->size )
778         return FALSE ;
779
780     for (i = 0 ; i < aop1->size ; i++ )
781         if (aop1->aopu.aop_reg[i] !=
782             aop2->aopu.aop_reg[i] )
783             return FALSE ;
784
785     return TRUE ;
786 }
787
788 /*-----------------------------------------------------------------*/
789 /* pic16_aopOp - allocates an asmop for an operand  :                    */
790 /*-----------------------------------------------------------------*/
791 void pic16_aopOp (operand *op, iCode *ic, bool result)
792 {
793     asmop *aop;
794     symbol *sym;
795     int i;
796
797     if (!op)
798         return ;
799
800 //      DEBUGpic16_emitcode(";","%d",__LINE__);
801
802     /* if this a literal */
803     if (IS_OP_LITERAL(op)) {
804         op->aop = aop = newAsmop(AOP_LIT);
805         aop->aopu.aop_lit = op->operand.valOperand;
806         aop->size = getSize(operandType(op));
807         return;
808     }
809
810     {
811       sym_link *type = operandType(op);
812 #if 0
813       if(IS_PTR_CONST(type))
814 #else
815       if(IS_CODEPTR(type))
816 #endif
817         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
818     }
819
820     /* if already has a asmop then continue */
821     if (op->aop)
822         return ;
823
824     /* if the underlying symbol has a aop */
825     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
826       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
827         op->aop = OP_SYMBOL(op)->aop;
828         return;
829     }
830
831     /* if this is a true symbol */
832     if (IS_TRUE_SYMOP(op)) {    
833         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
834       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
835       return ;
836     }
837
838     /* this is a temporary : this has
839     only four choices :
840     a) register
841     b) spillocation
842     c) rematerialize 
843     d) conditional   
844     e) can be a return use only */
845
846     sym = OP_SYMBOL(op);
847
848         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
849     /* if the type is a conditional */
850     if (sym->regType == REG_CND) {
851         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
852         aop->size = 0;
853         return;
854     }
855
856     /* if it is spilt then two situations
857     a) is rematerialize 
858     b) has a spill location */
859     if (sym->isspilt || sym->nRegs == 0) {
860
861       DEBUGpic16_emitcode(";","%d",__LINE__);
862         /* rematerialize it NOW */
863         if (sym->remat) {
864
865             sym->aop = op->aop = aop =
866                                       aopForRemat (op);
867             aop->size = getSize(sym->type);
868             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
869             return;
870         }
871
872         if (sym->accuse) {
873             int i;
874             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
875             aop->size = getSize(sym->type);
876             for ( i = 0 ; i < 2 ; i++ )
877                 aop->aopu.aop_str[i] = accUse[i];
878             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
879             return;  
880         }
881
882         if (sym->ruonly ) {
883           /*
884           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
885           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
886           //pic16_allocDirReg (IC_LEFT(ic));
887           aop->size = getSize(sym->type);
888           */
889
890           unsigned i;
891
892           aop = op->aop = sym->aop = newAsmop(AOP_STR);
893           aop->size = getSize(sym->type);
894           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
895             aop->aopu.aop_str[i] = fReturn[i];
896
897           DEBUGpic16_emitcode(";","%d",__LINE__);
898           return;
899         }
900
901         /* else spill location  */
902         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
903             /* force a new aop if sizes differ */
904             sym->usl.spillLoc->aop = NULL;
905         }
906         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
907                             __FUNCTION__,__LINE__,
908                             sym->usl.spillLoc->rname,
909                             sym->rname, sym->usl.spillLoc->offset);
910
911         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
912         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
913         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
914                                           getSize(sym->type), 
915                                           sym->usl.spillLoc->offset);
916         aop->size = getSize(sym->type);
917
918         return;
919     }
920
921     {
922       sym_link *type = operandType(op);
923 #if 0
924       if(IS_PTR_CONST(type)) 
925 #else
926       if(IS_CODEPTR(type)) 
927 #endif
928         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
929     }
930
931     /* must be in a register */
932     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
933     sym->aop = op->aop = aop = newAsmop(AOP_REG);
934     aop->size = sym->nRegs;
935     for ( i = 0 ; i < sym->nRegs ;i++)
936         aop->aopu.aop_reg[i] = sym->regs[i];
937 }
938
939 /*-----------------------------------------------------------------*/
940 /* pic16_freeAsmop - free up the asmop given to an operand               */
941 /*----------------------------------------------------------------*/
942 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
943 {   
944     asmop *aop ;
945
946     if (!op)
947         aop = aaop;
948     else 
949         aop = op->aop;
950
951     if (!aop)
952         return ;
953
954     if (aop->freed)
955         goto dealloc; 
956
957     aop->freed = 1;
958
959     /* depending on the asmop type only three cases need work AOP_RO
960        , AOP_R1 && AOP_STK */
961 #if 0
962     switch (aop->type) {
963         case AOP_R0 :
964             if (_G.r0Pushed ) {
965                 if (pop) {
966                     pic16_emitcode ("pop","ar0");     
967                     _G.r0Pushed--;
968                 }
969             }
970             bitVectUnSetBit(ic->rUsed,R0_IDX);
971             break;
972
973         case AOP_R1 :
974             if (_G.r1Pushed ) {
975                 if (pop) {
976                     pic16_emitcode ("pop","ar1");
977                     _G.r1Pushed--;
978                 }
979             }
980             bitVectUnSetBit(ic->rUsed,R1_IDX);          
981             break;
982
983         case AOP_STK :
984         {
985             int sz = aop->size;    
986             int stk = aop->aopu.aop_stk + aop->size;
987             bitVectUnSetBit(ic->rUsed,R0_IDX);
988             bitVectUnSetBit(ic->rUsed,R1_IDX);          
989
990             getFreePtr(ic,&aop,FALSE);
991             
992             if (options.stack10bit)
993             {
994                 /* I'm not sure what to do here yet... */
995                 /* #STUB */
996                 fprintf(stderr, 
997                         "*** Warning: probably generating bad code for "
998                         "10 bit stack mode.\n");
999             }
1000             
1001             if (stk) {
1002                 pic16_emitcode ("mov","a,_bp");
1003                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1004                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1005             } else {
1006                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1007             }
1008
1009             while (sz--) {
1010                 pic16_emitcode("pop","acc");
1011                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1012                 if (!sz) break;
1013                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1014             }
1015             op->aop = aop;
1016             pic16_freeAsmop(op,NULL,ic,TRUE);
1017             if (_G.r0Pushed) {
1018                 pic16_emitcode("pop","ar0");
1019                 _G.r0Pushed--;
1020             }
1021
1022             if (_G.r1Pushed) {
1023                 pic16_emitcode("pop","ar1");
1024                 _G.r1Pushed--;
1025             }       
1026         }
1027     }
1028 #endif
1029
1030 dealloc:
1031     /* all other cases just dealloc */
1032     if (op ) {
1033         op->aop = NULL;
1034         if (IS_SYMOP(op)) {
1035             OP_SYMBOL(op)->aop = NULL;    
1036             /* if the symbol has a spill */
1037             if (SPIL_LOC(op))
1038                 SPIL_LOC(op)->aop = NULL;
1039         }
1040     }
1041 }
1042
1043 /*-----------------------------------------------------------------*/
1044 /* pic16_aopGet - for fetching value of the aop                          */
1045 /*-----------------------------------------------------------------*/
1046 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1047 {
1048     char *s = buffer ;
1049     char *rs;
1050
1051     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1052     /* offset is greater than
1053     size then zero */
1054     if (offset > (aop->size - 1) &&
1055         aop->type != AOP_LIT)
1056         return zero;
1057
1058     /* depending on type */
1059     switch (aop->type) {
1060         
1061     case AOP_R0:
1062     case AOP_R1:
1063         DEBUGpic16_emitcode(";","%d",__LINE__);
1064         /* if we need to increment it */       
1065         while (offset > aop->coff) {        
1066             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1067             aop->coff++;
1068         }
1069         
1070         while (offset < aop->coff) {
1071             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1072             aop->coff--;
1073         }
1074         
1075         aop->coff = offset ;
1076         if (aop->paged) {
1077             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1078             return (dname ? "acc" : "a");
1079         }       
1080         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1081         rs = Safe_calloc(1,strlen(s)+1);
1082         strcpy(rs,s);   
1083         return rs;
1084         
1085     case AOP_DPTR:
1086     case AOP_DPTR2:
1087         DEBUGpic16_emitcode(";","%d",__LINE__);
1088     if (aop->type == AOP_DPTR2)
1089     {
1090         genSetDPTR(1);
1091     }
1092     
1093         while (offset > aop->coff) {
1094             pic16_emitcode ("inc","dptr");
1095             aop->coff++;
1096         }
1097         
1098         while (offset < aop->coff) {        
1099             pic16_emitcode("lcall","__decdptr");
1100             aop->coff--;
1101         }
1102         
1103         aop->coff = offset;
1104         if (aop->code) {
1105             pic16_emitcode("clr","a");
1106             pic16_emitcode("movc","a,@a+dptr");
1107         }
1108     else {
1109             pic16_emitcode("movx","a,@dptr");
1110     }
1111             
1112     if (aop->type == AOP_DPTR2)
1113     {
1114         genSetDPTR(0);
1115     }
1116             
1117     return (dname ? "acc" : "a");
1118         
1119         
1120     case AOP_IMMD:
1121         if (bit16) 
1122             sprintf (s,"%s",aop->aopu.aop_immd);
1123         else
1124             if (offset) 
1125                 sprintf(s,"(%s >> %d)",
1126                         aop->aopu.aop_immd,
1127                         offset*8);
1128             else
1129                 sprintf(s,"%s",
1130                         aop->aopu.aop_immd);
1131         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1132         rs = Safe_calloc(1,strlen(s)+1);
1133         strcpy(rs,s);   
1134         return rs;
1135         
1136     case AOP_DIR:
1137       if (offset) {
1138         sprintf(s,"(%s + %d)",
1139                 aop->aopu.aop_dir,
1140                 offset);
1141         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1142       } else
1143             sprintf(s,"%s",aop->aopu.aop_dir);
1144         rs = Safe_calloc(1,strlen(s)+1);
1145         strcpy(rs,s);   
1146         return rs;
1147         
1148     case AOP_REG:
1149       //if (dname) 
1150       //    return aop->aopu.aop_reg[offset]->dname;
1151       //else
1152             return aop->aopu.aop_reg[offset]->name;
1153         
1154     case AOP_CRY:
1155       //pic16_emitcode(";","%d",__LINE__);
1156       return aop->aopu.aop_dir;
1157         
1158     case AOP_ACC:
1159         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1160         return "AOP_accumulator_bug";
1161
1162     case AOP_LIT:
1163         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1164         rs = Safe_calloc(1,strlen(s)+1);
1165         strcpy(rs,s);   
1166         return rs;
1167         
1168     case AOP_STR:
1169         aop->coff = offset ;
1170         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1171             dname)
1172             return "acc";
1173         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1174         
1175         return aop->aopu.aop_str[offset];
1176         
1177     case AOP_PCODE:
1178       {
1179         pCodeOp *pcop = aop->aopu.pcop;
1180         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1181         if(pcop->name) {
1182           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1183           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1184           sprintf(s,"%s", pcop->name);
1185         } else
1186           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1187
1188       }
1189       rs = Safe_calloc(1,strlen(s)+1);
1190       strcpy(rs,s);   
1191       return rs;
1192
1193     }
1194
1195     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1196            "aopget got unsupported aop->type");
1197     exit(0);
1198 }
1199
1200
1201 /*-----------------------------------------------------------------*/
1202 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1203 /*-----------------------------------------------------------------*/
1204 pCodeOp *pic16_popGetTempReg(void)
1205 {
1206
1207   pCodeOp *pcop;
1208
1209   pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1210   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1211     PCOR(pcop)->r->wasUsed=1;
1212     PCOR(pcop)->r->isFree=0;
1213   }
1214
1215   return pcop;
1216 }
1217
1218 /*-----------------------------------------------------------------*/
1219 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1220 /*-----------------------------------------------------------------*/
1221 void pic16_popReleaseTempReg(pCodeOp *pcop)
1222 {
1223
1224   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1225     PCOR(pcop)->r->isFree = 1;
1226
1227 }
1228 /*-----------------------------------------------------------------*/
1229 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1230 /*-----------------------------------------------------------------*/
1231 pCodeOp *pic16_popGetLabel(unsigned int key)
1232 {
1233
1234   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1235
1236   if(key>max_key)
1237     max_key = key;
1238
1239   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1240 }
1241
1242 /*-----------------------------------------------------------------*/
1243 /* pic16_popCopyReg - copy a pcode operator                              */
1244 /*-----------------------------------------------------------------*/
1245 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1246 {
1247   pCodeOpReg *pcor;
1248
1249   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1250   pcor->pcop.type = pc->pcop.type;
1251   if(pc->pcop.name) {
1252     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1253       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1254   } else
1255     pcor->pcop.name = NULL;
1256
1257   pcor->r = pc->r;
1258   pcor->rIdx = pc->rIdx;
1259   pcor->r->wasUsed=1;
1260
1261   //DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1262
1263   return PCOP(pcor);
1264 }
1265
1266 /*-----------------------------------------------------------------*/
1267 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1268 /*-----------------------------------------------------------------*/
1269 pCodeOp *pic16_popGetLit(unsigned int lit)
1270 {
1271   return pic16_newpCodeOpLit(lit);
1272 }
1273
1274 /*-----------------------------------------------------------------*/
1275 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1276 /*-----------------------------------------------------------------*/
1277 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1278 {
1279   return pic16_newpCodeOpLit2(lit, arg2);
1280 }
1281
1282
1283 /*-----------------------------------------------------------------*/
1284 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1285 /*-----------------------------------------------------------------*/
1286 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1287 {
1288
1289   return pic16_newpCodeOpImmd(name, offset,index, 0);
1290 }
1291
1292
1293 /*-----------------------------------------------------------------*/
1294 /* pic16_popGet - asm operator to pcode operator conversion              */
1295 /*-----------------------------------------------------------------*/
1296 pCodeOp *pic16_popGetWithString(char *str)
1297 {
1298   pCodeOp *pcop;
1299
1300
1301   if(!str) {
1302     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1303     exit (1);
1304   }
1305
1306   pcop = pic16_newpCodeOp(str,PO_STR);
1307
1308   return pcop;
1309 }
1310
1311 /*-----------------------------------------------------------------*/
1312 /* pic16_popRegFromString -                                        */
1313 /*-----------------------------------------------------------------*/
1314 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1315 {
1316
1317   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1318   pcop->type = PO_DIR;
1319
1320   DEBUGpic16_emitcode(";","%d %s %s",__LINE__, __FUNCTION__, str);
1321 //  fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1322
1323   if(!str)
1324     str = "BAD_STRING";
1325
1326   pcop->name = Safe_calloc(1,strlen(str)+1);
1327   strcpy(pcop->name,str);
1328
1329   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1330
1331   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1332   if(PCOR(pcop)->r == NULL) {
1333 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1334 //              __FUNCTION__, __LINE__, str, size, offset);
1335     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1336
1337         //fprintf(stderr, "allocating new register -> %s\n", str);
1338
1339     DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1340   } else {
1341     DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1342   }
1343   PCOR(pcop)->instance = offset;
1344
1345   return pcop;
1346 }
1347
1348 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1349 {
1350   pCodeOp *pcop;
1351
1352 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1353
1354         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1355         PCOR(pcop)->rIdx = rIdx;
1356         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1357         PCOR(pcop)->r->isFree = 0;
1358         PCOR(pcop)->r->wasUsed = 1;
1359
1360         pcop->type = PCOR(pcop)->r->pc_type;
1361
1362   return pcop;
1363 }
1364
1365 /*---------------------------------------------------------------------------------*/
1366 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1367 /*                 VR 030601                                                       */
1368 /*---------------------------------------------------------------------------------*/
1369 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1370 {
1371   pCodeOpReg2 *pcop2;
1372   pCodeOp *temp;
1373   
1374         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1375
1376         /* comment the following check, so errors to throw up */
1377 //      if(!pcop2)return NULL;
1378
1379         temp = pic16_popGet(aop_dst, offset);
1380         pcop2->pcop2 = temp;
1381         
1382   return PCOP(pcop2);
1383 }
1384
1385 /*---------------------------------------------------------------------------------*/
1386 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1387 /*                     movff instruction                                           */
1388 /*---------------------------------------------------------------------------------*/
1389 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1390 {
1391   pCodeOpReg2 *pcop2;
1392
1393         if(!noalloc) {
1394                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1395                 pcop2->pcop2 = pic16_popCopyReg(dst);
1396         } else {
1397                 /* the pCodeOp may be already allocated */
1398                 pcop2 = (pCodeOpReg2 *)(src);
1399                 pcop2->pcop2 = (pCodeOp *)(dst);
1400         }
1401
1402   return PCOP(pcop2);
1403 }
1404
1405
1406 /*-----------------------------------------------------------------*/
1407 /* pic16_popGet - asm operator to pcode operator conversion              */
1408 /*-----------------------------------------------------------------*/
1409 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1410 {
1411   //char *s = buffer ;
1412     //char *rs;
1413
1414     pCodeOp *pcop;
1415
1416     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1417     /* offset is greater than
1418     size then zero */
1419
1420     if (offset > (aop->size - 1) &&
1421         aop->type != AOP_LIT)
1422       return NULL;  //zero;
1423
1424     /* depending on type */
1425     switch (aop->type) {
1426         
1427     case AOP_R0:
1428     case AOP_R1:
1429     case AOP_DPTR:
1430     case AOP_DPTR2:
1431     case AOP_ACC:
1432         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1433         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1434         return NULL;
1435         
1436     case AOP_IMMD:
1437       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1438       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1439
1440     case AOP_DIR:
1441       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1442       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1443         
1444     case AOP_REG:
1445       {
1446         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1447
1448         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1449         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1450         PCOR(pcop)->rIdx = rIdx;
1451         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1452         PCOR(pcop)->r->wasUsed=1;
1453         PCOR(pcop)->r->isFree=0;
1454
1455         PCOR(pcop)->instance = offset;
1456         pcop->type = PCOR(pcop)->r->pc_type;
1457         //rs = aop->aopu.aop_reg[offset]->name;
1458         //DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1459         return pcop;
1460       }
1461
1462     case AOP_CRY:
1463         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1464
1465       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1466       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1467       //if(PCOR(pcop)->r == NULL)
1468       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1469       return pcop;
1470         
1471     case AOP_LIT:
1472         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1473       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1474
1475     case AOP_STR:
1476       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1477       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1478
1479       /*
1480       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1481       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1482       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1483       pcop->type = PCOR(pcop)->r->pc_type;
1484       pcop->name = PCOR(pcop)->r->name;
1485
1486       return pcop;
1487       */
1488
1489     case AOP_PCODE:
1490       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s",pic16_pCodeOpType(aop->aopu.pcop),
1491                           __LINE__, 
1492                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1493       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1494       PCOI(pcop)->offset = offset;
1495       return pcop;
1496     }
1497
1498     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1499            "pic16_popGet got unsupported aop->type");
1500     exit(0);
1501 }
1502 /*-----------------------------------------------------------------*/
1503 /* pic16_aopPut - puts a string for a aop                                */
1504 /*-----------------------------------------------------------------*/
1505 void pic16_aopPut (asmop *aop, char *s, int offset)
1506 {
1507     char *d = buffer ;
1508     symbol *lbl ;
1509
1510     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1511
1512     if (aop->size && offset > ( aop->size - 1)) {
1513         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1514                "pic16_aopPut got offset > aop->size");
1515         exit(0);
1516     }
1517
1518     /* will assign value to value */
1519     /* depending on where it is ofcourse */
1520     switch (aop->type) {
1521     case AOP_DIR:
1522       if (offset) {
1523         sprintf(d,"(%s + %d)",
1524                 aop->aopu.aop_dir,offset);
1525         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1526
1527       } else
1528             sprintf(d,"%s",aop->aopu.aop_dir);
1529         
1530         if (strcmp(d,s)) {
1531           DEBUGpic16_emitcode(";","%d",__LINE__);
1532           if(strcmp(s,"W"))
1533             pic16_emitcode("movf","%s,w",s);
1534           pic16_emitcode("movwf","%s",d);
1535
1536           if(strcmp(s,"W")) {
1537             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1538             if(offset >= aop->size) {
1539               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1540               break;
1541             } else
1542               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1543           }
1544
1545           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1546
1547
1548         }
1549         break;
1550         
1551     case AOP_REG:
1552       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1553         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1554           /*
1555             if (*s == '@'           ||
1556                 strcmp(s,"r0") == 0 ||
1557                 strcmp(s,"r1") == 0 ||
1558                 strcmp(s,"r2") == 0 ||
1559                 strcmp(s,"r3") == 0 ||
1560                 strcmp(s,"r4") == 0 ||
1561                 strcmp(s,"r5") == 0 ||
1562                 strcmp(s,"r6") == 0 || 
1563                 strcmp(s,"r7") == 0 )
1564                 pic16_emitcode("mov","%s,%s  ; %d",
1565                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1566             else
1567           */
1568
1569           if(strcmp(s,"W")==0 )
1570             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1571
1572           pic16_emitcode("movwf","%s",
1573                    aop->aopu.aop_reg[offset]->name);
1574
1575           if(strcmp(s,zero)==0) {
1576             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1577
1578           } else if(strcmp(s,"W")==0) {
1579             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1580             pcop->type = PO_GPR_REGISTER;
1581
1582             PCOR(pcop)->rIdx = -1;
1583             PCOR(pcop)->r = NULL;
1584
1585             DEBUGpic16_emitcode(";","%d",__LINE__);
1586             pcop->name = Safe_strdup(s);
1587             pic16_emitpcode(POC_MOVFW,pcop);
1588             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1589           } else if(strcmp(s,one)==0) {
1590             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1591             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1592           } else {
1593             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1594           }
1595         }
1596         break;
1597         
1598     case AOP_DPTR:
1599     case AOP_DPTR2:
1600     
1601     if (aop->type == AOP_DPTR2)
1602     {
1603         genSetDPTR(1);
1604     }
1605     
1606         if (aop->code) {
1607             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1608                    "pic16_aopPut writting to code space");
1609             exit(0);
1610         }
1611         
1612         while (offset > aop->coff) {
1613             aop->coff++;
1614             pic16_emitcode ("inc","dptr");
1615         }
1616         
1617         while (offset < aop->coff) {
1618             aop->coff-- ;
1619             pic16_emitcode("lcall","__decdptr");
1620         }
1621         
1622         aop->coff = offset;
1623         
1624         /* if not in accumulater */
1625         MOVA(s);        
1626         
1627         pic16_emitcode ("movx","@dptr,a");
1628         
1629     if (aop->type == AOP_DPTR2)
1630     {
1631         genSetDPTR(0);
1632     }
1633         break;
1634         
1635     case AOP_R0:
1636     case AOP_R1:
1637         while (offset > aop->coff) {
1638             aop->coff++;
1639             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1640         }
1641         while (offset < aop->coff) {
1642             aop->coff-- ;
1643             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1644         }
1645         aop->coff = offset;
1646         
1647         if (aop->paged) {
1648             MOVA(s);           
1649             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1650             
1651         } else
1652             if (*s == '@') {
1653                 MOVA(s);
1654                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1655             } else
1656                 if (strcmp(s,"r0") == 0 ||
1657                     strcmp(s,"r1") == 0 ||
1658                     strcmp(s,"r2") == 0 ||
1659                     strcmp(s,"r3") == 0 ||
1660                     strcmp(s,"r4") == 0 ||
1661                     strcmp(s,"r5") == 0 ||
1662                     strcmp(s,"r6") == 0 || 
1663                     strcmp(s,"r7") == 0 ) {
1664                     char buffer[10];
1665                     sprintf(buffer,"a%s",s);
1666                     pic16_emitcode("mov","@%s,%s",
1667                              aop->aopu.aop_ptr->name,buffer);
1668                 } else
1669                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1670         
1671         break;
1672         
1673     case AOP_STK:
1674         if (strcmp(s,"a") == 0)
1675             pic16_emitcode("push","acc");
1676         else
1677             pic16_emitcode("push","%s",s);
1678         
1679         break;
1680         
1681     case AOP_CRY:
1682         /* if bit variable */
1683         if (!aop->aopu.aop_dir) {
1684             pic16_emitcode("clr","a");
1685             pic16_emitcode("rlc","a");
1686         } else {
1687             if (s == zero) 
1688                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1689             else
1690                 if (s == one)
1691                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1692                 else
1693                     if (!strcmp(s,"c"))
1694                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1695                     else {
1696                         lbl = newiTempLabel(NULL);
1697                         
1698                         if (strcmp(s,"a")) {
1699                             MOVA(s);
1700                         }
1701                         pic16_emitcode("clr","c");
1702                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1703                         pic16_emitcode("cpl","c");
1704                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1705                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1706                     }
1707         }
1708         break;
1709         
1710     case AOP_STR:
1711         aop->coff = offset;
1712         if (strcmp(aop->aopu.aop_str[offset],s))
1713             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1714         break;
1715         
1716     case AOP_ACC:
1717         aop->coff = offset;
1718         if (!offset && (strcmp(s,"acc") == 0))
1719             break;
1720         
1721         if (strcmp(aop->aopu.aop_str[offset],s))
1722             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1723         break;
1724
1725     default :
1726         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1727                "pic16_aopPut got unsupported aop->type");
1728         exit(0);    
1729     }    
1730
1731 }
1732
1733 /*-----------------------------------------------------------------*/
1734 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1735 /*-----------------------------------------------------------------*/
1736 static void mov2w (asmop *aop, int offset)
1737 {
1738
1739   if(!aop)
1740     return;
1741
1742   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1743
1744   if ( aop->type == AOP_PCODE ||
1745        aop->type == AOP_LIT )
1746     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1747   else
1748     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1749
1750 }
1751
1752
1753 void pic16_pushpCodeOpReg(pCodeOpReg *pcop)
1754 {
1755         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pcop, &pic16_pc_postdec1, 0));
1756 }
1757
1758 void pic16_poppCodeOpReg(pCodeOpReg *pcop)
1759 {
1760         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, pcop, 0));
1761 }
1762
1763
1764 /*-----------------------------------------------------------------*/
1765 /* pushw - pushes wreg to stack                                    */
1766 /*-----------------------------------------------------------------*/
1767 void pushw(void)
1768 {
1769         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1770         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1771 }
1772
1773                 
1774 /*-----------------------------------------------------------------*/
1775 /* pushaop - pushes aop to stack                                   */
1776 /*-----------------------------------------------------------------*/
1777 void pushaop(asmop *aop, int offset)
1778 {
1779         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1780         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1781 }
1782
1783 /*-----------------------------------------------------------------*/
1784 /* popaop - pops aop from stack                                    */
1785 /*-----------------------------------------------------------------*/
1786 void popaop(asmop *aop, int offset)
1787 {
1788         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1789         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1790 }
1791
1792 void popaopidx(asmop *aop, int offset, int index)
1793 {
1794   int ofs=1;
1795
1796         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1797
1798         if(STACK_MODEL_LARGE)ofs++;
1799
1800         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1801         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1802 }
1803
1804 /*-----------------------------------------------------------------*/
1805 /* reAdjustPreg - points a register back to where it should        */
1806 /*-----------------------------------------------------------------*/
1807 static void reAdjustPreg (asmop *aop)
1808 {
1809     int size ;
1810
1811     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1812     aop->coff = 0;
1813     if ((size = aop->size) <= 1)
1814         return ;
1815     size-- ;
1816     switch (aop->type) {
1817         case AOP_R0 :
1818         case AOP_R1 :
1819             while (size--)
1820                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1821             break;          
1822         case AOP_DPTR :
1823         case AOP_DPTR2:
1824             if (aop->type == AOP_DPTR2)
1825             {
1826                 genSetDPTR(1);
1827             } 
1828             while (size--)
1829             {
1830                 pic16_emitcode("lcall","__decdptr");
1831             }
1832                 
1833             if (aop->type == AOP_DPTR2)
1834             {
1835                 genSetDPTR(0);
1836             }                
1837             break;  
1838
1839     }   
1840
1841 }
1842
1843
1844 #if 0
1845 /*-----------------------------------------------------------------*/
1846 /* opIsGptr: returns non-zero if the passed operand is             */   
1847 /* a generic pointer type.                                         */
1848 /*-----------------------------------------------------------------*/ 
1849 static int opIsGptr(operand *op)
1850 {
1851     sym_link *type = operandType(op);
1852     
1853     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1854     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1855     {
1856         return 1;
1857     }
1858     return 0;        
1859 }
1860 #endif
1861
1862 /*-----------------------------------------------------------------*/
1863 /* pic16_getDataSize - get the operand data size                         */
1864 /*-----------------------------------------------------------------*/
1865 int pic16_getDataSize(operand *op)
1866 {
1867     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1868
1869
1870     return AOP_SIZE(op);
1871
1872     // tsd- in the pic port, the genptr size is 1, so this code here
1873     // fails. ( in the 8051 port, the size was 4).
1874 #if 0
1875     int size;
1876     size = AOP_SIZE(op);
1877     if (size == GPTRSIZE)
1878     {
1879         sym_link *type = operandType(op);
1880         if (IS_GENPTR(type))
1881         {
1882             /* generic pointer; arithmetic operations
1883              * should ignore the high byte (pointer type).
1884              */
1885             size--;
1886     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1887         }
1888     }
1889     return size;
1890 #endif
1891 }
1892
1893 /*-----------------------------------------------------------------*/
1894 /* pic16_outAcc - output Acc                                             */
1895 /*-----------------------------------------------------------------*/
1896 void pic16_outAcc(operand *result)
1897 {
1898   int size,offset;
1899   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1900   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
1901
1902
1903   size = pic16_getDataSize(result);
1904   if(size){
1905     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
1906     size--;
1907     offset = 1;
1908     /* unsigned or positive */
1909     while(size--)
1910       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1911   }
1912
1913 }
1914
1915 /*-----------------------------------------------------------------*/
1916 /* pic16_outBitC - output a bit C                                        */
1917 /*-----------------------------------------------------------------*/
1918 void pic16_outBitC(operand *result)
1919 {
1920
1921     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1922     /* if the result is bit */
1923     if (AOP_TYPE(result) == AOP_CRY) 
1924         pic16_aopPut(AOP(result),"c",0);
1925     else {
1926         pic16_emitcode("clr","a  ; %d", __LINE__);
1927         pic16_emitcode("rlc","a");
1928         pic16_outAcc(result);
1929     }
1930 }
1931
1932 /*-----------------------------------------------------------------*/
1933 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
1934 /*-----------------------------------------------------------------*/
1935 void pic16_toBoolean(operand *oper)
1936 {
1937     int size = AOP_SIZE(oper) - 1;
1938     int offset = 1;
1939
1940     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1941
1942     if ( AOP_TYPE(oper) != AOP_ACC) {
1943       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
1944     }
1945     while (size--) {
1946       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
1947     }
1948 }
1949
1950
1951 #if !defined(GEN_Not)
1952 /*-----------------------------------------------------------------*/
1953 /* genNot - generate code for ! operation                          */
1954 /*-----------------------------------------------------------------*/
1955 static void pic16_genNot (iCode *ic)
1956 {
1957   symbol *tlbl;
1958   int size;
1959
1960   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1961   /* assign asmOps to operand & result */
1962   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1963   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1964
1965   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1966   /* if in bit space then a special case */
1967   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1968     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1969       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1970       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1971     } else {
1972       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1973       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
1974       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1975     }
1976     goto release;
1977   }
1978
1979   size = AOP_SIZE(IC_LEFT(ic));
1980   if(size == 1) {
1981     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1982     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
1983     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1984     goto release;
1985   }
1986   pic16_toBoolean(IC_LEFT(ic));
1987
1988   tlbl = newiTempLabel(NULL);
1989   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1990   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
1991   pic16_outBitC(IC_RESULT(ic));
1992
1993  release:    
1994   /* release the aops */
1995   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1996   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1997 }
1998 #endif
1999
2000
2001 #if !defined(GEN_Cpl)
2002 /*-----------------------------------------------------------------*/
2003 /* genCpl - generate code for complement                           */
2004 /*-----------------------------------------------------------------*/
2005 static void pic16_genCpl (iCode *ic)
2006 {
2007     int offset = 0;
2008     int size ;
2009
2010
2011     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2012     /* assign asmOps to operand & result */
2013     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2014     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2015
2016     /* if both are in bit space then 
2017     a special case */
2018     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2019         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2020
2021         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2022         pic16_emitcode("cpl","c"); 
2023         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2024         goto release; 
2025     } 
2026
2027     size = AOP_SIZE(IC_RESULT(ic));
2028     while (size--) {
2029 /*
2030         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2031         MOVA(l);       
2032         pic16_emitcode("cpl","a");
2033         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2034 */
2035         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2036               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2037         } else {
2038                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2039                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2040         }
2041         offset++;
2042
2043     }
2044
2045
2046 release:
2047     /* release the aops */
2048     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2049     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2050 }
2051 #endif
2052
2053 /*-----------------------------------------------------------------*/
2054 /* genUminusFloat - unary minus for floating points                */
2055 /*-----------------------------------------------------------------*/
2056 static void genUminusFloat(operand *op,operand *result)
2057 {
2058     int size ,offset =0 ;
2059     char *l;
2060
2061     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2062     /* for this we just need to flip the 
2063     first it then copy the rest in place */
2064     size = AOP_SIZE(op) - 1;
2065     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2066
2067     MOVA(l);    
2068
2069     pic16_emitcode("cpl","acc.7");
2070     pic16_aopPut(AOP(result),"a",3);    
2071
2072     while(size--) {
2073         pic16_aopPut(AOP(result),
2074                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2075                offset);
2076         offset++;
2077     }          
2078 }
2079
2080 /*-----------------------------------------------------------------*/
2081 /* genUminus - unary minus code generation                         */
2082 /*-----------------------------------------------------------------*/
2083 static void genUminus (iCode *ic)
2084 {
2085   int size, i;
2086   sym_link *optype, *rtype;
2087
2088
2089   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2090   /* assign asmops */
2091   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2092   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2093
2094   /* if both in bit space then special
2095      case */
2096   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2097       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2098
2099     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2100     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2101     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2102
2103     goto release; 
2104   } 
2105
2106   optype = operandType(IC_LEFT(ic));
2107   rtype = operandType(IC_RESULT(ic));
2108
2109   /* if float then do float stuff */
2110   if (IS_FLOAT(optype)) {
2111     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2112     goto release;
2113   }
2114
2115   /* otherwise subtract from zero by taking the 2's complement */
2116   size = AOP_SIZE(IC_LEFT(ic));
2117
2118   for(i=0; i<size; i++) {
2119     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2120       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2121     else {
2122       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2123       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2124     }
2125   }
2126
2127   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2128   for(i=1; i<size; i++) {
2129     emitSKPNZ;
2130     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2131   }
2132
2133  release:
2134   /* release the aops */
2135   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2136   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2137 }
2138
2139 /*-----------------------------------------------------------------*/
2140 /* saveRegisters - will look for a call and save the registers     */
2141 /*-----------------------------------------------------------------*/
2142 static void saveRegisters(iCode *lic) 
2143 {
2144     int i;
2145     iCode *ic;
2146     bitVect *rsave;
2147     sym_link *dtype;
2148
2149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2150     /* look for call */
2151     for (ic = lic ; ic ; ic = ic->next) 
2152         if (ic->op == CALL || ic->op == PCALL)
2153             break;
2154
2155     if (!ic) {
2156         fprintf(stderr,"found parameter push with no function call\n");
2157         return ;
2158     }
2159
2160     /* if the registers have been saved already then
2161     do nothing */
2162     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2163         return ;
2164
2165     /* find the registers in use at this time 
2166     and push them away to safety */
2167     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2168                           ic->rUsed);
2169
2170     ic->regsSaved = 1;
2171     if (options.useXstack) {
2172         if (bitVectBitValue(rsave,R0_IDX))
2173             pic16_emitcode("mov","b,r0");
2174         pic16_emitcode("mov","r0,%s",spname);
2175         for (i = 0 ; i < pic16_nRegs ; i++) {
2176             if (bitVectBitValue(rsave,i)) {
2177                 if (i == R0_IDX)
2178                     pic16_emitcode("mov","a,b");
2179                 else
2180                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2181                 pic16_emitcode("movx","@r0,a");
2182                 pic16_emitcode("inc","r0");
2183             }
2184         }
2185         pic16_emitcode("mov","%s,r0",spname);
2186         if (bitVectBitValue(rsave,R0_IDX))
2187             pic16_emitcode("mov","r0,b");           
2188     }// else
2189     //for (i = 0 ; i < pic16_nRegs ; i++) {
2190     //    if (bitVectBitValue(rsave,i))
2191     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2192     //}
2193
2194     dtype = operandType(IC_LEFT(ic));
2195     if (currFunc && dtype && 
2196         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2197         IFFUNC_ISISR(currFunc->type) &&
2198         !ic->bankSaved) 
2199
2200         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2201
2202 }
2203 /*-----------------------------------------------------------------*/
2204 /* unsaveRegisters - pop the pushed registers                      */
2205 /*-----------------------------------------------------------------*/
2206 static void unsaveRegisters (iCode *ic)
2207 {
2208     int i;
2209     bitVect *rsave;
2210
2211     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2212     /* find the registers in use at this time 
2213     and push them away to safety */
2214     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2215                           ic->rUsed);
2216     
2217     if (options.useXstack) {
2218         pic16_emitcode("mov","r0,%s",spname);   
2219         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2220             if (bitVectBitValue(rsave,i)) {
2221                 pic16_emitcode("dec","r0");
2222                 pic16_emitcode("movx","a,@r0");
2223                 if (i == R0_IDX)
2224                     pic16_emitcode("mov","b,a");
2225                 else
2226                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2227             }       
2228
2229         }
2230         pic16_emitcode("mov","%s,r0",spname);
2231         if (bitVectBitValue(rsave,R0_IDX))
2232             pic16_emitcode("mov","r0,b");
2233     } //else
2234     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2235     //    if (bitVectBitValue(rsave,i))
2236     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2237     //}
2238
2239 }  
2240
2241
2242 /*-----------------------------------------------------------------*/
2243 /* pushSide -                                                      */
2244 /*-----------------------------------------------------------------*/
2245 static void pushSide(operand * oper, int size)
2246 {
2247 #if 0
2248         int offset = 0;
2249     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2250         while (size--) {
2251                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2252                 if (AOP_TYPE(oper) != AOP_REG &&
2253                     AOP_TYPE(oper) != AOP_DIR &&
2254                     strcmp(l,"a") ) {
2255                         pic16_emitcode("mov","a,%s",l);
2256                         pic16_emitcode("push","acc");
2257                 } else
2258                         pic16_emitcode("push","%s",l);
2259         }
2260 #endif
2261 }
2262
2263 /*-----------------------------------------------------------------*/
2264 /* assignResultValue -                                             */
2265 /*-----------------------------------------------------------------*/
2266 static void assignResultValue(operand * oper)
2267 {
2268   int size = AOP_SIZE(oper);
2269
2270         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2271         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2272
2273         if(!GpsuedoStkPtr) {
2274 //              DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2275                 /* The last byte in the assignment is in W */
2276                 size--;
2277                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2278                 GpsuedoStkPtr++;
2279         }
2280
2281         while (size--) {
2282 //              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2283 //              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2284                 
2285 #if STACK_SUPPORT
2286                 if(USE_STACK) {
2287                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2288                 } else {
2289                         pic16_emitpcode(POC_MOVFW, pic16_popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2290                 }
2291 #else
2292                 pic16_emitpcode(POC_MOVFW, pic16_popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2293 #endif  /* STACK_SUPPORT */
2294                 GpsuedoStkPtr++;
2295
2296 #if STACK_SUPPORT
2297                 if(!USE_STACK)
2298                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2299 #else
2300                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2301 #endif
2302
2303         }
2304                 
2305 }
2306
2307
2308 /*-----------------------------------------------------------------*/
2309 /* genIpush - genrate code for pushing this gets a little complex  */
2310 /*-----------------------------------------------------------------*/
2311 static void genIpush (iCode *ic)
2312 {
2313
2314   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2315 #if 0
2316     int size, offset = 0 ;
2317     char *l;
2318
2319
2320     /* if this is not a parm push : ie. it is spill push 
2321     and spill push is always done on the local stack */
2322     if (!ic->parmPush) {
2323
2324         /* and the item is spilt then do nothing */
2325         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2326             return ;
2327
2328         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2329         size = AOP_SIZE(IC_LEFT(ic));
2330         /* push it on the stack */
2331         while(size--) {
2332             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2333             if (*l == '#') {
2334                 MOVA(l);
2335                 l = "acc";
2336             }
2337             pic16_emitcode("push","%s",l);
2338         }
2339         return ;        
2340     }
2341
2342     /* this is a paramter push: in this case we call
2343     the routine to find the call and save those
2344     registers that need to be saved */   
2345     saveRegisters(ic);
2346
2347     /* then do the push */
2348     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2349
2350
2351         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2352     size = AOP_SIZE(IC_LEFT(ic));
2353
2354     while (size--) {
2355         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2356         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2357             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2358             strcmp(l,"a") ) {
2359             pic16_emitcode("mov","a,%s",l);
2360             pic16_emitcode("push","acc");
2361         } else
2362             pic16_emitcode("push","%s",l);
2363     }       
2364
2365     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2366 #endif
2367 }
2368
2369 /*-----------------------------------------------------------------*/
2370 /* genIpop - recover the registers: can happen only for spilling   */
2371 /*-----------------------------------------------------------------*/
2372 static void genIpop (iCode *ic)
2373 {
2374   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2375 #if 0
2376     int size,offset ;
2377
2378
2379     /* if the temp was not pushed then */
2380     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2381         return ;
2382
2383     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2384     size = AOP_SIZE(IC_LEFT(ic));
2385     offset = (size-1);
2386     while (size--) 
2387         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2388                                    FALSE,TRUE));
2389
2390     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2391 #endif
2392 }
2393
2394 /*-----------------------------------------------------------------*/
2395 /* unsaverbank - restores the resgister bank from stack            */
2396 /*-----------------------------------------------------------------*/
2397 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2398 {
2399   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2400 #if 0
2401     int i;
2402     asmop *aop ;
2403     regs *r = NULL;
2404
2405     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2406     if (popPsw) {
2407         if (options.useXstack) {
2408             aop = newAsmop(0);
2409             r = getFreePtr(ic,&aop,FALSE);
2410             
2411             
2412             pic16_emitcode("mov","%s,_spx",r->name);
2413             pic16_emitcode("movx","a,@%s",r->name);
2414             pic16_emitcode("mov","psw,a");
2415             pic16_emitcode("dec","%s",r->name);
2416             
2417         }else
2418             pic16_emitcode ("pop","psw");
2419     }
2420
2421     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2422         if (options.useXstack) {       
2423             pic16_emitcode("movx","a,@%s",r->name);
2424             //pic16_emitcode("mov","(%s+%d),a",
2425             //       regspic16[i].base,8*bank+regspic16[i].offset);
2426             pic16_emitcode("dec","%s",r->name);
2427
2428         } else 
2429           pic16_emitcode("pop",""); //"(%s+%d)",
2430         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2431     }
2432
2433     if (options.useXstack) {
2434
2435         pic16_emitcode("mov","_spx,%s",r->name);
2436         pic16_freeAsmop(NULL,aop,ic,TRUE);
2437
2438     }
2439 #endif 
2440 }
2441
2442 /*-----------------------------------------------------------------*/
2443 /* saverbank - saves an entire register bank on the stack          */
2444 /*-----------------------------------------------------------------*/
2445 static void saverbank (int bank, iCode *ic, bool pushPsw)
2446 {
2447   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2448 #if 0
2449     int i;
2450     asmop *aop ;
2451     regs *r = NULL;
2452
2453     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2454     if (options.useXstack) {
2455
2456         aop = newAsmop(0);
2457         r = getFreePtr(ic,&aop,FALSE);  
2458         pic16_emitcode("mov","%s,_spx",r->name);
2459
2460     }
2461
2462     for (i = 0 ; i < pic16_nRegs ;i++) {
2463         if (options.useXstack) {
2464             pic16_emitcode("inc","%s",r->name);
2465             //pic16_emitcode("mov","a,(%s+%d)",
2466             //         regspic16[i].base,8*bank+regspic16[i].offset);
2467             pic16_emitcode("movx","@%s,a",r->name);           
2468         } else 
2469           pic16_emitcode("push","");// "(%s+%d)",
2470                      //regspic16[i].base,8*bank+regspic16[i].offset);
2471     }
2472     
2473     if (pushPsw) {
2474         if (options.useXstack) {
2475             pic16_emitcode("mov","a,psw");
2476             pic16_emitcode("movx","@%s,a",r->name);     
2477             pic16_emitcode("inc","%s",r->name);
2478             pic16_emitcode("mov","_spx,%s",r->name);       
2479             pic16_freeAsmop (NULL,aop,ic,TRUE);
2480             
2481         } else
2482             pic16_emitcode("push","psw");
2483         
2484         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2485     }
2486     ic->bankSaved = 1;
2487 #endif
2488 }
2489
2490
2491
2492 /*-----------------------------------------------------------------*/
2493 /* genCall - generates a call statement                            */
2494 /*-----------------------------------------------------------------*/
2495 static void genCall (iCode *ic)
2496 {
2497   sym_link *dtype;   
2498   int stackParms=0;
2499   
2500         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2501
2502         /* if caller saves & we have not saved then */
2503         if (!ic->regsSaved)
2504                 saveRegisters(ic);
2505
2506         /* if we are calling a function that is not using
2507          * the same register bank then we need to save the
2508          * destination registers on the stack */
2509         dtype = operandType(IC_LEFT(ic));
2510         if (currFunc && dtype && 
2511                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2512                 IFFUNC_ISISR(currFunc->type) &&
2513                 !ic->bankSaved) 
2514
2515                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2516
2517         /* if send set is not empty the assign */
2518         if (_G.sendSet) {
2519           iCode *sic;
2520
2521                 /* For the Pic port, there is no data stack.
2522                  * So parameters passed to functions are stored
2523                  * in registers. (The pCode optimizer will get
2524                  * rid of most of these :). */
2525
2526           int psuedoStkPtr=-1; 
2527           int firstTimeThruLoop = 1;
2528
2529                 _G.sendSet = reverseSet(_G.sendSet);
2530
2531                 /* First figure how many parameters are getting passed */
2532                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2533                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2534                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2535                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2536                 }
2537
2538                 stackParms = psuedoStkPtr;
2539
2540                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2541                   int size, offset = 0;
2542
2543                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2544                         size = AOP_SIZE(IC_LEFT(sic));
2545
2546                         while (size--) {
2547                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2548                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2549                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2550
2551                                 if(!firstTimeThruLoop) {
2552                                         /* If this is not the first time we've been through the loop
2553                                          * then we need to save the parameter in a temporary
2554                                          * register. The last byte of the last parameter is
2555                                          * passed in W. */
2556
2557 #if STACK_SUPPORT
2558                                         if(USE_STACK) {
2559                                                 pushw();
2560                                                 --psuedoStkPtr;         // sanity check
2561                                         } else {
2562                                                 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2563                                         }
2564 #else
2565                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2566 #endif  /* STACK_SUPPORT */
2567                                 }
2568                         
2569                                 firstTimeThruLoop=0;
2570
2571                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2572                                 offset++;
2573                         }
2574                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2575                 }
2576                 _G.sendSet = NULL;
2577         }
2578
2579         /* make the call */
2580         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2581                         OP_SYMBOL(IC_LEFT(ic))->rname :
2582                         OP_SYMBOL(IC_LEFT(ic))->name));
2583
2584         GpsuedoStkPtr=0;
2585         /* if we need assign a result value */
2586         if ((IS_ITEMP(IC_RESULT(ic)) && 
2587                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2588                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2589                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2590
2591                 _G.accInUse++;
2592                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2593                 _G.accInUse--;
2594
2595                 assignResultValue(IC_RESULT(ic));
2596
2597                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2598                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2599                 
2600                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2601         }
2602
2603 #if STACK_SUPPORT
2604         if(USE_STACK && stackParms>0) {
2605                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2606                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2607                 if(STACK_MODEL_LARGE) {
2608                         emitSKPNC;
2609                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2610                 }
2611         }
2612 #endif
2613
2614         /* adjust the stack for parameters if required */
2615 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2616
2617         if (ic->parmBytes) {
2618           int i;
2619
2620                 if (ic->parmBytes > 3) {
2621                         pic16_emitcode("mov","a,%s",spname);
2622                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2623                         pic16_emitcode("mov","%s,a",spname);
2624                 } else 
2625                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2626                                 pic16_emitcode("dec","%s",spname);
2627         }
2628
2629         /* if register bank was saved then pop them */
2630         if (ic->bankSaved)
2631                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2632
2633         /* if we hade saved some registers then unsave them */
2634         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2635                 unsaveRegisters (ic);
2636 }
2637
2638 /*-----------------------------------------------------------------*/
2639 /* genPcall - generates a call by pointer statement                */
2640 /*-----------------------------------------------------------------*/
2641 static void genPcall (iCode *ic)
2642 {
2643     sym_link *dtype;
2644     symbol *rlbl = newiTempLabel(NULL);
2645
2646
2647     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2648     /* if caller saves & we have not saved then */
2649     if (!ic->regsSaved)
2650         saveRegisters(ic);
2651
2652     /* if we are calling a function that is not using
2653     the same register bank then we need to save the
2654     destination registers on the stack */
2655     dtype = operandType(IC_LEFT(ic));
2656     if (currFunc && dtype && 
2657         IFFUNC_ISISR(currFunc->type) &&
2658         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2659         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2660
2661
2662     /* push the return address on to the stack */
2663     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2664     pic16_emitcode("push","acc");    
2665     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2666     pic16_emitcode("push","acc");
2667     
2668     if (options.model == MODEL_FLAT24)
2669     {
2670         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2671         pic16_emitcode("push","acc");    
2672     }
2673
2674     /* now push the calling address */
2675     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2676
2677     pushSide(IC_LEFT(ic), FPTRSIZE);
2678
2679     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2680
2681     /* if send set is not empty the assign */
2682     if (_G.sendSet) {
2683         iCode *sic ;
2684
2685         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2686              sic = setNextItem(_G.sendSet)) {
2687             int size, offset = 0;
2688             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2689             size = AOP_SIZE(IC_LEFT(sic));
2690             while (size--) {
2691                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
2692                                 FALSE,FALSE);
2693                 if (strcmp(l,fReturn[offset]))
2694                     pic16_emitcode("mov","%s,%s",
2695                              fReturn[offset],
2696                              l);
2697                 offset++;
2698             }
2699             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2700         }
2701         _G.sendSet = NULL;
2702     }
2703
2704     pic16_emitcode("ret","");
2705     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
2706
2707
2708     /* if we need assign a result value */
2709     if ((IS_ITEMP(IC_RESULT(ic)) &&
2710          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2711           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2712         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2713
2714         _G.accInUse++;
2715         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2716         _G.accInUse--;
2717         
2718         assignResultValue(IC_RESULT(ic));
2719
2720         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2721     }
2722
2723     /* adjust the stack for parameters if 
2724     required */
2725     if (ic->parmBytes) {
2726         int i;
2727         if (ic->parmBytes > 3) {
2728             pic16_emitcode("mov","a,%s",spname);
2729             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2730             pic16_emitcode("mov","%s,a",spname);
2731         } else 
2732             for ( i = 0 ; i <  ic->parmBytes ;i++)
2733                 pic16_emitcode("dec","%s",spname);
2734
2735     }
2736
2737     /* if register bank was saved then unsave them */
2738     if (currFunc && dtype && 
2739         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2740         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2741
2742     /* if we hade saved some registers then
2743     unsave them */
2744     if (ic->regsSaved)
2745         unsaveRegisters (ic);
2746
2747 }
2748
2749 /*-----------------------------------------------------------------*/
2750 /* resultRemat - result  is rematerializable                       */
2751 /*-----------------------------------------------------------------*/
2752 static int resultRemat (iCode *ic)
2753 {
2754   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2755   if (SKIP_IC(ic) || ic->op == IFX)
2756     return 0;
2757
2758   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2759     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2760     if (sym->remat && !POINTER_SET(ic)) 
2761       return 1;
2762   }
2763
2764   return 0;
2765 }
2766
2767 #if defined(__BORLANDC__) || defined(_MSC_VER)
2768 #define STRCASECMP stricmp
2769 #else
2770 #define STRCASECMP strcasecmp
2771 #endif
2772
2773 #if 0
2774 /*-----------------------------------------------------------------*/
2775 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2776 /*-----------------------------------------------------------------*/
2777 static bool inExcludeList(char *s)
2778 {
2779   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2780     int i =0;
2781     
2782     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2783     if (options.excludeRegs[i] &&
2784     STRCASECMP(options.excludeRegs[i],"none") == 0)
2785         return FALSE ;
2786
2787     for ( i = 0 ; options.excludeRegs[i]; i++) {
2788         if (options.excludeRegs[i] &&
2789         STRCASECMP(s,options.excludeRegs[i]) == 0)
2790             return TRUE;
2791     }
2792     return FALSE ;
2793 }
2794 #endif
2795
2796 /*-----------------------------------------------------------------*/
2797 /* genFunction - generated code for function entry                 */
2798 /*-----------------------------------------------------------------*/
2799 static void genFunction (iCode *ic)
2800 {
2801   symbol *sym;
2802   sym_link *ftype;
2803
2804         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2805
2806         labelOffset += (max_key+4);
2807         max_key=0;
2808         GpsuedoStkPtr=0;
2809         _G.nRegsSaved = 0;
2810         /* create the function header */
2811         pic16_emitcode(";","-----------------------------------------");
2812         pic16_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2813         pic16_emitcode(";","-----------------------------------------");
2814
2815         pic16_emitcode("","%s:",sym->rname);
2816         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
2817
2818         {
2819           absSym *ab;
2820
2821                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
2822                         if(strcmp(ab->name, sym->name)) {
2823                                 pic16_pBlockConvert2Absolute(pb);
2824                                 break;
2825                         }
2826                 
2827         }
2828
2829         ftype = operandType(IC_LEFT(ic));
2830
2831         if(IFFUNC_ISNAKED(ftype)) {
2832                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
2833                 return;
2834         }
2835         
2836
2837         /* if critical function then turn interrupts off */
2838         if (IFFUNC_ISCRITICAL(ftype))
2839                 pic16_emitcode("clr","ea");
2840
2841         /* here we need to generate the equates for the
2842          * register bank if required */
2843 #if 0
2844         if (FUNC_REGBANK(ftype) != rbank) {
2845           int i ;
2846
2847                 rbank = FUNC_REGBANK(ftype);
2848                 for ( i = 0 ; i < pic16_nRegs ; i++ ) {
2849                         if (strcmp(regspic16[i].base,"0") == 0)
2850                                 pic16_emitcode("","%s = 0x%02x",
2851                                         regspic16[i].dname,
2852                                         8*rbank+regspic16[i].offset);
2853                         else
2854                                 pic16_emitcode ("","%s = %s + 0x%02x",
2855                                         regspic16[i].dname,
2856                                         regspic16[i].base,
2857                                         *rbank+regspic16[i].offset);
2858                 }
2859         }
2860 #endif
2861
2862         /* if this is an interrupt service routine then
2863          * save acc, b, dpl, dph  */
2864         if (IFFUNC_ISISR(sym->type)) {
2865                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_wsave));
2866                 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_status));
2867                 pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2868                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_ssave));
2869
2870                 pic16_pBlockConvert2ISR(pb);
2871 #if 0  
2872                 if (!inExcludeList("acc"))          
2873                         pic16_emitcode ("push","acc");  
2874                 if (!inExcludeList("b"))
2875                         pic16_emitcode ("push","b");
2876                 if (!inExcludeList("dpl"))
2877                         pic16_emitcode ("push","dpl");
2878                 if (!inExcludeList("dph"))
2879                         pic16_emitcode ("push","dph");
2880                 
2881                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx")) {
2882                         pic16_emitcode ("push", "dpx");
2883
2884                         /* Make sure we're using standard DPTR */
2885                         pic16_emitcode ("push", "dps");
2886                         pic16_emitcode ("mov", "dps, #0x00");
2887                         if (options.stack10bit) {       
2888                                 /* This ISR could conceivably use DPTR2. Better save it. */
2889                                 pic16_emitcode ("push", "dpl1");
2890                                 pic16_emitcode ("push", "dph1");
2891                                 pic16_emitcode ("push", "dpx1");
2892                         }
2893                 }
2894
2895                 /* if this isr has no bank i.e. is going to
2896                  * run with bank 0 , then we need to save more
2897                  * registers :-) */
2898                 if (!FUNC_REGBANK(sym->type)) {
2899
2900                         /* if this function does not call any other
2901                          * function then we can be economical and
2902                          * save only those registers that are used */
2903                         if (! IFFUNC_HASFCALL(sym->type)) {
2904                           int i;
2905
2906                                 /* if any registers used */
2907                                 if (sym->regsUsed) {
2908                                         /* save the registers used */
2909                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2910                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2911                                                         (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2912                                                 pic16_emitcode("push","junk");//"%s",pic16_regWithIdx(i)->dname);                           
2913                                         }
2914                                 }
2915
2916                         } else {
2917                                 /* this function has  a function call cannot
2918                                  * determines register usage so we will have the
2919                                  * entire bank */
2920                                 saverbank(0,ic,FALSE);
2921                         }           
2922                 }
2923 #endif
2924         } else {
2925 #if STACK_SUPPORT
2926                 /* emit code to setup stack frame if user enabled,
2927                  * and function is not main() */
2928          
2929 //              fprintf(stderr, "function name: %s\n", sym->name);
2930                 if(USE_STACK && strcmp(sym->name, "main")) {
2931                         if(!options.ommitFramePtr || sym->regsUsed) {
2932                         /* setup the stack frame */
2933                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
2934                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
2935                                 if(STACK_MODEL_LARGE)
2936                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
2937                         }
2938                 }
2939 #endif
2940
2941                 /* if callee-save to be used for this function
2942                 * then save the registers being used in this function */
2943                 if (IFFUNC_CALLEESAVES(sym->type)) {
2944                   int i;
2945             
2946 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %p\n", __FILE__, __LINE__, sym->regsUsed);
2947                         
2948                         /* if any registers used */
2949                         if (sym->regsUsed
2950 #if STACK_SUPPORT
2951                                 && USE_STACK
2952 #endif
2953                                 ) {
2954                                 /* save the registers used */
2955                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
2956                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2957                                         if (bitVectBitValue(sym->regsUsed,i)) {
2958 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
2959 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
2960 //                                                              pic16_regWithIdx(i)->name);
2961
2962                                                 pic16_pushpCodeOpReg( PCOR(pic16_popRegFromIdx(i) ));
2963 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
2964 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
2965 //                                                      &pic16_pc_postdec1, 0));
2966                                                 _G.nRegsSaved++;
2967                                         }
2968                                 }
2969                         }
2970                 }
2971         }
2972
2973
2974         
2975 #if 0
2976         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2977
2978                 if (options.useXstack) {
2979                         pic16_emitcode("mov","r0,%s",spname);
2980                         pic16_emitcode("mov","a,_bp");
2981                         pic16_emitcode("movx","@r0,a");
2982                         pic16_emitcode("inc","%s",spname);
2983                 } else {
2984                         /* set up the stack */
2985                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
2986                 }
2987                 pic16_emitcode ("mov","_bp,%s",spname);
2988         }
2989 #endif
2990         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
2991
2992         /* adjust the stack for the function */
2993         if (sym->stack) {
2994           int i = sym->stack;
2995
2996                 if (i > 127 ) 
2997                         werror(W_STACK_OVERFLOW,sym->name);
2998
2999                 if (i > 3 && sym->recvSize < 4) {              
3000                         pic16_emitcode ("mov","a,sp");
3001                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3002                         pic16_emitcode ("mov","sp,a");
3003                 } else
3004                         while(i--)
3005                                 pic16_emitcode("inc","sp");
3006         }
3007
3008         if (sym->xstack) {
3009                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3010
3011                 pic16_emitcode ("mov","a,_spx");
3012                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3013                 pic16_emitcode ("mov","_spx,a");
3014         }
3015     
3016 }
3017
3018 /*-----------------------------------------------------------------*/
3019 /* genEndFunction - generates epilogue for functions               */
3020 /*-----------------------------------------------------------------*/
3021 static void genEndFunction (iCode *ic)
3022 {
3023     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3024
3025     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3026
3027     if(IFFUNC_ISNAKED(sym->type)) {
3028         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3029         return;
3030     }
3031
3032 #if 0
3033     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3034     {
3035         pic16_emitcode ("mov","%s,_bp",spname);
3036     }
3037 #endif
3038
3039     /* if use external stack but some variables were
3040     added to the local stack then decrement the
3041     local stack */
3042     if (options.useXstack && sym->stack) {      
3043         pic16_emitcode("mov","a,sp");
3044         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3045         pic16_emitcode("mov","sp,a");
3046     }
3047
3048
3049 #if 0
3050     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3051         if (options.useXstack) {
3052             pic16_emitcode("mov","r0,%s",spname);
3053             pic16_emitcode("movx","a,@r0");
3054             pic16_emitcode("mov","_bp,a");
3055             pic16_emitcode("dec","%s",spname);
3056         }
3057         else
3058         {
3059             pic16_emitcode ("pop","_bp");
3060         }
3061     }
3062 #endif
3063
3064     /* restore the register bank  */    
3065     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3066         pic16_emitcode ("pop","psw");
3067
3068     if (IFFUNC_ISISR(sym->type)) {
3069
3070         /* now we need to restore the registers */
3071         /* if this isr has no bank i.e. is going to
3072            run with bank 0 , then we need to save more
3073            registers :-) */
3074         if (!FUNC_REGBANK(sym->type)) {
3075             
3076             /* if this function does not call any other
3077                function then we can be economical and
3078                save only those registers that are used */
3079             if (! IFFUNC_HASFCALL(sym->type)) {
3080                 int i;
3081                 
3082                 /* if any registers used */
3083                 if (sym->regsUsed) {
3084                     /* save the registers used */
3085                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3086                         if (bitVectBitValue(sym->regsUsed,i) ||
3087                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3088                           pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
3089                     }
3090                 }
3091                 
3092             } else {
3093                 /* this function has  a function call cannot
3094                    determines register usage so we will have the
3095                    entire bank */
3096                 unsaverbank(0,ic,FALSE);
3097             }       
3098         }
3099 #if 0
3100         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3101         {
3102             if (options.stack10bit)
3103             {
3104                 pic16_emitcode ("pop", "dpx1");
3105                 pic16_emitcode ("pop", "dph1");
3106                 pic16_emitcode ("pop", "dpl1");
3107             }   
3108             pic16_emitcode ("pop", "dps");
3109             pic16_emitcode ("pop", "dpx");
3110         }
3111         if (!inExcludeList("dph"))
3112             pic16_emitcode ("pop","dph");
3113         if (!inExcludeList("dpl"))
3114             pic16_emitcode ("pop","dpl");
3115         if (!inExcludeList("b"))
3116             pic16_emitcode ("pop","b");
3117         if (!inExcludeList("acc"))
3118             pic16_emitcode ("pop","acc");
3119
3120         if (IFFUNC_ISCRITICAL(sym->type))
3121             pic16_emitcode("setb","ea");
3122 #endif
3123
3124         /* if debug then send end of function */
3125 /*      if (options.debug && currFunc) { */
3126         if (currFunc) {
3127             _G.debugLine = 1;
3128             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3129                      FileBaseName(ic->filename),currFunc->lastLine,
3130                      ic->level,ic->block); 
3131             if (IS_STATIC(currFunc->etype))         
3132                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3133             else
3134                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3135             _G.debugLine = 0;
3136         }
3137         
3138 //      pic16_emitcode ("reti","");
3139
3140         pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
3141         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
3142         pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
3143         pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
3144         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
3145
3146 #if 0
3147         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("END_OF_INTERRUPT",-1));
3148 #endif
3149
3150         pic16_emitpcodeNULLop(POC_RETFIE);
3151
3152     }
3153     else {
3154         if (IFFUNC_ISCRITICAL(sym->type))
3155             pic16_emitcode("setb","ea");
3156         
3157         /* if any registers used */
3158         if (sym->regsUsed
3159 #if STACK_SUPPORT
3160                 && USE_STACK
3161 #endif
3162         ) {
3163           int i;
3164                 /* save the registers used */
3165                 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3166                 for ( i = sym->regsUsed->size; i >= 0; i--) {
3167                         if (bitVectBitValue(sym->regsUsed,i)) {
3168 //                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3169 //                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3170 //                                              pic16_regWithIdx(i)->name);
3171         
3172                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3173                                         &pic16_pc_preinc1,
3174                                         PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3175                         }
3176                 }
3177         }
3178         
3179
3180         /* if debug then send end of function */
3181         if (currFunc) {
3182             _G.debugLine = 1;
3183             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3184                      FileBaseName(ic->filename),currFunc->lastLine,
3185                      ic->level,ic->block); 
3186             if (IS_STATIC(currFunc->etype))         
3187                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3188             else
3189                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3190             _G.debugLine = 0;
3191         }
3192
3193 #if STACK_SUPPORT
3194         /* insert code to restore stack frame, if user enabled it
3195          * and function is not main() */
3196          
3197         if(USE_STACK && strcmp(sym->name, "main")) {
3198                 if(!options.ommitFramePtr || sym->regsUsed) {
3199                         /* restore stack frame */
3200                         if(STACK_MODEL_LARGE)
3201                                 pic16_emitpcode(POC_MOVFF,
3202                                         pic16_popCombine2( &pic16_pc_postinc1, &pic16_pc_fsr2h, 0));
3203                         pic16_emitpcode(POC_MOVFF,
3204                                         pic16_popCombine2( &pic16_pc_postinc1, &pic16_pc_fsr2l, 0));
3205                 }
3206         }
3207 #endif
3208
3209         pic16_emitcode ("return","");
3210         pic16_emitpcodeNULLop(POC_RETURN);
3211
3212         /* Mark the end of a function */
3213         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3214     }
3215
3216 }
3217
3218 /*-----------------------------------------------------------------*/
3219 /* genRet - generate code for return statement                     */
3220 /*-----------------------------------------------------------------*/
3221 static void genRet (iCode *ic)
3222 {
3223   int size,offset = 0 , pushed = 0;
3224     
3225   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3226   /* if we have no return value then
3227      just generate the "ret" */
3228   if (!IC_LEFT(ic)) 
3229     goto jumpret;       
3230     
3231   /* we have something to return then
3232      move the return value into place */
3233   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3234   size = AOP_SIZE(IC_LEFT(ic));
3235     
3236   while (size--) {
3237     char *l ;
3238     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3239       /* #NOCHANGE */
3240       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,
3241                  FALSE,TRUE);
3242       pic16_emitcode("push","%s",l);
3243       pushed++;
3244     } else {
3245         DEBUGpic16_emitcode(";", "%d", __LINE__);
3246       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,
3247                  FALSE,FALSE);
3248         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3249       if (strcmp(fReturn[offset],l)) {
3250         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3251             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3252           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3253         }else {
3254           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3255         }
3256         if(size) {
3257           pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3258         }
3259         offset++;
3260       }
3261     }
3262   }    
3263
3264   if (pushed) {
3265     while(pushed) {
3266       pushed--;
3267       if (strcmp(fReturn[pushed],"a"))
3268         pic16_emitcode("pop",fReturn[pushed]);
3269       else
3270         pic16_emitcode("pop","acc");
3271     }
3272   }
3273   pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3274     
3275  jumpret:
3276   /* generate a jump to the return label
3277      if the next is not the return statement */
3278   if (!(ic->next && ic->next->op == LABEL &&
3279         IC_LABEL(ic->next) == returnLabel)) {
3280         
3281     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3282     pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3283   }
3284     
3285 }
3286
3287 /*-----------------------------------------------------------------*/
3288 /* genLabel - generates a label                                    */
3289 /*-----------------------------------------------------------------*/
3290 static void genLabel (iCode *ic)
3291 {
3292     /* special case never generate */
3293     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3294     if (IC_LABEL(ic) == entryLabel)
3295         return ;
3296
3297     pic16_emitpLabel(IC_LABEL(ic)->key);
3298     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3299 }
3300
3301 /*-----------------------------------------------------------------*/
3302 /* genGoto - generates a goto                                      */
3303 /*-----------------------------------------------------------------*/
3304 //tsd
3305 static void genGoto (iCode *ic)
3306 {
3307   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3308   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3309 }
3310
3311
3312 /*-----------------------------------------------------------------*/
3313 /* genMultbits :- multiplication of bits                           */
3314 /*-----------------------------------------------------------------*/
3315 static void genMultbits (operand *left, 
3316                          operand *right, 
3317                          operand *result)
3318 {
3319   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3320
3321   if(!pic16_sameRegs(AOP(result),AOP(right)))
3322     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3323
3324   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3325   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3326   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3327
3328 }
3329
3330
3331 /*-----------------------------------------------------------------*/
3332 /* genMultOneByte : 8 bit multiplication & division                */
3333 /*-----------------------------------------------------------------*/
3334 static void genMultOneByte (operand *left,
3335                             operand *right,
3336                             operand *result)
3337 {
3338   sym_link *opetype = operandType(result);
3339
3340   // symbol *lbl ;
3341   int size,offset;
3342
3343   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3344   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3345   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3346
3347   /* (if two literals, the value is computed before) */
3348   /* if one literal, literal on the right */
3349   if (AOP_TYPE(left) == AOP_LIT){
3350     operand *t = right;
3351     right = left;
3352     left = t;
3353   }
3354
3355   size = AOP_SIZE(result);
3356   if(size == 1) {
3357
3358     if (AOP_TYPE(right) == AOP_LIT){
3359       pic16_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3360                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3361                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3362                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3363       pic16_emitcode("call","genMultLit");
3364     } else {
3365       pic16_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3366                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3367                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3368                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3369       pic16_emitcode("call","pic16_genMult8X8_8");
3370
3371     }
3372     pic16_genMult8X8_8 (left, right,result);
3373
3374
3375     /* signed or unsigned */
3376     //pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3377     //l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3378     //MOVA(l);       
3379     //pic16_emitcode("mul","ab");
3380     /* if result size = 1, mul signed = mul unsigned */
3381     //pic16_aopPut(AOP(result),"a",0);
3382
3383   } else {  // (size > 1)
3384
3385     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3386                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3387                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3388                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3389
3390     if (SPEC_USIGN(opetype)){
3391       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3392       pic16_genUMult8X8_16 (left, right, result, NULL);
3393
3394       if (size > 2) {
3395         /* for filling the MSBs */
3396         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3397         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3398       }
3399     }
3400     else{
3401       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3402
3403       pic16_emitcode("mov","a,b");
3404
3405       /* adjust the MSB if left or right neg */
3406
3407       /* if one literal */
3408       if (AOP_TYPE(right) == AOP_LIT){
3409         pic16_emitcode("multiply ","right is a lit");
3410         /* AND literal negative */
3411         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3412           /* adjust MSB (c==0 after mul) */
3413           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3414         }
3415       }
3416       else{
3417         pic16_genSMult8X8_16 (left, right, result, NULL);
3418       }
3419
3420       if(size > 2){
3421         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3422         /* get the sign */
3423         pic16_emitcode("rlc","a");
3424         pic16_emitcode("subb","a,acc");
3425       }
3426     }
3427
3428     size -= 2;   
3429     offset = 2;
3430     if (size > 0)
3431       while (size--)
3432         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3433     //pic16_aopPut(AOP(result),"a",offset++);
3434   }
3435 }
3436
3437 /*-----------------------------------------------------------------*/
3438 /* genMult - generates code for multiplication                     */
3439 /*-----------------------------------------------------------------*/
3440 static void genMult (iCode *ic)
3441 {
3442     operand *left = IC_LEFT(ic);
3443     operand *right = IC_RIGHT(ic);
3444     operand *result= IC_RESULT(ic);   
3445
3446     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3447     /* assign the amsops */
3448     pic16_aopOp (left,ic,FALSE);
3449     pic16_aopOp (right,ic,FALSE);
3450     pic16_aopOp (result,ic,TRUE);
3451
3452   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3453
3454     /* special cases first */
3455     /* both are bits */
3456     if (AOP_TYPE(left) == AOP_CRY &&
3457         AOP_TYPE(right)== AOP_CRY) {
3458         genMultbits(left,right,result);
3459         goto release ;
3460     }
3461
3462     /* if both are of size == 1 */
3463     if (AOP_SIZE(left) == 1 &&
3464         AOP_SIZE(right) == 1 ) {
3465         genMultOneByte(left,right,result);
3466         goto release ;
3467     }
3468
3469     pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3470
3471     /* should have been converted to function call */
3472     //assert(0) ;
3473
3474 release :
3475     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3476     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3477     pic16_freeAsmop(result,NULL,ic,TRUE); 
3478 }
3479
3480 /*-----------------------------------------------------------------*/
3481 /* genDivbits :- division of bits                                  */
3482 /*-----------------------------------------------------------------*/
3483 static void genDivbits (operand *left, 
3484                         operand *right, 
3485                         operand *result)
3486 {
3487
3488     char *l;
3489
3490     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3491     /* the result must be bit */    
3492     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3493     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3494
3495     MOVA(l);    
3496
3497     pic16_emitcode("div","ab");
3498     pic16_emitcode("rrc","a");
3499     pic16_aopPut(AOP(result),"c",0);
3500 }
3501
3502 /*-----------------------------------------------------------------*/
3503 /* genDivOneByte : 8 bit division                                  */
3504 /*-----------------------------------------------------------------*/
3505 static void genDivOneByte (operand *left,
3506                            operand *right,
3507                            operand *result)
3508 {
3509     sym_link *opetype = operandType(result);
3510     char *l ;
3511     symbol *lbl ;
3512     int size,offset;
3513
3514     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3515     size = AOP_SIZE(result) - 1;
3516     offset = 1;
3517     /* signed or unsigned */
3518     if (SPEC_USIGN(opetype)) {
3519         /* unsigned is easy */
3520         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3521         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3522         MOVA(l);        
3523         pic16_emitcode("div","ab");
3524         pic16_aopPut(AOP(result),"a",0);
3525         while (size--)
3526             pic16_aopPut(AOP(result),zero,offset++);
3527         return ;
3528     }
3529
3530     /* signed is a little bit more difficult */
3531
3532     /* save the signs of the operands */
3533     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3534     MOVA(l);    
3535     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3536     pic16_emitcode("push","acc"); /* save it on the stack */
3537
3538     /* now sign adjust for both left & right */
3539     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3540     MOVA(l);       
3541     lbl = newiTempLabel(NULL);
3542     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3543     pic16_emitcode("cpl","a");   
3544     pic16_emitcode("inc","a");
3545     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3546     pic16_emitcode("mov","b,a");
3547
3548     /* sign adjust left side */
3549     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3550     MOVA(l);
3551
3552     lbl = newiTempLabel(NULL);
3553     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3554     pic16_emitcode("cpl","a");
3555     pic16_emitcode("inc","a");
3556     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3557
3558     /* now the division */
3559     pic16_emitcode("div","ab");
3560     /* we are interested in the lower order
3561     only */
3562     pic16_emitcode("mov","b,a");
3563     lbl = newiTempLabel(NULL);
3564     pic16_emitcode("pop","acc");   
3565     /* if there was an over flow we don't 
3566     adjust the sign of the result */
3567     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3568     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3569     CLRC;
3570     pic16_emitcode("clr","a");
3571     pic16_emitcode("subb","a,b");
3572     pic16_emitcode("mov","b,a");
3573     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3574
3575     /* now we are done */
3576     pic16_aopPut(AOP(result),"b",0);
3577     if(size > 0){
3578         pic16_emitcode("mov","c,b.7");
3579         pic16_emitcode("subb","a,acc");   
3580     }
3581     while (size--)
3582         pic16_aopPut(AOP(result),"a",offset++);
3583
3584 }
3585
3586 /*-----------------------------------------------------------------*/
3587 /* genDiv - generates code for division                            */
3588 /*-----------------------------------------------------------------*/
3589 static void genDiv (iCode *ic)
3590 {
3591     operand *left = IC_LEFT(ic);
3592     operand *right = IC_RIGHT(ic);
3593     operand *result= IC_RESULT(ic);   
3594
3595     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3596     /* assign the amsops */
3597     pic16_aopOp (left,ic,FALSE);
3598     pic16_aopOp (right,ic,FALSE);
3599     pic16_aopOp (result,ic,TRUE);
3600
3601     /* special cases first */
3602     /* both are bits */
3603     if (AOP_TYPE(left) == AOP_CRY &&
3604         AOP_TYPE(right)== AOP_CRY) {
3605         genDivbits(left,right,result);
3606         goto release ;
3607     }
3608
3609     /* if both are of size == 1 */
3610     if (AOP_SIZE(left) == 1 &&
3611         AOP_SIZE(right) == 1 ) {
3612         genDivOneByte(left,right,result);
3613         goto release ;
3614     }
3615
3616     /* should have been converted to function call */
3617     assert(0);
3618 release :
3619     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3620     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3621     pic16_freeAsmop(result,NULL,ic,TRUE); 
3622 }
3623
3624 /*-----------------------------------------------------------------*/
3625 /* genModbits :- modulus of bits                                   */
3626 /*-----------------------------------------------------------------*/
3627 static void genModbits (operand *left, 
3628                         operand *right, 
3629                         operand *result)
3630 {
3631
3632     char *l;
3633
3634     /* the result must be bit */    
3635     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3636     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3637
3638     MOVA(l);       
3639
3640     pic16_emitcode("div","ab");
3641     pic16_emitcode("mov","a,b");
3642     pic16_emitcode("rrc","a");
3643     pic16_aopPut(AOP(result),"c",0);
3644 }
3645
3646 /*-----------------------------------------------------------------*/
3647 /* genModOneByte : 8 bit modulus                                   */
3648 /*-----------------------------------------------------------------*/
3649 static void genModOneByte (operand *left,
3650                            operand *right,
3651                            operand *result)
3652 {
3653     sym_link *opetype = operandType(result);
3654     char *l ;
3655     symbol *lbl ;
3656
3657     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3658     /* signed or unsigned */
3659     if (SPEC_USIGN(opetype)) {
3660         /* unsigned is easy */
3661         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3662         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3663         MOVA(l);    
3664         pic16_emitcode("div","ab");
3665         pic16_aopPut(AOP(result),"b",0);
3666         return ;
3667     }
3668
3669     /* signed is a little bit more difficult */
3670
3671     /* save the signs of the operands */
3672     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3673     MOVA(l);
3674
3675     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3676     pic16_emitcode("push","acc"); /* save it on the stack */
3677
3678     /* now sign adjust for both left & right */
3679     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3680     MOVA(l);
3681
3682     lbl = newiTempLabel(NULL);
3683     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3684     pic16_emitcode("cpl","a");   
3685     pic16_emitcode("inc","a");
3686     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3687     pic16_emitcode("mov","b,a"); 
3688
3689     /* sign adjust left side */
3690     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3691     MOVA(l);
3692
3693     lbl = newiTempLabel(NULL);
3694     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3695     pic16_emitcode("cpl","a");   
3696     pic16_emitcode("inc","a");
3697     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3698
3699     /* now the multiplication */
3700     pic16_emitcode("div","ab");
3701     /* we are interested in the lower order
3702     only */
3703     lbl = newiTempLabel(NULL);
3704     pic16_emitcode("pop","acc");   
3705     /* if there was an over flow we don't 
3706     adjust the sign of the result */
3707     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3708     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3709     CLRC ;
3710     pic16_emitcode("clr","a");
3711     pic16_emitcode("subb","a,b");
3712     pic16_emitcode("mov","b,a");
3713     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3714
3715     /* now we are done */
3716     pic16_aopPut(AOP(result),"b",0);
3717
3718 }
3719
3720 /*-----------------------------------------------------------------*/
3721 /* genMod - generates code for division                            */
3722 /*-----------------------------------------------------------------*/
3723 static void genMod (iCode *ic)
3724 {
3725     operand *left = IC_LEFT(ic);
3726     operand *right = IC_RIGHT(ic);
3727     operand *result= IC_RESULT(ic);  
3728
3729     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3730     /* assign the amsops */
3731     pic16_aopOp (left,ic,FALSE);
3732     pic16_aopOp (right,ic,FALSE);
3733     pic16_aopOp (result,ic,TRUE);
3734
3735     /* special cases first */
3736     /* both are bits */
3737     if (AOP_TYPE(left) == AOP_CRY &&
3738         AOP_TYPE(right)== AOP_CRY) {
3739         genModbits(left,right,result);
3740         goto release ;
3741     }
3742
3743     /* if both are of size == 1 */
3744     if (AOP_SIZE(left) == 1 &&
3745         AOP_SIZE(right) == 1 ) {
3746         genModOneByte(left,right,result);
3747         goto release ;
3748     }
3749
3750     /* should have been converted to function call */
3751     assert(0);
3752
3753 release :
3754     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3755     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3756     pic16_freeAsmop(result,NULL,ic,TRUE); 
3757 }
3758
3759 /*-----------------------------------------------------------------*/
3760 /* genIfxJump :- will create a jump depending on the ifx           */
3761 /*-----------------------------------------------------------------*/
3762 /*
3763   note: May need to add parameter to indicate when a variable is in bit space.
3764 */
3765 static void genIfxJump (iCode *ic, char *jval)
3766 {
3767
3768     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3769     /* if true label then we jump if condition
3770     supplied is true */
3771     if ( IC_TRUE(ic) ) {
3772
3773         if(strcmp(jval,"a") == 0)
3774           emitSKPZ;
3775         else if (strcmp(jval,"c") == 0)
3776           emitSKPC;
3777         else {
3778           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3779           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
3780         }
3781
3782         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
3783         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3784
3785     }
3786     else {
3787         /* false label is present */
3788         if(strcmp(jval,"a") == 0)
3789           emitSKPNZ;
3790         else if (strcmp(jval,"c") == 0)
3791           emitSKPNC;
3792         else {
3793           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3794           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
3795         }
3796
3797         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
3798         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3799
3800     }
3801
3802
3803     /* mark the icode as generated */
3804     ic->generated = 1;
3805 }
3806
3807 /*-----------------------------------------------------------------*/
3808 /* genSkip                                                         */
3809 /*-----------------------------------------------------------------*/
3810 static void genSkip(iCode *ifx,int status_bit)
3811 {
3812   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3813   if(!ifx)
3814     return;
3815
3816   if ( IC_TRUE(ifx) ) {
3817     switch(status_bit) {
3818     case 'z':
3819       emitSKPNZ;
3820       break;
3821
3822     case 'c':
3823       emitSKPNC;
3824       break;
3825
3826     case 'd':
3827       emitSKPDC;
3828       break;
3829
3830     }
3831
3832     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3833     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3834
3835   } else {
3836
3837     switch(status_bit) {
3838
3839     case 'z':
3840       emitSKPZ;
3841       break;
3842
3843     case 'c':
3844       emitSKPC;
3845       break;
3846
3847     case 'd':
3848       emitSKPDC;
3849       break;
3850     }
3851     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3852     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3853
3854   }
3855
3856 }
3857
3858 /*-----------------------------------------------------------------*/
3859 /* genSkipc                                                        */
3860 /*-----------------------------------------------------------------*/
3861 static void genSkipc(resolvedIfx *rifx)
3862 {
3863   if(!rifx)
3864     return;
3865
3866   if(rifx->condition)
3867     emitSKPC;
3868   else
3869     emitSKPNC;
3870
3871   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3872   rifx->generated = 1;
3873 }
3874
3875 /*-----------------------------------------------------------------*/
3876 /* genSkipz2                                                       */
3877 /*-----------------------------------------------------------------*/
3878 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3879 {
3880   if(!rifx)
3881     return;
3882
3883   if( (rifx->condition ^ invert_condition) & 1)
3884     emitSKPZ;
3885   else
3886     emitSKPNZ;
3887
3888   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3889   rifx->generated = 1;
3890 }
3891
3892 #if 0
3893 /*-----------------------------------------------------------------*/
3894 /* genSkipz                                                        */
3895 /*-----------------------------------------------------------------*/
3896 static void genSkipz(iCode *ifx, int condition)
3897 {
3898   if(!ifx)
3899     return;
3900
3901   if(condition)
3902     emitSKPNZ;
3903   else
3904     emitSKPZ;
3905
3906   if ( IC_TRUE(ifx) )
3907     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3908   else
3909     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3910
3911   if ( IC_TRUE(ifx) )
3912     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3913   else
3914     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3915
3916 }
3917 #endif
3918
3919 /*-----------------------------------------------------------------*/
3920 /* genSkipCond                                                     */
3921 /*-----------------------------------------------------------------*/
3922 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3923 {
3924   if(!rifx)
3925     return;
3926
3927   if(rifx->condition)
3928     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3929   else
3930     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3931
3932
3933   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3934   rifx->generated = 1;
3935 }
3936
3937 #if 0
3938 /*-----------------------------------------------------------------*/
3939 /* genChkZeroes :- greater or less than comparison                 */
3940 /*     For each byte in a literal that is zero, inclusive or the   */
3941 /*     the corresponding byte in the operand with W                */
3942 /*     returns true if any of the bytes are zero                   */
3943 /*-----------------------------------------------------------------*/
3944 static int genChkZeroes(operand *op, int lit,  int size)
3945 {
3946
3947   int i;
3948   int flag =1;
3949
3950   while(size--) {
3951     i = (lit >> (size*8)) & 0xff;
3952
3953     if(i==0) {
3954       if(flag) 
3955         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
3956       else
3957         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
3958       flag = 0;
3959     }
3960   }
3961
3962   return (flag==0);
3963 }
3964 #endif
3965
3966 /*-----------------------------------------------------------------*/
3967 /* genCmp :- greater or less than comparison                       */
3968 /*-----------------------------------------------------------------*/
3969 static void genCmp (operand *left,operand *right,
3970                     operand *result, iCode *ifx, int sign)
3971 {
3972   int size; //, offset = 0 ;
3973   unsigned long lit = 0L,i = 0;
3974   resolvedIfx rFalseIfx;
3975   //  resolvedIfx rTrueIfx;
3976   symbol *truelbl;
3977   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3978 /*
3979   if(ifx) {
3980     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3981     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3982   }
3983 */
3984
3985   resolveIfx(&rFalseIfx,ifx);
3986   truelbl  = newiTempLabel(NULL);
3987   size = max(AOP_SIZE(left),AOP_SIZE(right));
3988
3989   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3990
3991 #define _swapp
3992
3993   /* if literal is on the right then swap with left */
3994   if ((AOP_TYPE(right) == AOP_LIT)) {
3995     operand *tmp = right ;
3996     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3997     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3998 #ifdef _swapp
3999
4000     lit = (lit - 1) & mask;
4001     right = left;
4002     left = tmp;
4003     rFalseIfx.condition ^= 1;
4004 #endif
4005
4006   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4007     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4008   }
4009
4010
4011   //if(IC_TRUE(ifx) == NULL)
4012   /* if left & right are bit variables */
4013   if (AOP_TYPE(left) == AOP_CRY &&
4014       AOP_TYPE(right) == AOP_CRY ) {
4015     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4016     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4017   } else {
4018     /* subtract right from left if at the
4019        end the carry flag is set then we know that
4020        left is greater than right */
4021
4022     //    {
4023
4024     symbol *lbl  = newiTempLabel(NULL);
4025
4026 #ifndef _swapp
4027     if(AOP_TYPE(right) == AOP_LIT) {
4028
4029       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4030
4031       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4032
4033       /* special cases */
4034
4035       if(lit == 0) {
4036
4037         if(sign != 0) 
4038           genSkipCond(&rFalseIfx,left,size-1,7);
4039         else 
4040           /* no need to compare to 0...*/
4041           /* NOTE: this is a de-generate compare that most certainly 
4042            *       creates some dead code. */
4043           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4044
4045         if(ifx) ifx->generated = 1;
4046         return;
4047
4048       }
4049       size--;
4050
4051       if(size == 0) {
4052         //i = (lit >> (size*8)) & 0xff;
4053         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4054         
4055         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4056
4057         i = ((0-lit) & 0xff);
4058         if(sign) {
4059           if( i == 0x81) { 
4060             /* lit is 0x7f, all signed chars are less than
4061              * this except for 0x7f itself */
4062             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4063             genSkipz2(&rFalseIfx,0);
4064           } else {
4065             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4066             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4067             genSkipc(&rFalseIfx);
4068           }
4069
4070         } else {
4071           if(lit == 1) {
4072             genSkipz2(&rFalseIfx,1);
4073           } else {
4074             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4075             genSkipc(&rFalseIfx);
4076           }
4077         }
4078
4079         if(ifx) ifx->generated = 1;
4080         return;
4081       }
4082
4083       /* chars are out of the way. now do ints and longs */
4084
4085
4086       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4087         
4088       /* special cases */
4089
4090       if(sign) {
4091
4092         if(lit == 0) {
4093           genSkipCond(&rFalseIfx,left,size,7);
4094           if(ifx) ifx->generated = 1;
4095           return;
4096         }
4097
4098         if(lit <0x100) {
4099           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4100
4101           //rFalseIfx.condition ^= 1;
4102           //genSkipCond(&rFalseIfx,left,size,7);
4103           //rFalseIfx.condition ^= 1;
4104
4105           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4106           if(rFalseIfx.condition)
4107             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4108           else
4109             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4110
4111           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4112           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4113           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4114
4115           while(size > 1)
4116             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4117
4118           if(rFalseIfx.condition) {
4119             emitSKPZ;
4120             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4121
4122           } else {
4123             emitSKPNZ;
4124           }
4125
4126           genSkipc(&rFalseIfx);
4127           pic16_emitpLabel(truelbl->key);
4128           if(ifx) ifx->generated = 1;
4129           return;
4130
4131         }
4132
4133         if(size == 1) {
4134
4135           if( (lit & 0xff) == 0) {
4136             /* lower byte is zero */
4137             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4138             i = ((lit >> 8) & 0xff) ^0x80;
4139             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4140             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4141             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4142             genSkipc(&rFalseIfx);
4143
4144
4145             if(ifx) ifx->generated = 1;
4146             return;
4147
4148           }
4149         } else {
4150           /* Special cases for signed longs */
4151           if( (lit & 0xffffff) == 0) {
4152             /* lower byte is zero */
4153             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4154             i = ((lit >> 8*3) & 0xff) ^0x80;
4155             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4156             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4157             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4158             genSkipc(&rFalseIfx);
4159
4160
4161             if(ifx) ifx->generated = 1;
4162             return;
4163
4164           }
4165
4166         }
4167
4168
4169         if(lit & (0x80 << (size*8))) {
4170           /* lit is negative */
4171           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4172
4173           //genSkipCond(&rFalseIfx,left,size,7);
4174
4175           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4176
4177           if(rFalseIfx.condition)
4178             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4179           else
4180             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4181
4182
4183         } else {
4184           /* lit is positive */
4185           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4186           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4187           if(rFalseIfx.condition)
4188             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4189           else
4190             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4191
4192         }
4193
4194         /*
4195           This works, but is only good for ints.
4196           It also requires a "known zero" register.
4197           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4198           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4199           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4200           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4201           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4202           genSkipc(&rFalseIfx);
4203
4204           pic16_emitpLabel(truelbl->key);
4205           if(ifx) ifx->generated = 1;
4206           return;
4207         **/
4208           
4209         /* There are no more special cases, so perform a general compare */
4210   
4211         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4212         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4213
4214         while(size--) {
4215
4216           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4217           emitSKPNZ;
4218           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4219         }
4220         //rFalseIfx.condition ^= 1;
4221         genSkipc(&rFalseIfx);
4222
4223         pic16_emitpLabel(truelbl->key);
4224
4225         if(ifx) ifx->generated = 1;
4226         return;
4227
4228
4229       }
4230
4231
4232       /* sign is out of the way. So now do an unsigned compare */
4233       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4234
4235
4236       /* General case - compare to an unsigned literal on the right.*/
4237
4238       i = (lit >> (size*8)) & 0xff;
4239       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4240       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4241       while(size--) {
4242         i = (lit >> (size*8)) & 0xff;
4243
4244         if(i) {
4245           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4246           emitSKPNZ;
4247           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4248         } else {
4249           /* this byte of the lit is zero, 
4250            *if it's not the last then OR in the variable */
4251           if(size)
4252             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4253         }
4254       }
4255
4256
4257       pic16_emitpLabel(lbl->key);
4258       //if(emitFinalCheck)
4259       genSkipc(&rFalseIfx);
4260       if(sign)
4261         pic16_emitpLabel(truelbl->key);
4262
4263       if(ifx) ifx->generated = 1;
4264       return;
4265
4266
4267     }
4268 #endif  // _swapp
4269
4270     if(AOP_TYPE(left) == AOP_LIT) {
4271       //symbol *lbl = newiTempLabel(NULL);
4272
4273       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4274
4275
4276       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4277
4278       /* Special cases */
4279       if((lit == 0) && (sign == 0)){
4280
4281         size--;
4282         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4283         while(size) 
4284           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4285
4286         genSkipz2(&rFalseIfx,0);
4287         if(ifx) ifx->generated = 1;
4288         return;
4289       }
4290
4291       if(size==1) {
4292         /* Special cases */
4293         lit &= 0xff;
4294         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4295           /* degenerate compare can never be true */
4296           if(rFalseIfx.condition == 0)
4297             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4298
4299           if(ifx) ifx->generated = 1;
4300           return;
4301         }
4302
4303         if(sign) {
4304           /* signed comparisons to a literal byte */
4305
4306           int lp1 = (lit+1) & 0xff;
4307
4308           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4309           switch (lp1) {
4310           case 0:
4311             rFalseIfx.condition ^= 1;
4312             genSkipCond(&rFalseIfx,right,0,7);
4313             break;
4314           case 0x7f:
4315             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4316             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4317             genSkipz2(&rFalseIfx,1);
4318             break;
4319           default:
4320             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4321             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4322             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4323             rFalseIfx.condition ^= 1;
4324             genSkipc(&rFalseIfx);
4325             break;
4326           }
4327         } else {
4328           /* unsigned comparisons to a literal byte */
4329
4330           switch(lit & 0xff ) {
4331           case 0:
4332             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4333             genSkipz2(&rFalseIfx,0);
4334             break;
4335           case 0x7f:
4336             rFalseIfx.condition ^= 1;
4337             genSkipCond(&rFalseIfx,right,0,7);
4338             break;
4339
4340           default:
4341             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4342             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4343             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4344             rFalseIfx.condition ^= 1;
4345             if (AOP_TYPE(result) == AOP_CRY)
4346               genSkipc(&rFalseIfx);
4347             else {
4348               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4349               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4350             }         
4351             break;
4352           }
4353         }
4354
4355         if(ifx) ifx->generated = 1;
4356         //goto check_carry;
4357         return;
4358
4359       } else {
4360
4361         /* Size is greater than 1 */
4362
4363         if(sign) {
4364           int lp1 = lit+1;
4365
4366           size--;
4367
4368           if(lp1 == 0) {
4369             /* this means lit = 0xffffffff, or -1 */
4370
4371
4372             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4373             rFalseIfx.condition ^= 1;
4374             genSkipCond(&rFalseIfx,right,size,7);
4375             if(ifx) ifx->generated = 1;
4376             return;
4377           }
4378
4379           if(lit == 0) {
4380             int s = size;
4381
4382             if(rFalseIfx.condition) {
4383               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4384               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4385             }
4386
4387             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4388             while(size--)
4389               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4390
4391
4392             emitSKPZ;
4393             if(rFalseIfx.condition) {
4394               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4395               pic16_emitpLabel(truelbl->key);
4396             }else {
4397               rFalseIfx.condition ^= 1;
4398               genSkipCond(&rFalseIfx,right,s,7);
4399             }
4400
4401             if(ifx) ifx->generated = 1;
4402             return;
4403           }
4404
4405           if((size == 1) &&  (0 == (lp1&0xff))) {
4406             /* lower byte of signed word is zero */
4407             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4408             i = ((lp1 >> 8) & 0xff) ^0x80;
4409             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4410             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4411             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4412             rFalseIfx.condition ^= 1;
4413             genSkipc(&rFalseIfx);
4414
4415
4416             if(ifx) ifx->generated = 1;
4417             return;
4418           }
4419
4420           if(lit & (0x80 << (size*8))) {
4421             /* Lit is less than zero */
4422             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4423             //rFalseIfx.condition ^= 1;
4424             //genSkipCond(&rFalseIfx,left,size,7);
4425             //rFalseIfx.condition ^= 1;
4426             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4427             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4428
4429             if(rFalseIfx.condition)
4430               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4431             else
4432               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4433
4434
4435           } else {
4436             /* Lit is greater than or equal to zero */
4437             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4438             //rFalseIfx.condition ^= 1;
4439             //genSkipCond(&rFalseIfx,right,size,7);
4440             //rFalseIfx.condition ^= 1;
4441
4442             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4443             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4444
4445             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4446             if(rFalseIfx.condition)
4447               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4448             else
4449               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4450
4451           }
4452
4453
4454           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4455           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4456
4457           while(size--) {
4458
4459             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4460             emitSKPNZ;
4461             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4462           }
4463           rFalseIfx.condition ^= 1;
4464           //rFalseIfx.condition = 1;
4465           genSkipc(&rFalseIfx);
4466
4467           pic16_emitpLabel(truelbl->key);
4468
4469           if(ifx) ifx->generated = 1;
4470           return;
4471           // end of if (sign)
4472         } else {
4473
4474           /* compare word or long to an unsigned literal on the right.*/
4475
4476
4477           size--;
4478           if(lit < 0xff) {
4479             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4480             switch (lit) {
4481             case 0:
4482               break; /* handled above */
4483 /*
4484             case 0xff:
4485               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4486               while(size--)
4487                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4488               genSkipz2(&rFalseIfx,0);
4489               break;
4490 */
4491             default:
4492               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4493               while(--size)
4494                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4495
4496               emitSKPZ;
4497               if(rFalseIfx.condition)
4498                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4499               else
4500                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4501
4502
4503               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4504               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4505
4506               rFalseIfx.condition ^= 1;
4507               genSkipc(&rFalseIfx);
4508             }
4509
4510             pic16_emitpLabel(truelbl->key);
4511
4512             if(ifx) ifx->generated = 1;
4513             return;
4514           }
4515
4516
4517           lit++;
4518           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4519           i = (lit >> (size*8)) & 0xff;
4520
4521           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4522           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4523
4524           while(size--) {
4525             i = (lit >> (size*8)) & 0xff;
4526
4527             if(i) {
4528               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4529               emitSKPNZ;
4530               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4531             } else {
4532               /* this byte of the lit is zero, 
4533                *if it's not the last then OR in the variable */
4534               if(size)
4535                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4536             }
4537           }
4538
4539
4540           pic16_emitpLabel(lbl->key);
4541
4542           rFalseIfx.condition ^= 1;
4543           genSkipc(&rFalseIfx);
4544         }
4545
4546         if(sign)
4547           pic16_emitpLabel(truelbl->key);
4548         if(ifx) ifx->generated = 1;
4549         return;
4550       }
4551     }
4552     /* Compare two variables */
4553
4554     DEBUGpic16_emitcode(";sign","%d",sign);
4555
4556     size--;
4557     if(sign) {
4558       /* Sigh. thus sucks... */
4559       if(size) {
4560         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4561         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4562         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4563         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4564         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4565         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4566       } else {
4567         /* Signed char comparison */
4568         /* Special thanks to Nikolai Golovchenko for this snippet */
4569         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4570         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4571         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
4572         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4573         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4574         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4575
4576         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4577         genSkipc(&rFalseIfx);
4578           
4579         if(ifx) ifx->generated = 1;
4580         return;
4581       }
4582
4583     } else {
4584
4585       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4586       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4587     }
4588
4589
4590     /* The rest of the bytes of a multi-byte compare */
4591     while (size) {
4592
4593       emitSKPZ;
4594       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
4595       size--;
4596
4597       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4598       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4599
4600
4601     }
4602
4603     pic16_emitpLabel(lbl->key);
4604
4605     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4606     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4607         (AOP_TYPE(result) == AOP_REG)) {
4608       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4609       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4610     } else {
4611       genSkipc(&rFalseIfx);
4612     }         
4613     //genSkipc(&rFalseIfx);
4614     if(ifx) ifx->generated = 1;
4615
4616     return;
4617
4618   }
4619
4620   // check_carry:
4621   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4622     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4623     pic16_outBitC(result);
4624   } else {
4625     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4626     /* if the result is used in the next
4627        ifx conditional branch then generate
4628        code a little differently */
4629     if (ifx )
4630       genIfxJump (ifx,"c");
4631     else
4632       pic16_outBitC(result);
4633     /* leave the result in acc */
4634   }
4635
4636 }
4637
4638 /*-----------------------------------------------------------------*/
4639 /* genCmpGt :- greater than comparison                             */
4640 /*-----------------------------------------------------------------*/
4641 static void genCmpGt (iCode *ic, iCode *ifx)
4642 {
4643     operand *left, *right, *result;
4644     sym_link *letype , *retype;
4645     int sign ;
4646
4647     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4648     left = IC_LEFT(ic);
4649     right= IC_RIGHT(ic);
4650     result = IC_RESULT(ic);
4651
4652     letype = getSpec(operandType(left));
4653     retype =getSpec(operandType(right));
4654     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4655     /* assign the amsops */
4656     pic16_aopOp (left,ic,FALSE);
4657     pic16_aopOp (right,ic,FALSE);
4658     pic16_aopOp (result,ic,TRUE);
4659
4660     genCmp(right, left, result, ifx, sign);
4661
4662     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4663     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4664     pic16_freeAsmop(result,NULL,ic,TRUE); 
4665 }
4666
4667 /*-----------------------------------------------------------------*/
4668 /* genCmpLt - less than comparisons                                */
4669 /*-----------------------------------------------------------------*/
4670 static void genCmpLt (iCode *ic, iCode *ifx)
4671 {
4672     operand *left, *right, *result;
4673     sym_link *letype , *retype;
4674     int sign ;
4675
4676     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4677     left = IC_LEFT(ic);
4678     right= IC_RIGHT(ic);
4679     result = IC_RESULT(ic);
4680
4681     letype = getSpec(operandType(left));
4682     retype =getSpec(operandType(right));
4683     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4684
4685     /* assign the amsops */
4686     pic16_aopOp (left,ic,FALSE);
4687     pic16_aopOp (right,ic,FALSE);
4688     pic16_aopOp (result,ic,TRUE);
4689
4690     genCmp(left, right, result, ifx, sign);
4691
4692     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4693     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4694     pic16_freeAsmop(result,NULL,ic,TRUE); 
4695 }
4696
4697 /*-----------------------------------------------------------------*/
4698 /* genc16bit2lit - compare a 16 bit value to a literal             */
4699 /*-----------------------------------------------------------------*/
4700 static void genc16bit2lit(operand *op, int lit, int offset)
4701 {
4702   int i;
4703
4704   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4705   if( (lit&0xff) == 0) 
4706     i=1;
4707   else
4708     i=0;
4709
4710   switch( BYTEofLONG(lit,i)) { 
4711   case 0:
4712     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4713     break;
4714   case 1:
4715     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4716     break;
4717   case 0xff:
4718     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4719     break;
4720   default:
4721     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4722     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4723   }
4724
4725   i ^= 1;
4726
4727   switch( BYTEofLONG(lit,i)) { 
4728   case 0:
4729     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
4730     break;
4731   case 1:
4732     emitSKPNZ;
4733     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4734     break;
4735   case 0xff:
4736     emitSKPNZ;
4737     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4738     break;
4739   default:
4740     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4741     emitSKPNZ;
4742     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
4743
4744   }
4745
4746 }
4747
4748 /*-----------------------------------------------------------------*/
4749 /* gencjneshort - compare and jump if not equal                    */
4750 /*-----------------------------------------------------------------*/
4751 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4752 {
4753   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4754   int offset = 0;
4755   int res_offset = 0;  /* the result may be a different size then left or right */
4756   int res_size = AOP_SIZE(result);
4757   resolvedIfx rIfx;
4758   symbol *lbl;
4759
4760   unsigned long lit = 0L;
4761   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4762   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4763   if(result)
4764     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4765   resolveIfx(&rIfx,ifx);
4766   lbl =  newiTempLabel(NULL);
4767
4768
4769   /* if the left side is a literal or 
4770      if the right is in a pointer register and left 
4771      is not */
4772   if ((AOP_TYPE(left) == AOP_LIT) || 
4773       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4774     operand *t = right;
4775     right = left;
4776     left = t;
4777   }
4778   if(AOP_TYPE(right) == AOP_LIT)
4779     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4780
4781   /* if the right side is a literal then anything goes */
4782   if (AOP_TYPE(right) == AOP_LIT &&
4783       AOP_TYPE(left) != AOP_DIR ) {
4784     switch(size) {
4785     case 2:
4786       genc16bit2lit(left, lit, 0);
4787       emitSKPNZ;
4788       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4789       break;
4790     default:
4791       while (size--) {
4792         if(lit & 0xff) {
4793           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4794           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4795         } else {
4796           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4797         }
4798
4799         emitSKPNZ;
4800         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4801         offset++;
4802         if(res_offset < res_size-1)
4803           res_offset++;
4804         lit >>= 8;
4805       }
4806       break;
4807     }
4808   }
4809
4810   /* if the right side is in a register or in direct space or
4811      if the left is a pointer register & right is not */    
4812   else if (AOP_TYPE(right) == AOP_REG ||
4813            AOP_TYPE(right) == AOP_DIR || 
4814            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4815            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4816     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4817     int lbl_key = lbl->key;
4818
4819     if(result) {
4820       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
4821       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4822     }else {
4823       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4824       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4825               __FUNCTION__,__LINE__);
4826       return;
4827     }
4828
4829 /*     switch(size) { */
4830 /*     case 2: */
4831 /*       genc16bit2lit(left, lit, 0); */
4832 /*       emitSKPNZ; */
4833 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
4834 /*       break; */
4835 /*     default: */
4836     while (size--) {
4837       int emit_skip=1;
4838       if((AOP_TYPE(left) == AOP_DIR) && 
4839          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4840
4841         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4842         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4843
4844       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4845             
4846         switch (lit & 0xff) {
4847         case 0:
4848           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4849           break;
4850         case 1:
4851           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4852           pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4853           //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4854           emit_skip=0;
4855           break;
4856         case 0xff:
4857           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4858           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4859           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4860           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4861           emit_skip=0;
4862           break;
4863         default:
4864           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4865           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4866         }
4867         lit >>= 8;
4868
4869       } else {
4870         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4871       }
4872       if(emit_skip) {
4873         if(AOP_TYPE(result) == AOP_CRY) {
4874           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4875           if(rIfx.condition)
4876             emitSKPNZ;
4877           else
4878             emitSKPZ;
4879           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4880         } else {
4881           /* fix me. probably need to check result size too */
4882           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
4883           if(rIfx.condition)
4884             emitSKPZ;
4885           else
4886             emitSKPNZ;
4887           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4888           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4889         }
4890         if(ifx)
4891           ifx->generated=1;
4892       }
4893       emit_skip++;
4894       offset++;
4895       if(res_offset < res_size-1)
4896         res_offset++;
4897     }
4898 /*       break; */
4899 /*     } */
4900   } else if(AOP_TYPE(right) == AOP_REG &&
4901             AOP_TYPE(left) != AOP_DIR){
4902
4903     while(size--) {
4904       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4905       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4906       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4907       if(rIfx.condition)
4908         emitSKPNZ;
4909       else
4910         emitSKPZ;
4911       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4912       offset++;
4913       if(res_offset < res_size-1)
4914         res_offset++;
4915     }
4916       
4917   }else{
4918     /* right is a pointer reg need both a & b */
4919     while(size--) {
4920       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
4921       if(strcmp(l,"b"))
4922         pic16_emitcode("mov","b,%s",l);
4923       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
4924       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4925       offset++;
4926     }
4927   }
4928
4929   pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4930   if(!rIfx.condition)
4931     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4932
4933   pic16_emitpLabel(lbl->key);
4934
4935   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4936
4937   if(ifx)
4938     ifx->generated = 1;
4939 }
4940
4941 #if 0
4942 /*-----------------------------------------------------------------*/
4943 /* gencjne - compare and jump if not equal                         */
4944 /*-----------------------------------------------------------------*/
4945 static void gencjne(operand *left, operand *right, iCode *ifx)
4946 {
4947     symbol *tlbl  = newiTempLabel(NULL);
4948
4949     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4950     gencjneshort(left, right, lbl);
4951
4952     pic16_emitcode("mov","a,%s",one);
4953     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4954     pic16_emitcode("","%05d_DS_:",lbl->key+100);
4955     pic16_emitcode("clr","a");
4956     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
4957
4958     pic16_emitpLabel(lbl->key);
4959     pic16_emitpLabel(tlbl->key);
4960
4961 }
4962 #endif
4963
4964 /*-----------------------------------------------------------------*/
4965 /* genCmpEq - generates code for equal to                          */
4966 /*-----------------------------------------------------------------*/
4967 static void genCmpEq (iCode *ic, iCode *ifx)
4968 {
4969     operand *left, *right, *result;
4970     unsigned long lit = 0L;
4971     int size,offset=0;
4972     symbol *falselbl  = newiTempLabel(NULL);
4973
4974
4975     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4976
4977     if(ifx)
4978       DEBUGpic16_emitcode ("; ifx is non-null","");
4979     else
4980       DEBUGpic16_emitcode ("; ifx is null","");
4981
4982     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4983     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4984     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4985
4986     size = max(AOP_SIZE(left),AOP_SIZE(right));
4987
4988     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4989
4990     /* if literal, literal on the right or 
4991     if the right is in a pointer register and left 
4992     is not */
4993     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4994         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4995       operand *tmp = right ;
4996       right = left;
4997       left = tmp;
4998     }
4999
5000
5001     if(ifx && !AOP_SIZE(result)){
5002         symbol *tlbl;
5003         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5004         /* if they are both bit variables */
5005         if (AOP_TYPE(left) == AOP_CRY &&
5006             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5007                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5008             if(AOP_TYPE(right) == AOP_LIT){
5009                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5010                 if(lit == 0L){
5011                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5012                     pic16_emitcode("cpl","c");
5013                 } else if(lit == 1L) {
5014                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5015                 } else {
5016                     pic16_emitcode("clr","c");
5017                 }
5018                 /* AOP_TYPE(right) == AOP_CRY */
5019             } else {
5020                 symbol *lbl = newiTempLabel(NULL);
5021                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5022                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5023                 pic16_emitcode("cpl","c");
5024                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5025             }
5026             /* if true label then we jump if condition
5027             supplied is true */
5028             tlbl = newiTempLabel(NULL);
5029             if ( IC_TRUE(ifx) ) {
5030                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5031                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5032             } else {
5033                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5034                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5035             }
5036             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5037
5038                 {
5039                 /* left and right are both bit variables, result is carry */
5040                         resolvedIfx rIfx;
5041               
5042                         resolveIfx(&rIfx,ifx);
5043
5044                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5045                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5046                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5047                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5048                         genSkipz2(&rIfx,0);
5049                 }
5050         } else {
5051
5052                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5053
5054                         /* They're not both bit variables. Is the right a literal? */
5055                         if(AOP_TYPE(right) == AOP_LIT) {
5056                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5057             
5058                         switch(size) {
5059
5060                                 case 1:
5061                                         switch(lit & 0xff) {
5062                                                 case 1:
5063                                                                 if ( IC_TRUE(ifx) ) {
5064                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5065                                                                         emitSKPNZ;
5066                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5067                                                                 } else {
5068                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5069                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5070                                                                 }
5071                                                                 break;
5072                                                 case 0xff:
5073                                                                 if ( IC_TRUE(ifx) ) {
5074                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5075                                                                         emitSKPNZ;
5076                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5077                                                                 } else {
5078                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5079                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5080                                                                 }
5081                                                                 break;
5082                                                 default:
5083                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5084                                                                 if(lit)
5085                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5086                                                                 genSkip(ifx,'z');
5087                                         } // switch lit
5088
5089
5090                                         /* end of size == 1 */
5091                                         break;
5092               
5093                                 case 2:
5094                                         genc16bit2lit(left,lit,offset);
5095                                         genSkip(ifx,'z');
5096                                         break;
5097                                         /* end of size == 2 */
5098
5099                                 default:
5100                                         /* size is 4 */
5101                                         if(lit==0) {
5102                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5103                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5104                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5105                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5106                                                 genSkip(ifx,'z');
5107                                         } else {
5108                                                 /* search for patterns that can be optimized */
5109
5110                                                 genc16bit2lit(left,lit,0);
5111                                                 lit >>= 16;
5112                                                 if(lit) {
5113                                                                 if(IC_TRUE(ifx))
5114                                                                 emitSKPZ; // if hi word unequal
5115                                                                 else
5116                                                                 emitSKPNZ; // if hi word equal
5117                                                                 // fail early
5118                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5119                                                         genc16bit2lit(left,lit,2);
5120                                                         genSkip(ifx,'z');
5121                                                 } else {
5122                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5123                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5124                                                         genSkip(ifx,'z');
5125                                                 }
5126                                         }
5127                                                 pic16_emitpLabel(falselbl->key);
5128                                                 break;
5129
5130                         } // switch size
5131           
5132                         ifx->generated = 1;
5133                         goto release ;
5134             
5135
5136           } else if(AOP_TYPE(right) == AOP_CRY ) {
5137             /* we know the left is not a bit, but that the right is */
5138             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5139             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5140                       pic16_popGet(AOP(right),offset));
5141             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5142
5143             /* if the two are equal, then W will be 0 and the Z bit is set
5144              * we could test Z now, or go ahead and check the high order bytes if
5145              * the variable we're comparing is larger than a byte. */
5146
5147             while(--size)
5148               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5149
5150             if ( IC_TRUE(ifx) ) {
5151               emitSKPNZ;
5152               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5153               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5154             } else {
5155               emitSKPZ;
5156               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5157               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5158             }
5159
5160           } else {
5161             /* They're both variables that are larger than bits */
5162             int s = size;
5163
5164             tlbl = newiTempLabel(NULL);
5165
5166             while(size--) {
5167               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5168               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5169
5170               if ( IC_TRUE(ifx) ) {
5171                 if(size) {
5172                   emitSKPZ;
5173                 
5174                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5175
5176                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5177                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5178                 } else {
5179                   emitSKPNZ;
5180
5181                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5182
5183
5184                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5185                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5186                 }
5187               } else {
5188                 emitSKPZ;
5189
5190                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5191
5192                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5193                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5194               }
5195               offset++;
5196             }
5197             if(s>1 && IC_TRUE(ifx)) {
5198               pic16_emitpLabel(tlbl->key);
5199               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5200             }
5201           }
5202         }
5203         /* mark the icode as generated */
5204         ifx->generated = 1;
5205         goto release ;
5206     }
5207
5208     /* if they are both bit variables */
5209     if (AOP_TYPE(left) == AOP_CRY &&
5210         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5211         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5212         if(AOP_TYPE(right) == AOP_LIT){
5213             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5214             if(lit == 0L){
5215                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5216                 pic16_emitcode("cpl","c");
5217             } else if(lit == 1L) {
5218                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5219             } else {
5220                 pic16_emitcode("clr","c");
5221             }
5222             /* AOP_TYPE(right) == AOP_CRY */
5223         } else {
5224             symbol *lbl = newiTempLabel(NULL);
5225             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5226             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5227             pic16_emitcode("cpl","c");
5228             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5229         }
5230         /* c = 1 if egal */
5231         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5232             pic16_outBitC(result);
5233             goto release ;
5234         }
5235         if (ifx) {
5236             genIfxJump (ifx,"c");
5237             goto release ;
5238         }
5239         /* if the result is used in an arithmetic operation
5240         then put the result in place */
5241         pic16_outBitC(result);
5242     } else {
5243       
5244       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5245       gencjne(left,right,result,ifx);
5246 /*
5247       if(ifx) 
5248         gencjne(left,right,newiTempLabel(NULL));
5249       else {
5250         if(IC_TRUE(ifx)->key)
5251           gencjne(left,right,IC_TRUE(ifx)->key);
5252         else
5253           gencjne(left,right,IC_FALSE(ifx)->key);
5254         ifx->generated = 1;
5255         goto release ;
5256       }
5257       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5258         pic16_aopPut(AOP(result),"a",0);
5259         goto release ;
5260       }
5261
5262       if (ifx) {
5263         genIfxJump (ifx,"a");
5264         goto release ;
5265       }
5266 */
5267       /* if the result is used in an arithmetic operation
5268          then put the result in place */
5269 /*
5270       if (AOP_TYPE(result) != AOP_CRY) 
5271         pic16_outAcc(result);
5272 */
5273       /* leave the result in acc */
5274     }
5275
5276 release:
5277     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5278     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5279     pic16_freeAsmop(result,NULL,ic,TRUE);
5280 }
5281
5282 /*-----------------------------------------------------------------*/
5283 /* ifxForOp - returns the icode containing the ifx for operand     */
5284 /*-----------------------------------------------------------------*/
5285 static iCode *ifxForOp ( operand *op, iCode *ic )
5286 {
5287     /* if true symbol then needs to be assigned */
5288     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5289     if (IS_TRUE_SYMOP(op))
5290         return NULL ;
5291
5292     /* if this has register type condition and
5293     the next instruction is ifx with the same operand
5294     and live to of the operand is upto the ifx only then */
5295     if (ic->next &&
5296         ic->next->op == IFX &&
5297         IC_COND(ic->next)->key == op->key &&
5298         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5299         return ic->next;
5300
5301     if (ic->next &&
5302         ic->next->op == IFX &&
5303         IC_COND(ic->next)->key == op->key) {
5304       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5305       return ic->next;
5306     }
5307
5308     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5309     if (ic->next &&
5310         ic->next->op == IFX)
5311       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5312
5313     if (ic->next &&
5314         ic->next->op == IFX &&
5315         IC_COND(ic->next)->key == op->key) {
5316       DEBUGpic16_emitcode ("; "," key is okay");
5317       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5318                            OP_SYMBOL(op)->liveTo,
5319                            ic->next->seq);
5320     }
5321
5322
5323     return NULL;
5324 }
5325 /*-----------------------------------------------------------------*/
5326 /* genAndOp - for && operation                                     */
5327 /*-----------------------------------------------------------------*/
5328 static void genAndOp (iCode *ic)
5329 {
5330     operand *left,*right, *result;
5331 /*     symbol *tlbl; */
5332
5333     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5334     /* note here that && operations that are in an
5335     if statement are taken away by backPatchLabels
5336     only those used in arthmetic operations remain */
5337     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5338     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5339     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5340
5341     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5342
5343     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5344     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5345     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5346
5347     /* if both are bit variables */
5348 /*     if (AOP_TYPE(left) == AOP_CRY && */
5349 /*         AOP_TYPE(right) == AOP_CRY ) { */
5350 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5351 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5352 /*         pic16_outBitC(result); */
5353 /*     } else { */
5354 /*         tlbl = newiTempLabel(NULL); */
5355 /*         pic16_toBoolean(left);     */
5356 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5357 /*         pic16_toBoolean(right); */
5358 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5359 /*         pic16_outBitAcc(result); */
5360 /*     } */
5361
5362     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5363     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5364     pic16_freeAsmop(result,NULL,ic,TRUE);
5365 }
5366
5367
5368 /*-----------------------------------------------------------------*/
5369 /* genOrOp - for || operation                                      */
5370 /*-----------------------------------------------------------------*/
5371 /*
5372   tsd pic port -
5373   modified this code, but it doesn't appear to ever get called
5374 */
5375
5376 static void genOrOp (iCode *ic)
5377 {
5378     operand *left,*right, *result;
5379     symbol *tlbl;
5380
5381     /* note here that || operations that are in an
5382     if statement are taken away by backPatchLabels
5383     only those used in arthmetic operations remain */
5384     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5385     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5386     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5387     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5388
5389     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5390
5391     /* if both are bit variables */
5392     if (AOP_TYPE(left) == AOP_CRY &&
5393         AOP_TYPE(right) == AOP_CRY ) {
5394       pic16_emitcode("clrc","");
5395       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5396                AOP(left)->aopu.aop_dir,
5397                AOP(left)->aopu.aop_dir);
5398       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5399                AOP(right)->aopu.aop_dir,
5400                AOP(right)->aopu.aop_dir);
5401       pic16_emitcode("setc","");
5402
5403     } else {
5404         tlbl = newiTempLabel(NULL);
5405         pic16_toBoolean(left);
5406         emitSKPZ;
5407         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5408         pic16_toBoolean(right);
5409         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5410
5411         pic16_outBitAcc(result);
5412     }
5413
5414     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5415     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5416     pic16_freeAsmop(result,NULL,ic,TRUE);            
5417 }
5418
5419 /*-----------------------------------------------------------------*/
5420 /* isLiteralBit - test if lit == 2^n                               */
5421 /*-----------------------------------------------------------------*/
5422 static int isLiteralBit(unsigned long lit)
5423 {
5424     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5425     0x100L,0x200L,0x400L,0x800L,
5426     0x1000L,0x2000L,0x4000L,0x8000L,
5427     0x10000L,0x20000L,0x40000L,0x80000L,
5428     0x100000L,0x200000L,0x400000L,0x800000L,
5429     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5430     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5431     int idx;
5432     
5433     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5434     for(idx = 0; idx < 32; idx++)
5435         if(lit == pw[idx])
5436             return idx+1;
5437     return 0;
5438 }
5439
5440 /*-----------------------------------------------------------------*/
5441 /* continueIfTrue -                                                */
5442 /*-----------------------------------------------------------------*/
5443 static void continueIfTrue (iCode *ic)
5444 {
5445     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5446     if(IC_TRUE(ic))
5447         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5448     ic->generated = 1;
5449 }
5450
5451 /*-----------------------------------------------------------------*/
5452 /* jmpIfTrue -                                                     */
5453 /*-----------------------------------------------------------------*/
5454 static void jumpIfTrue (iCode *ic)
5455 {
5456     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5457     if(!IC_TRUE(ic))
5458         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5459     ic->generated = 1;
5460 }
5461
5462 /*-----------------------------------------------------------------*/
5463 /* jmpTrueOrFalse -                                                */
5464 /*-----------------------------------------------------------------*/
5465 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5466 {
5467     // ugly but optimized by peephole
5468     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5469     if(IC_TRUE(ic)){
5470         symbol *nlbl = newiTempLabel(NULL);
5471         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5472         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5473         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5474         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5475     }
5476     else{
5477         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5478         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5479     }
5480     ic->generated = 1;
5481 }
5482
5483 /*-----------------------------------------------------------------*/
5484 /* genAnd  - code for and                                          */
5485 /*-----------------------------------------------------------------*/
5486 static void genAnd (iCode *ic, iCode *ifx)
5487 {
5488   operand *left, *right, *result;
5489   int size, offset=0;  
5490   unsigned long lit = 0L;
5491   int bytelit = 0;
5492   resolvedIfx rIfx;
5493
5494
5495   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5496   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5497   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5498   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5499
5500   resolveIfx(&rIfx,ifx);
5501
5502   /* if left is a literal & right is not then exchange them */
5503   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5504       AOP_NEEDSACC(left)) {
5505     operand *tmp = right ;
5506     right = left;
5507     left = tmp;
5508   }
5509
5510   /* if result = right then exchange them */
5511   if(pic16_sameRegs(AOP(result),AOP(right))){
5512     operand *tmp = right ;
5513     right = left;
5514     left = tmp;
5515   }
5516
5517   /* if right is bit then exchange them */
5518   if (AOP_TYPE(right) == AOP_CRY &&
5519       AOP_TYPE(left) != AOP_CRY){
5520     operand *tmp = right ;
5521     right = left;
5522     left = tmp;
5523   }
5524   if(AOP_TYPE(right) == AOP_LIT)
5525     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5526
5527   size = AOP_SIZE(result);
5528
5529   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5530
5531   // if(bit & yy)
5532   // result = bit & yy;
5533   if (AOP_TYPE(left) == AOP_CRY){
5534     // c = bit & literal;
5535     if(AOP_TYPE(right) == AOP_LIT){
5536       if(lit & 1) {
5537         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5538           // no change
5539           goto release;
5540         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5541       } else {
5542         // bit(result) = 0;
5543         if(size && (AOP_TYPE(result) == AOP_CRY)){
5544           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5545           goto release;
5546         }
5547         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5548           jumpIfTrue(ifx);
5549           goto release;
5550         }
5551         pic16_emitcode("clr","c");
5552       }
5553     } else {
5554       if (AOP_TYPE(right) == AOP_CRY){
5555         // c = bit & bit;
5556         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5557         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5558       } else {
5559         // c = bit & val;
5560         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5561         // c = lsb
5562         pic16_emitcode("rrc","a");
5563         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5564       }
5565     }
5566     // bit = c
5567     // val = c
5568     if(size)
5569       pic16_outBitC(result);
5570     // if(bit & ...)
5571     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5572       genIfxJump(ifx, "c");           
5573     goto release ;
5574   }
5575
5576   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5577   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5578   if((AOP_TYPE(right) == AOP_LIT) &&
5579      (AOP_TYPE(result) == AOP_CRY) &&
5580      (AOP_TYPE(left) != AOP_CRY)){
5581     int posbit = isLiteralBit(lit);
5582     /* left &  2^n */
5583     if(posbit){
5584       posbit--;
5585       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5586       // bit = left & 2^n
5587       if(size)
5588         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5589       // if(left &  2^n)
5590       else{
5591         if(ifx){
5592 /*
5593           if(IC_TRUE(ifx)) {
5594             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5595             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5596           } else {
5597             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5598             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5599           }
5600 */
5601           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5602                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5603           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5604           
5605           ifx->generated = 1;
5606         }
5607         goto release;
5608       }
5609     } else {
5610       symbol *tlbl = newiTempLabel(NULL);
5611       int sizel = AOP_SIZE(left);
5612       if(size)
5613         pic16_emitcode("setb","c");
5614       while(sizel--){
5615         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5616           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5617           // byte ==  2^n ?
5618           if((posbit = isLiteralBit(bytelit)) != 0)
5619             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5620           else{
5621             if(bytelit != 0x0FFL)
5622               pic16_emitcode("anl","a,%s",
5623                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
5624             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5625           }
5626         }
5627         offset++;
5628       }
5629       // bit = left & literal
5630       if(size){
5631         pic16_emitcode("clr","c");
5632         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5633       }
5634       // if(left & literal)
5635       else{
5636         if(ifx)
5637           jmpTrueOrFalse(ifx, tlbl);
5638         goto release ;
5639       }
5640     }
5641     pic16_outBitC(result);
5642     goto release ;
5643   }
5644
5645   /* if left is same as result */
5646   if(pic16_sameRegs(AOP(result),AOP(left))){
5647     int know_W = -1;
5648     for(;size--; offset++,lit>>=8) {
5649       if(AOP_TYPE(right) == AOP_LIT){
5650         switch(lit & 0xff) {
5651         case 0x00:
5652           /*  and'ing with 0 has clears the result */
5653 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5654           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5655           break;
5656         case 0xff:
5657           /* and'ing with 0xff is a nop when the result and left are the same */
5658           break;
5659
5660         default:
5661           {
5662             int p = my_powof2( (~lit) & 0xff );
5663             if(p>=0) {
5664               /* only one bit is set in the literal, so use a bcf instruction */
5665 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5666               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5667
5668             } else {
5669               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5670               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5671               if(know_W != (lit&0xff))
5672                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5673               know_W = lit &0xff;
5674               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5675             }
5676           }    
5677         }
5678       } else {
5679         if (AOP_TYPE(left) == AOP_ACC) {
5680           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5681         } else {                    
5682           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5683           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5684
5685         }
5686       }
5687     }
5688
5689   } else {
5690     // left & result in different registers
5691     if(AOP_TYPE(result) == AOP_CRY){
5692       // result = bit
5693       // if(size), result in bit
5694       // if(!size && ifx), conditional oper: if(left & right)
5695       symbol *tlbl = newiTempLabel(NULL);
5696       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5697       if(size)
5698         pic16_emitcode("setb","c");
5699       while(sizer--){
5700         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5701         pic16_emitcode("anl","a,%s",
5702                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5703         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5704         offset++;
5705       }
5706       if(size){
5707         CLRC;
5708         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5709         pic16_outBitC(result);
5710       } else if(ifx)
5711         jmpTrueOrFalse(ifx, tlbl);
5712     } else {
5713       for(;(size--);offset++) {
5714         // normal case
5715         // result = left & right
5716         if(AOP_TYPE(right) == AOP_LIT){
5717           int t = (lit >> (offset*8)) & 0x0FFL;
5718           switch(t) { 
5719           case 0x00:
5720             pic16_emitcode("clrf","%s",
5721                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5722             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5723             break;
5724           case 0xff:
5725             pic16_emitcode("movf","%s,w",
5726                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5727             pic16_emitcode("movwf","%s",
5728                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5729             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5730             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5731             break;
5732           default:
5733             pic16_emitcode("movlw","0x%x",t);
5734             pic16_emitcode("andwf","%s,w",
5735                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5736             pic16_emitcode("movwf","%s",
5737                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5738               
5739             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5740             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5741             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5742           }
5743           continue;
5744         }
5745
5746         if (AOP_TYPE(left) == AOP_ACC) {
5747           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5748           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5749         } else {
5750           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5751           pic16_emitcode("andwf","%s,w",
5752                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5753           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5754           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5755         }
5756         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5757         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5758       }
5759     }
5760   }
5761
5762   release :
5763     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5764   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5765   pic16_freeAsmop(result,NULL,ic,TRUE);     
5766 }
5767
5768 /*-----------------------------------------------------------------*/
5769 /* genOr  - code for or                                            */
5770 /*-----------------------------------------------------------------*/
5771 static void genOr (iCode *ic, iCode *ifx)
5772 {
5773     operand *left, *right, *result;
5774     int size, offset=0;
5775     unsigned long lit = 0L;
5776
5777     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5778
5779     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5780     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5781     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5782
5783     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5784
5785     /* if left is a literal & right is not then exchange them */
5786     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5787         AOP_NEEDSACC(left)) {
5788         operand *tmp = right ;
5789         right = left;
5790         left = tmp;
5791     }
5792
5793     /* if result = right then exchange them */
5794     if(pic16_sameRegs(AOP(result),AOP(right))){
5795         operand *tmp = right ;
5796         right = left;
5797         left = tmp;
5798     }
5799
5800     /* if right is bit then exchange them */
5801     if (AOP_TYPE(right) == AOP_CRY &&
5802         AOP_TYPE(left) != AOP_CRY){
5803         operand *tmp = right ;
5804         right = left;
5805         left = tmp;
5806     }
5807
5808     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5809
5810     if(AOP_TYPE(right) == AOP_LIT)
5811         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5812
5813     size = AOP_SIZE(result);
5814
5815     // if(bit | yy)
5816     // xx = bit | yy;
5817     if (AOP_TYPE(left) == AOP_CRY){
5818         if(AOP_TYPE(right) == AOP_LIT){
5819             // c = bit & literal;
5820             if(lit){
5821                 // lit != 0 => result = 1
5822                 if(AOP_TYPE(result) == AOP_CRY){
5823                   if(size)
5824                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5825                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5826                   //     AOP(result)->aopu.aop_dir,
5827                   //     AOP(result)->aopu.aop_dir);
5828                     else if(ifx)
5829                         continueIfTrue(ifx);
5830                     goto release;
5831                 }
5832             } else {
5833                 // lit == 0 => result = left
5834                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5835                     goto release;
5836                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5837             }
5838         } else {
5839             if (AOP_TYPE(right) == AOP_CRY){
5840               if(pic16_sameRegs(AOP(result),AOP(left))){
5841                 // c = bit | bit;
5842                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5843                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5844                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5845
5846                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5847                          AOP(result)->aopu.aop_dir,
5848                          AOP(result)->aopu.aop_dir);
5849                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5850                          AOP(right)->aopu.aop_dir,
5851                          AOP(right)->aopu.aop_dir);
5852                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5853                          AOP(result)->aopu.aop_dir,
5854                          AOP(result)->aopu.aop_dir);
5855               } else {
5856                 if( AOP_TYPE(result) == AOP_ACC) {
5857                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5858                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5859                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5860                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5861
5862                 } else {
5863
5864                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5865                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5866                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5867                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5868
5869                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5870                                  AOP(result)->aopu.aop_dir,
5871                                  AOP(result)->aopu.aop_dir);
5872                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5873                                  AOP(right)->aopu.aop_dir,
5874                                  AOP(right)->aopu.aop_dir);
5875                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5876                                  AOP(left)->aopu.aop_dir,
5877                                  AOP(left)->aopu.aop_dir);
5878                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5879                                  AOP(result)->aopu.aop_dir,
5880                                  AOP(result)->aopu.aop_dir);
5881                 }
5882               }
5883             } else {
5884                 // c = bit | val;
5885                 symbol *tlbl = newiTempLabel(NULL);
5886                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5887
5888
5889                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5890                 if( AOP_TYPE(right) == AOP_ACC) {
5891                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5892                   emitSKPNZ;
5893                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5894                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5895                 }
5896
5897
5898
5899                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5900                     pic16_emitcode(";XXX setb","c");
5901                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5902                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5903                 pic16_toBoolean(right);
5904                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5905                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5906                     jmpTrueOrFalse(ifx, tlbl);
5907                     goto release;
5908                 } else {
5909                     CLRC;
5910                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5911                 }
5912             }
5913         }
5914         // bit = c
5915         // val = c
5916         if(size)
5917             pic16_outBitC(result);
5918         // if(bit | ...)
5919         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5920             genIfxJump(ifx, "c");           
5921         goto release ;
5922     }
5923
5924     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5925     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5926     if((AOP_TYPE(right) == AOP_LIT) &&
5927        (AOP_TYPE(result) == AOP_CRY) &&
5928        (AOP_TYPE(left) != AOP_CRY)){
5929         if(lit){
5930           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5931             // result = 1
5932             if(size)
5933                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5934             else 
5935                 continueIfTrue(ifx);
5936             goto release;
5937         } else {
5938           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5939             // lit = 0, result = boolean(left)
5940             if(size)
5941                 pic16_emitcode(";XXX setb","c");
5942             pic16_toBoolean(right);
5943             if(size){
5944                 symbol *tlbl = newiTempLabel(NULL);
5945                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5946                 CLRC;
5947                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5948             } else {
5949                 genIfxJump (ifx,"a");
5950                 goto release;
5951             }
5952         }
5953         pic16_outBitC(result);
5954         goto release ;
5955     }
5956
5957     /* if left is same as result */
5958     if(pic16_sameRegs(AOP(result),AOP(left))){
5959       int know_W = -1;
5960       for(;size--; offset++,lit>>=8) {
5961         if(AOP_TYPE(right) == AOP_LIT){
5962           if((lit & 0xff) == 0)
5963             /*  or'ing with 0 has no effect */
5964             continue;
5965           else {
5966             int p = my_powof2(lit & 0xff);
5967             if(p>=0) {
5968               /* only one bit is set in the literal, so use a bsf instruction */
5969               pic16_emitpcode(POC_BSF,
5970                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5971             } else {
5972               if(know_W != (lit & 0xff))
5973                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5974               know_W = lit & 0xff;
5975               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5976             }
5977                     
5978           }
5979         } else {
5980           if (AOP_TYPE(left) == AOP_ACC) {
5981             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
5982             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5983           } else {                  
5984             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5985             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
5986
5987             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5988             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5989
5990           }
5991         }
5992       }
5993     } else {
5994         // left & result in different registers
5995         if(AOP_TYPE(result) == AOP_CRY){
5996             // result = bit
5997             // if(size), result in bit
5998             // if(!size && ifx), conditional oper: if(left | right)
5999             symbol *tlbl = newiTempLabel(NULL);
6000             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6001             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6002
6003
6004             if(size)
6005                 pic16_emitcode(";XXX setb","c");
6006             while(sizer--){
6007                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6008                 pic16_emitcode(";XXX orl","a,%s",
6009                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6010                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6011                 offset++;
6012             }
6013             if(size){
6014                 CLRC;
6015                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6016                 pic16_outBitC(result);
6017             } else if(ifx)
6018                 jmpTrueOrFalse(ifx, tlbl);
6019         } else for(;(size--);offset++){
6020           // normal case
6021           // result = left & right
6022           if(AOP_TYPE(right) == AOP_LIT){
6023             int t = (lit >> (offset*8)) & 0x0FFL;
6024             switch(t) { 
6025             case 0x00:
6026               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6027               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6028
6029               pic16_emitcode("movf","%s,w",
6030                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6031               pic16_emitcode("movwf","%s",
6032                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6033               break;
6034             default:
6035               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6036               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6037               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6038
6039               pic16_emitcode("movlw","0x%x",t);
6040               pic16_emitcode("iorwf","%s,w",
6041                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6042               pic16_emitcode("movwf","%s",
6043                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6044               
6045             }
6046             continue;
6047           }
6048
6049           // faster than result <- left, anl result,right
6050           // and better if result is SFR
6051           if (AOP_TYPE(left) == AOP_ACC) {
6052             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6053             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6054           } else {
6055             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6056             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6057
6058             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6059             pic16_emitcode("iorwf","%s,w",
6060                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6061           }
6062           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6063           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6064         }
6065     }
6066
6067 release :
6068     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6069     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6070     pic16_freeAsmop(result,NULL,ic,TRUE);     
6071 }
6072
6073 /*-----------------------------------------------------------------*/
6074 /* genXor - code for xclusive or                                   */
6075 /*-----------------------------------------------------------------*/
6076 static void genXor (iCode *ic, iCode *ifx)
6077 {
6078   operand *left, *right, *result;
6079   int size, offset=0;
6080   unsigned long lit = 0L;
6081
6082   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6083
6084   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6085   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6086   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6087
6088   /* if left is a literal & right is not ||
6089      if left needs acc & right does not */
6090   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6091       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6092     operand *tmp = right ;
6093     right = left;
6094     left = tmp;
6095   }
6096
6097   /* if result = right then exchange them */
6098   if(pic16_sameRegs(AOP(result),AOP(right))){
6099     operand *tmp = right ;
6100     right = left;
6101     left = tmp;
6102   }
6103
6104   /* if right is bit then exchange them */
6105   if (AOP_TYPE(right) == AOP_CRY &&
6106       AOP_TYPE(left) != AOP_CRY){
6107     operand *tmp = right ;
6108     right = left;
6109     left = tmp;
6110   }
6111   if(AOP_TYPE(right) == AOP_LIT)
6112     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6113
6114   size = AOP_SIZE(result);
6115
6116   // if(bit ^ yy)
6117   // xx = bit ^ yy;
6118   if (AOP_TYPE(left) == AOP_CRY){
6119     if(AOP_TYPE(right) == AOP_LIT){
6120       // c = bit & literal;
6121       if(lit>>1){
6122         // lit>>1  != 0 => result = 1
6123         if(AOP_TYPE(result) == AOP_CRY){
6124           if(size)
6125             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6126             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6127           else if(ifx)
6128             continueIfTrue(ifx);
6129           goto release;
6130         }
6131         pic16_emitcode("setb","c");
6132       } else{
6133         // lit == (0 or 1)
6134         if(lit == 0){
6135           // lit == 0, result = left
6136           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6137             goto release;
6138           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6139         } else{
6140           // lit == 1, result = not(left)
6141           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6142             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6143             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6144             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6145             goto release;
6146           } else {
6147             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6148             pic16_emitcode("cpl","c");
6149           }
6150         }
6151       }
6152
6153     } else {
6154       // right != literal
6155       symbol *tlbl = newiTempLabel(NULL);
6156       if (AOP_TYPE(right) == AOP_CRY){
6157         // c = bit ^ bit;
6158         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6159       }
6160       else{
6161         int sizer = AOP_SIZE(right);
6162         // c = bit ^ val
6163         // if val>>1 != 0, result = 1
6164         pic16_emitcode("setb","c");
6165         while(sizer){
6166           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6167           if(sizer == 1)
6168             // test the msb of the lsb
6169             pic16_emitcode("anl","a,#0xfe");
6170           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6171           sizer--;
6172         }
6173         // val = (0,1)
6174         pic16_emitcode("rrc","a");
6175       }
6176       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6177       pic16_emitcode("cpl","c");
6178       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6179     }
6180     // bit = c
6181     // val = c
6182     if(size)
6183       pic16_outBitC(result);
6184     // if(bit | ...)
6185     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6186       genIfxJump(ifx, "c");           
6187     goto release ;
6188   }
6189
6190   if(pic16_sameRegs(AOP(result),AOP(left))){
6191     /* if left is same as result */
6192     for(;size--; offset++) {
6193       if(AOP_TYPE(right) == AOP_LIT){
6194         int t  = (lit >> (offset*8)) & 0x0FFL;
6195         if(t == 0x00L)
6196           continue;
6197         else
6198           if (IS_AOP_PREG(left)) {
6199             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6200             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6201             pic16_aopPut(AOP(result),"a",offset);
6202           } else {
6203             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6204             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6205             pic16_emitcode("xrl","%s,%s",
6206                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6207                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6208           }
6209       } else {
6210         if (AOP_TYPE(left) == AOP_ACC)
6211           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6212         else {
6213           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6214           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6215 /*
6216           if (IS_AOP_PREG(left)) {
6217             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6218             pic16_aopPut(AOP(result),"a",offset);
6219           } else
6220             pic16_emitcode("xrl","%s,a",
6221                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6222 */
6223         }
6224       }
6225     }
6226   } else {
6227     // left & result in different registers
6228     if(AOP_TYPE(result) == AOP_CRY){
6229       // result = bit
6230       // if(size), result in bit
6231       // if(!size && ifx), conditional oper: if(left ^ right)
6232       symbol *tlbl = newiTempLabel(NULL);
6233       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6234       if(size)
6235         pic16_emitcode("setb","c");
6236       while(sizer--){
6237         if((AOP_TYPE(right) == AOP_LIT) &&
6238            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6239           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6240         } else {
6241           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6242           pic16_emitcode("xrl","a,%s",
6243                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6244         }
6245         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6246         offset++;
6247       }
6248       if(size){
6249         CLRC;
6250         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6251         pic16_outBitC(result);
6252       } else if(ifx)
6253         jmpTrueOrFalse(ifx, tlbl);
6254     } else for(;(size--);offset++){
6255       // normal case
6256       // result = left & right
6257       if(AOP_TYPE(right) == AOP_LIT){
6258         int t = (lit >> (offset*8)) & 0x0FFL;
6259         switch(t) { 
6260         case 0x00:
6261           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6262           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6263           pic16_emitcode("movf","%s,w",
6264                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6265           pic16_emitcode("movwf","%s",
6266                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6267           break;
6268         case 0xff:
6269           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6270           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6271           pic16_emitcode("comf","%s,w",
6272                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6273           pic16_emitcode("movwf","%s",
6274                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6275           break;
6276         default:
6277           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6278           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6279           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6280           pic16_emitcode("movlw","0x%x",t);
6281           pic16_emitcode("xorwf","%s,w",
6282                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6283           pic16_emitcode("movwf","%s",
6284                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6285
6286         }
6287         continue;
6288       }
6289
6290       // faster than result <- left, anl result,right
6291       // and better if result is SFR
6292       if (AOP_TYPE(left) == AOP_ACC) {
6293         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6294         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6295       } else {
6296         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6297         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6298         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6299         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6300       }
6301       if ( AOP_TYPE(result) != AOP_ACC){
6302         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6303         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6304       }
6305     }
6306   }
6307
6308   release :
6309     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6310   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6311   pic16_freeAsmop(result,NULL,ic,TRUE);     
6312 }
6313
6314 /*-----------------------------------------------------------------*/
6315 /* genInline - write the inline code out                           */
6316 /*-----------------------------------------------------------------*/
6317 static void genInline (iCode *ic)
6318 {
6319     char *buffer, *bp, *bp1;
6320     
6321     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6322
6323     _G.inLine += (!options.asmpeep);
6324
6325     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6326     strcpy(buffer,IC_INLINE(ic));
6327
6328     /* emit each line as a code */
6329     while (*bp) {
6330         if (*bp == '\n') {
6331             *bp++ = '\0';
6332
6333             if(*bp1)
6334               pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL));       //pic16_AssembleLine(bp1, 0));
6335                                         // inline directly, no process
6336             bp1 = bp;
6337         } else {
6338             if (*bp == ':') {
6339                 bp++;
6340                 *bp = '\0';
6341                 bp++;
6342                 pic16_emitcode(bp1,"");
6343                 bp1 = bp;
6344             } else
6345                 bp++;
6346         }
6347     }
6348     if ((bp1 != bp) && *bp1)
6349       pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL));               //pic16_AssembleLine(bp1, 0));
6350
6351     Safe_free(buffer);
6352
6353     _G.inLine -= (!options.asmpeep);
6354 }
6355
6356 /*-----------------------------------------------------------------*/
6357 /* genRRC - rotate right with carry                                */
6358 /*-----------------------------------------------------------------*/
6359 static void genRRC (iCode *ic)
6360 {
6361   operand *left , *result ;
6362   int size, offset = 0, same;
6363
6364   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6365
6366   /* rotate right with carry */
6367   left = IC_LEFT(ic);
6368   result=IC_RESULT(ic);
6369   pic16_aopOp (left,ic,FALSE);
6370   pic16_aopOp (result,ic,FALSE);
6371
6372   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6373
6374   same = pic16_sameRegs(AOP(result),AOP(left));
6375
6376   size = AOP_SIZE(result);    
6377
6378   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6379
6380   /* get the lsb and put it into the carry */
6381   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6382
6383   offset = 0 ;
6384
6385   while(size--) {
6386
6387     if(same) {
6388       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6389     } else {
6390       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6391       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6392     }
6393
6394     offset++;
6395   }
6396
6397   pic16_freeAsmop(left,NULL,ic,TRUE);
6398   pic16_freeAsmop(result,NULL,ic,TRUE);
6399 }
6400
6401 /*-----------------------------------------------------------------*/
6402 /* genRLC - generate code for rotate left with carry               */
6403 /*-----------------------------------------------------------------*/
6404 static void genRLC (iCode *ic)
6405 {    
6406   operand *left , *result ;
6407   int size, offset = 0;
6408   int same;
6409
6410   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6411   /* rotate right with carry */
6412   left = IC_LEFT(ic);
6413   result=IC_RESULT(ic);
6414   pic16_aopOp (left,ic,FALSE);
6415   pic16_aopOp (result,ic,FALSE);
6416
6417   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6418
6419   same = pic16_sameRegs(AOP(result),AOP(left));
6420
6421   /* move it to the result */
6422   size = AOP_SIZE(result);    
6423
6424   /* get the msb and put it into the carry */
6425   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6426
6427   offset = 0 ;
6428
6429   while(size--) {
6430
6431     if(same) {
6432       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6433     } else {
6434       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6435       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6436     }
6437
6438     offset++;
6439   }
6440
6441
6442   pic16_freeAsmop(left,NULL,ic,TRUE);
6443   pic16_freeAsmop(result,NULL,ic,TRUE);
6444 }
6445
6446 /*-----------------------------------------------------------------*/
6447 /* genGetHbit - generates code get highest order bit               */
6448 /*-----------------------------------------------------------------*/
6449 static void genGetHbit (iCode *ic)
6450 {
6451     operand *left, *result;
6452     left = IC_LEFT(ic);
6453     result=IC_RESULT(ic);
6454     pic16_aopOp (left,ic,FALSE);
6455     pic16_aopOp (result,ic,FALSE);
6456
6457     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6458     /* get the highest order byte into a */
6459     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6460     if(AOP_TYPE(result) == AOP_CRY){
6461         pic16_emitcode("rlc","a");
6462         pic16_outBitC(result);
6463     }
6464     else{
6465         pic16_emitcode("rl","a");
6466         pic16_emitcode("anl","a,#0x01");
6467         pic16_outAcc(result);
6468     }
6469
6470
6471     pic16_freeAsmop(left,NULL,ic,TRUE);
6472     pic16_freeAsmop(result,NULL,ic,TRUE);
6473 }
6474
6475 #if 0
6476 /*-----------------------------------------------------------------*/
6477 /* AccRol - rotate left accumulator by known count                 */
6478 /*-----------------------------------------------------------------*/
6479 static void AccRol (int shCount)
6480 {
6481     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6482     shCount &= 0x0007;              // shCount : 0..7
6483     switch(shCount){
6484         case 0 :
6485             break;
6486         case 1 :
6487             pic16_emitcode("rl","a");
6488             break;
6489         case 2 :
6490             pic16_emitcode("rl","a");
6491             pic16_emitcode("rl","a");
6492             break;
6493         case 3 :
6494             pic16_emitcode("swap","a");
6495             pic16_emitcode("rr","a");
6496             break;
6497         case 4 :
6498             pic16_emitcode("swap","a");
6499             break;
6500         case 5 :
6501             pic16_emitcode("swap","a");
6502             pic16_emitcode("rl","a");
6503             break;
6504         case 6 :
6505             pic16_emitcode("rr","a");
6506             pic16_emitcode("rr","a");
6507             break;
6508         case 7 :
6509             pic16_emitcode("rr","a");
6510             break;
6511     }
6512 }
6513 #endif
6514
6515 /*-----------------------------------------------------------------*/
6516 /* AccLsh - left shift accumulator by known count                  */
6517 /*-----------------------------------------------------------------*/
6518 static void AccLsh (int shCount)
6519 {
6520     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6521     switch(shCount){
6522         case 0 :
6523                         return;
6524             break;
6525         case 1 :
6526             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6527             break;
6528         case 2 :
6529             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6530             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6531             break;
6532         case 3 :
6533             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6534             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6535             break;
6536         case 4 :
6537             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6538             break;
6539         case 5 :
6540             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6541             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6542             break;
6543         case 6 :
6544             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6545             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6546             break;
6547         case 7 :
6548             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6549             break;
6550     }
6551     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6552
6553 }
6554
6555 /*-----------------------------------------------------------------*/
6556 /* AccRsh - right shift accumulator by known count                 */
6557 /*-----------------------------------------------------------------*/
6558 static void AccRsh (int shCount)
6559 {
6560     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6561     switch(shCount){
6562         case 0 :
6563                         return;
6564             break;
6565         case 1 :
6566             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6567             break;
6568         case 2 :
6569             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6570             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6571             break;
6572         case 3 :
6573             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6574             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6575             break;
6576         case 4 :
6577             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6578             break;
6579         case 5 :
6580             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6581             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6582             break;
6583         case 6 :
6584             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6585             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6586             break;
6587         case 7 :
6588             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6589             break;
6590     }
6591     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6592 }
6593
6594 #if 0
6595 /*-----------------------------------------------------------------*/
6596 /* AccSRsh - signed right shift accumulator by known count                 */
6597 /*-----------------------------------------------------------------*/
6598 static void AccSRsh (int shCount)
6599 {
6600     symbol *tlbl ;
6601     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6602     if(shCount != 0){
6603         if(shCount == 1){
6604             pic16_emitcode("mov","c,acc.7");
6605             pic16_emitcode("rrc","a");
6606         } else if(shCount == 2){
6607             pic16_emitcode("mov","c,acc.7");
6608             pic16_emitcode("rrc","a");
6609             pic16_emitcode("mov","c,acc.7");
6610             pic16_emitcode("rrc","a");
6611         } else {
6612             tlbl = newiTempLabel(NULL);
6613             /* rotate right accumulator */
6614             AccRol(8 - shCount);
6615             /* and kill the higher order bits */
6616             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6617             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6618             pic16_emitcode("orl","a,#0x%02x",
6619                      (unsigned char)~SRMask[shCount]);
6620             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6621         }
6622     }
6623 }
6624 #endif
6625 /*-----------------------------------------------------------------*/
6626 /* shiftR1Left2Result - shift right one byte from left to result   */
6627 /*-----------------------------------------------------------------*/
6628 static void shiftR1Left2ResultSigned (operand *left, int offl,
6629                                 operand *result, int offr,
6630                                 int shCount)
6631 {
6632   int same;
6633
6634   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6635
6636   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6637
6638   switch(shCount) {
6639   case 1:
6640     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6641     if(same) 
6642       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6643     else {
6644       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6645       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6646     }
6647
6648     break;
6649   case 2:
6650
6651     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6652     if(same) 
6653       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6654     else {
6655       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6656       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6657     }
6658     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6659     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6660
6661     break;
6662
6663   case 3:
6664     if(same)
6665       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6666     else {
6667       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6668       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6669     }
6670
6671     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6672     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6673     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6674
6675     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6676     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
6677
6678     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6679     break;
6680
6681   case 4:
6682     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6683     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
6684     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6685     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
6686     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6687     break;
6688   case 5:
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     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
6696     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
6697     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6698     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
6699     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6700     break;
6701
6702   case 6:
6703     if(same) {
6704       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6705       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6706       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
6707       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6708       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
6709       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6710     } else {
6711       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6712       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6713       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6714       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6715       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6716     }
6717     break;
6718
6719   case 7:
6720     if(same) {
6721       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6722       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6723       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6724       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6725     } else {
6726       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6727       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6728       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6729     }
6730
6731   default:
6732     break;
6733   }
6734 }
6735
6736 /*-----------------------------------------------------------------*/
6737 /* shiftR1Left2Result - shift right one byte from left to result   */
6738 /*-----------------------------------------------------------------*/
6739 static void shiftR1Left2Result (operand *left, int offl,
6740                                 operand *result, int offr,
6741                                 int shCount, int sign)
6742 {
6743   int same;
6744
6745   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6746
6747   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6748
6749   /* Copy the msb into the carry if signed. */
6750   if(sign) {
6751     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6752     return;
6753   }
6754
6755
6756
6757   switch(shCount) {
6758   case 1:
6759     emitCLRC;
6760     if(same) 
6761       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6762     else {
6763       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6764       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6765     }
6766     break;
6767   case 2:
6768     emitCLRC;
6769     if(same) {
6770       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6771     } else {
6772       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6773       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6774     }
6775     emitCLRC;
6776     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6777
6778     break;
6779   case 3:
6780     if(same)
6781       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6782     else {
6783       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6784       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6785     }
6786
6787     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6788     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6789     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6790     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6791     break;
6792       
6793   case 4:
6794     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6795     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6796     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6797     break;
6798
6799   case 5:
6800     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6801     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6802     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6803     emitCLRC;
6804     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6805
6806     break;
6807   case 6:
6808
6809     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
6810     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6811     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6812     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6813     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6814     break;
6815
6816   case 7:
6817
6818     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6819     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6820     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6821
6822     break;
6823
6824   default:
6825     break;
6826   }
6827 }
6828
6829 /*-----------------------------------------------------------------*/
6830 /* shiftL1Left2Result - shift left one byte from left to result    */
6831 /*-----------------------------------------------------------------*/
6832 static void shiftL1Left2Result (operand *left, int offl,
6833                                 operand *result, int offr, int shCount)
6834 {
6835   int same;
6836
6837   //    char *l;
6838   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6839
6840   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6841   DEBUGpic16_emitcode ("; ***","same =  %d",same);
6842     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6843     //    MOVA(l);
6844     /* shift left accumulator */
6845     //AccLsh(shCount); // don't comment out just yet...
6846   //    pic16_aopPut(AOP(result),"a",offr);
6847
6848   switch(shCount) {
6849   case 1:
6850     /* Shift left 1 bit position */
6851     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6852     if(same) {
6853       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
6854     } else {
6855       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
6856       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6857     }
6858     break;
6859   case 2:
6860     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6861     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
6862     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6863     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6864     break;
6865   case 3:
6866     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6867     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
6868     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6869     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6870     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6871     break;
6872   case 4:
6873     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6874     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6875     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6876     break;
6877   case 5:
6878     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6879     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6880     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6881     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6882     break;
6883   case 6:
6884     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6885     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
6886     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6887     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6888     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6889     break;
6890   case 7:
6891     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6892     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6893     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6894     break;
6895
6896   default:
6897     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6898   }
6899
6900 }
6901
6902 /*-----------------------------------------------------------------*/
6903 /* movLeft2Result - move byte from left to result                  */
6904 /*-----------------------------------------------------------------*/
6905 static void movLeft2Result (operand *left, int offl,
6906                             operand *result, int offr)
6907 {
6908   char *l;
6909   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6910   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6911     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6912
6913     if (*l == '@' && (IS_AOP_PREG(result))) {
6914       pic16_emitcode("mov","a,%s",l);
6915       pic16_aopPut(AOP(result),"a",offr);
6916     } else {
6917       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6918       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6919     }
6920   }
6921 }
6922
6923 /*-----------------------------------------------------------------*/
6924 /* shiftL2Left2Result - shift left two bytes from left to result   */
6925 /*-----------------------------------------------------------------*/
6926 static void shiftL2Left2Result (operand *left, int offl,
6927                                 operand *result, int offr, int shCount)
6928 {
6929   int same = pic16_sameRegs(AOP(result), AOP(left));
6930   int i;
6931
6932   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6933
6934   if (same && (offl != offr)) { // shift bytes
6935     if (offr > offl) {
6936        for(i=1;i>-1;i--) {
6937          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6938          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6939        }
6940     } else { // just treat as different later on
6941                 same = 0;
6942     }
6943   }
6944
6945   if(same) {
6946     switch(shCount) {
6947     case 0:
6948       break;
6949     case 1:
6950     case 2:
6951     case 3:
6952
6953       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6954       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6955       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6956
6957       while(--shCount) {
6958                 emitCLRC;
6959                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6960                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6961       }
6962
6963       break;
6964     case 4:
6965     case 5:
6966       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6967       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6968       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6969       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6970       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6971       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6972       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6973       if(shCount >=5) {
6974                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6975                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6976       }
6977       break;
6978     case 6:
6979       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6980       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6981       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6982       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6983       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6984       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6985       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6986       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6987       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6988       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6989       break;
6990     case 7:
6991       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6992       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6993       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6994       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6995       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6996     }
6997
6998   } else {
6999     switch(shCount) {
7000     case 0:
7001       break;
7002     case 1:
7003     case 2:
7004     case 3:
7005       /* note, use a mov/add for the shift since the mov has a
7006          chance of getting optimized out */
7007       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7008       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7009       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7010       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7011       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7012
7013       while(--shCount) {
7014                 emitCLRC;
7015                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7016                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7017       }
7018       break;
7019
7020     case 4:
7021     case 5:
7022       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7023       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7024       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7025       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7026       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7027       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7028       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7029       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7030
7031
7032       if(shCount == 5) {
7033                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7034                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7035       }
7036       break;
7037     case 6:
7038       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7039       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7040       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7041       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7042
7043       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7044       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7045       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7046       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7047       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7048       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7049       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7050       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7051       break;
7052     case 7:
7053       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7054       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7055       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7056       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7057       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7058     }
7059   }
7060
7061 }
7062 /*-----------------------------------------------------------------*/
7063 /* shiftR2Left2Result - shift right two bytes from left to result  */
7064 /*-----------------------------------------------------------------*/
7065 static void shiftR2Left2Result (operand *left, int offl,
7066                                 operand *result, int offr,
7067                                 int shCount, int sign)
7068 {
7069   int same = pic16_sameRegs(AOP(result), AOP(left));
7070   int i;
7071   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7072
7073   if (same && (offl != offr)) { // shift right bytes
7074     if (offr < offl) {
7075        for(i=0;i<2;i++) {
7076          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7077          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7078        }
7079     } else { // just treat as different later on
7080                 same = 0;
7081     }
7082   }
7083
7084   switch(shCount) {
7085   case 0:
7086     break;
7087   case 1:
7088   case 2:
7089   case 3:
7090     if(sign)
7091       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7092     else
7093       emitCLRC;
7094
7095     if(same) {
7096       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7097       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7098     } else {
7099       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7100       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7101       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7102       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7103     }
7104
7105     while(--shCount) {
7106       if(sign)
7107                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7108       else
7109                 emitCLRC;
7110       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7111       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7112     }
7113     break;
7114   case 4:
7115   case 5:
7116     if(same) {
7117
7118       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7119       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7120       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7121
7122       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7123       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7124       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7125       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7126     } else {
7127       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7128       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7129       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7130
7131       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7132       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7133       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7134       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7135       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7136     }
7137
7138     if(shCount >=5) {
7139       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7140       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7141     }
7142
7143     if(sign) {
7144       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7145       pic16_emitpcode(POC_BTFSC, 
7146                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7147       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7148     }
7149
7150     break;
7151
7152   case 6:
7153     if(same) {
7154
7155       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7156       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7157
7158       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7159       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7160       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7161       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7162       if(sign) {
7163         pic16_emitpcode(POC_BTFSC, 
7164                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7165         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7166       }
7167       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7168       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7169       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7170       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7171     } else {
7172       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7173       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7174       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7175       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7176       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7177       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7178       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7179       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7180       if(sign) {
7181         pic16_emitpcode(POC_BTFSC, 
7182                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7183         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7184       }
7185       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7186       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7187
7188         
7189     }
7190
7191     break;
7192   case 7:
7193     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7194     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7195     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7196     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7197     if(sign) {
7198       emitSKPNC;
7199       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7200     } else 
7201       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7202   }
7203 }
7204
7205
7206 /*-----------------------------------------------------------------*/
7207 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7208 /*-----------------------------------------------------------------*/
7209 static void shiftLLeftOrResult (operand *left, int offl,
7210                                 operand *result, int offr, int shCount)
7211 {
7212     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7213
7214     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7215     /* shift left accumulator */
7216     AccLsh(shCount);
7217     /* or with result */
7218     /* back to result */
7219     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7220 }
7221
7222 /*-----------------------------------------------------------------*/
7223 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7224 /*-----------------------------------------------------------------*/
7225 static void shiftRLeftOrResult (operand *left, int offl,
7226                                 operand *result, int offr, int shCount)
7227 {
7228     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7229     
7230     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7231     /* shift right accumulator */
7232     AccRsh(shCount);
7233     /* or with result */
7234     /* back to result */
7235     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7236 }
7237
7238 /*-----------------------------------------------------------------*/
7239 /* genlshOne - left shift a one byte quantity by known count       */
7240 /*-----------------------------------------------------------------*/
7241 static void genlshOne (operand *result, operand *left, int shCount)
7242 {       
7243     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7244     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7245 }
7246
7247 /*-----------------------------------------------------------------*/
7248 /* genlshTwo - left shift two bytes by known amount != 0           */
7249 /*-----------------------------------------------------------------*/
7250 static void genlshTwo (operand *result,operand *left, int shCount)
7251 {
7252     int size;
7253     
7254     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7255     size = pic16_getDataSize(result);
7256
7257     /* if shCount >= 8 */
7258     if (shCount >= 8) {
7259         shCount -= 8 ;
7260
7261         if (size > 1){
7262             if (shCount)
7263                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7264             else 
7265                 movLeft2Result(left, LSB, result, MSB16);
7266         }
7267         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7268     }
7269
7270     /*  1 <= shCount <= 7 */
7271     else {  
7272         if(size == 1)
7273             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7274         else 
7275             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7276     }
7277 }
7278
7279 /*-----------------------------------------------------------------*/
7280 /* shiftLLong - shift left one long from left to result            */
7281 /* offr = LSB or MSB16                                             */
7282 /*-----------------------------------------------------------------*/
7283 static void shiftLLong (operand *left, operand *result, int offr )
7284 {
7285     int size = AOP_SIZE(result);
7286     int same = pic16_sameRegs(AOP(left),AOP(result));
7287         int i;
7288
7289     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7290
7291         if (same && (offr == MSB16)) { //shift one byte
7292                 for(i=size-1;i>=MSB16;i--) {
7293                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7294                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7295                 }
7296         } else {
7297                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7298         }
7299         
7300     if (size >= LSB+offr ){
7301                 if (same) {
7302                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7303                 } else {
7304                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7305                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7306                 }
7307          }
7308
7309     if(size >= MSB16+offr){
7310                 if (same) {
7311                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7312                 } else {
7313                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7314                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7315                 }
7316     }
7317
7318     if(size >= MSB24+offr){
7319                 if (same) {
7320                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7321                 } else {
7322                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7323                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7324                 }
7325     }
7326
7327     if(size > MSB32+offr){
7328                 if (same) {
7329                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7330                 } else {
7331                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7332                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7333                 }
7334     }
7335     if(offr != LSB)
7336                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7337
7338 }
7339
7340 /*-----------------------------------------------------------------*/
7341 /* genlshFour - shift four byte by a known amount != 0             */
7342 /*-----------------------------------------------------------------*/
7343 static void genlshFour (operand *result, operand *left, int shCount)
7344 {
7345     int size;
7346
7347     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7348     size = AOP_SIZE(result);
7349
7350     /* if shifting more that 3 bytes */
7351     if (shCount >= 24 ) {
7352         shCount -= 24;
7353         if (shCount)
7354             /* lowest order of left goes to the highest
7355             order of the destination */
7356             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7357         else
7358             movLeft2Result(left, LSB, result, MSB32);
7359
7360                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7361                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7362                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7363
7364         return;
7365     }
7366
7367     /* more than two bytes */
7368     else if ( shCount >= 16 ) {
7369         /* lower order two bytes goes to higher order two bytes */
7370         shCount -= 16;
7371         /* if some more remaining */
7372         if (shCount)
7373             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7374         else {
7375             movLeft2Result(left, MSB16, result, MSB32);
7376             movLeft2Result(left, LSB, result, MSB24);
7377         }
7378                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7379                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7380         return;
7381     }    
7382
7383     /* if more than 1 byte */
7384     else if ( shCount >= 8 ) {
7385         /* lower order three bytes goes to higher order  three bytes */
7386         shCount -= 8;
7387         if(size == 2){
7388             if(shCount)
7389                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7390             else
7391                 movLeft2Result(left, LSB, result, MSB16);
7392         }
7393         else{   /* size = 4 */
7394             if(shCount == 0){
7395                 movLeft2Result(left, MSB24, result, MSB32);
7396                 movLeft2Result(left, MSB16, result, MSB24);
7397                 movLeft2Result(left, LSB, result, MSB16);
7398                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7399             }
7400             else if(shCount == 1)
7401                 shiftLLong(left, result, MSB16);
7402             else{
7403                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7404                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7405                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7406                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7407             }
7408         }
7409     }
7410
7411     /* 1 <= shCount <= 7 */
7412     else if(shCount <= 3)
7413     { 
7414         shiftLLong(left, result, LSB);
7415         while(--shCount >= 1)
7416             shiftLLong(result, result, LSB);
7417     }
7418     /* 3 <= shCount <= 7, optimize */
7419     else{
7420         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7421         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7422         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7423     }
7424 }
7425
7426 /*-----------------------------------------------------------------*/
7427 /* genLeftShiftLiteral - left shifting by known count              */
7428 /*-----------------------------------------------------------------*/
7429 static void genLeftShiftLiteral (operand *left,
7430                                  operand *right,
7431                                  operand *result,
7432                                  iCode *ic)
7433 {    
7434     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7435     int size;
7436
7437     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7438     pic16_freeAsmop(right,NULL,ic,TRUE);
7439
7440     pic16_aopOp(left,ic,FALSE);
7441     pic16_aopOp(result,ic,FALSE);
7442
7443     size = getSize(operandType(result));
7444
7445 #if VIEW_SIZE
7446     pic16_emitcode("; shift left ","result %d, left %d",size,
7447              AOP_SIZE(left));
7448 #endif
7449
7450     /* I suppose that the left size >= result size */
7451     if(shCount == 0){
7452         while(size--){
7453             movLeft2Result(left, size, result, size);
7454         }
7455     }
7456
7457     else if(shCount >= (size * 8))
7458         while(size--)
7459             pic16_aopPut(AOP(result),zero,size);
7460     else{
7461         switch (size) {
7462             case 1:
7463                 genlshOne (result,left,shCount);
7464                 break;
7465
7466             case 2:
7467             case 3:
7468                 genlshTwo (result,left,shCount);
7469                 break;
7470
7471             case 4:
7472                 genlshFour (result,left,shCount);
7473                 break;
7474         }
7475     }
7476     pic16_freeAsmop(left,NULL,ic,TRUE);
7477     pic16_freeAsmop(result,NULL,ic,TRUE);
7478 }
7479
7480 /*-----------------------------------------------------------------*
7481  * genMultiAsm - repeat assembly instruction for size of register.
7482  * if endian == 1, then the high byte (i.e base address + size of 
7483  * register) is used first else the low byte is used first;
7484  *-----------------------------------------------------------------*/
7485 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7486 {
7487
7488   int offset = 0;
7489
7490   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7491
7492   if(!reg)
7493     return;
7494
7495   if(!endian) {
7496     endian = 1;
7497   } else {
7498     endian = -1;
7499     offset = size-1;
7500   }
7501
7502   while(size--) {
7503     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7504     offset += endian;
7505   }
7506
7507 }
7508 /*-----------------------------------------------------------------*/
7509 /* genLeftShift - generates code for left shifting                 */
7510 /*-----------------------------------------------------------------*/
7511 static void genLeftShift (iCode *ic)
7512 {
7513   operand *left,*right, *result;
7514   int size, offset;
7515   char *l;
7516   symbol *tlbl , *tlbl1;
7517   pCodeOp *pctemp;
7518
7519   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7520
7521   right = IC_RIGHT(ic);
7522   left  = IC_LEFT(ic);
7523   result = IC_RESULT(ic);
7524
7525   pic16_aopOp(right,ic,FALSE);
7526
7527   /* if the shift count is known then do it 
7528      as efficiently as possible */
7529   if (AOP_TYPE(right) == AOP_LIT) {
7530     genLeftShiftLiteral (left,right,result,ic);
7531     return ;
7532   }
7533
7534   /* shift count is unknown then we have to form 
7535      a loop get the loop count in B : Note: we take
7536      only the lower order byte since shifting
7537      more that 32 bits make no sense anyway, ( the
7538      largest size of an object can be only 32 bits ) */  
7539
7540     
7541   pic16_aopOp(left,ic,FALSE);
7542   pic16_aopOp(result,ic,FALSE);
7543
7544   /* now move the left to the result if they are not the
7545      same */
7546   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7547       AOP_SIZE(result) > 1) {
7548
7549     size = AOP_SIZE(result);
7550     offset=0;
7551     while (size--) {
7552       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7553       if (*l == '@' && (IS_AOP_PREG(result))) {
7554
7555         pic16_emitcode("mov","a,%s",l);
7556         pic16_aopPut(AOP(result),"a",offset);
7557       } else {
7558         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7559         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7560         //pic16_aopPut(AOP(result),l,offset);
7561       }
7562       offset++;
7563     }
7564   }
7565
7566   size = AOP_SIZE(result);
7567
7568   /* if it is only one byte then */
7569   if (size == 1) {
7570     if(optimized_for_speed) {
7571       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7572       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7573       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7574       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7575       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7576       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7577       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7578       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7579       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7580       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7581       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7582       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7583     } else {
7584
7585       tlbl = newiTempLabel(NULL);
7586       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7587                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7588                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7589       }
7590
7591       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7592       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7593       pic16_emitpLabel(tlbl->key);
7594       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7595       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7596       emitSKPC;
7597       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7598     }
7599     goto release ;
7600   }
7601     
7602   if (pic16_sameRegs(AOP(left),AOP(result))) {
7603
7604     tlbl = newiTempLabel(NULL);
7605     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7606     genMultiAsm(POC_RRCF, result, size,1);
7607     pic16_emitpLabel(tlbl->key);
7608     genMultiAsm(POC_RLCF, result, size,0);
7609     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7610     emitSKPC;
7611     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7612     goto release;
7613   }
7614
7615   //tlbl = newiTempLabel(NULL);
7616   //offset = 0 ;   
7617   //tlbl1 = newiTempLabel(NULL);
7618
7619   //reAdjustPreg(AOP(result));    
7620     
7621   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7622   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7623   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7624   //MOVA(l);
7625   //pic16_emitcode("add","a,acc");         
7626   //pic16_aopPut(AOP(result),"a",offset++);
7627   //while (--size) {
7628   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7629   //  MOVA(l);
7630   //  pic16_emitcode("rlc","a");         
7631   //  pic16_aopPut(AOP(result),"a",offset++);
7632   //}
7633   //reAdjustPreg(AOP(result));
7634
7635   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7636   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7637
7638
7639   tlbl = newiTempLabel(NULL);
7640   tlbl1= newiTempLabel(NULL);
7641
7642   size = AOP_SIZE(result);
7643   offset = 1;
7644
7645   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7646
7647   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7648
7649   /* offset should be 0, 1 or 3 */
7650   
7651   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
7652   emitSKPNZ;
7653   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7654
7655   pic16_emitpcode(POC_MOVWF, pctemp);
7656
7657
7658   pic16_emitpLabel(tlbl->key);
7659
7660   emitCLRC;
7661   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
7662   while(--size)
7663     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
7664
7665   pic16_emitpcode(POC_DECFSZ,  pctemp);
7666   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7667   pic16_emitpLabel(tlbl1->key);
7668
7669   pic16_popReleaseTempReg(pctemp);
7670
7671
7672  release:
7673   pic16_freeAsmop (right,NULL,ic,TRUE);
7674   pic16_freeAsmop(left,NULL,ic,TRUE);
7675   pic16_freeAsmop(result,NULL,ic,TRUE);
7676 }
7677
7678 /*-----------------------------------------------------------------*/
7679 /* genrshOne - right shift a one byte quantity by known count      */
7680 /*-----------------------------------------------------------------*/
7681 static void genrshOne (operand *result, operand *left,
7682                        int shCount, int sign)
7683 {
7684     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7685     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7686 }
7687
7688 /*-----------------------------------------------------------------*/
7689 /* genrshTwo - right shift two bytes by known amount != 0          */
7690 /*-----------------------------------------------------------------*/
7691 static void genrshTwo (operand *result,operand *left,
7692                        int shCount, int sign)
7693 {
7694   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7695   /* if shCount >= 8 */
7696   if (shCount >= 8) {
7697     shCount -= 8 ;
7698     if (shCount)
7699       shiftR1Left2Result(left, MSB16, result, LSB,
7700                          shCount, sign);
7701     else
7702       movLeft2Result(left, MSB16, result, LSB);
7703
7704     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7705
7706     if(sign) {
7707       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7708       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
7709     }
7710   }
7711
7712   /*  1 <= shCount <= 7 */
7713   else
7714     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7715 }
7716
7717 /*-----------------------------------------------------------------*/
7718 /* shiftRLong - shift right one long from left to result           */
7719 /* offl = LSB or MSB16                                             */
7720 /*-----------------------------------------------------------------*/
7721 static void shiftRLong (operand *left, int offl,
7722                         operand *result, int sign)
7723 {
7724     int size = AOP_SIZE(result);
7725     int same = pic16_sameRegs(AOP(left),AOP(result));
7726     int i;
7727     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7728
7729     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7730
7731         if (same && (offl == MSB16)) { //shift one byte right
7732                 for(i=MSB16;i<size;i++) {
7733                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7734                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7735                 }
7736         }
7737
7738     if(sign)
7739                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7740         else
7741                 emitCLRC;
7742
7743         if (same) {
7744                 if (offl == LSB)
7745                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7746         } else {
7747         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7748         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7749         }
7750
7751     if(offl == MSB16) {
7752         /* add sign of "a" */
7753         pic16_addSign(result, MSB32, sign);
7754         }
7755
7756         if (same) {
7757         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7758         } else {
7759         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7760         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7761         }
7762         
7763         if (same) {
7764         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7765         } else {
7766         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7767         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7768         }
7769
7770         if (same) {
7771         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7772         } else {
7773         if(offl == LSB){
7774                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7775                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7776         }
7777         }
7778 }
7779
7780 /*-----------------------------------------------------------------*/
7781 /* genrshFour - shift four byte by a known amount != 0             */
7782 /*-----------------------------------------------------------------*/
7783 static void genrshFour (operand *result, operand *left,
7784                         int shCount, int sign)
7785 {
7786   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7787   /* if shifting more that 3 bytes */
7788   if(shCount >= 24 ) {
7789     shCount -= 24;
7790     if(shCount)
7791       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7792     else
7793       movLeft2Result(left, MSB32, result, LSB);
7794
7795     pic16_addSign(result, MSB16, sign);
7796   }
7797   else if(shCount >= 16){
7798     shCount -= 16;
7799     if(shCount)
7800       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7801     else{
7802       movLeft2Result(left, MSB24, result, LSB);
7803       movLeft2Result(left, MSB32, result, MSB16);
7804     }
7805     pic16_addSign(result, MSB24, sign);
7806   }
7807   else if(shCount >= 8){
7808     shCount -= 8;
7809     if(shCount == 1)
7810       shiftRLong(left, MSB16, result, sign);
7811     else if(shCount == 0){
7812       movLeft2Result(left, MSB16, result, LSB);
7813       movLeft2Result(left, MSB24, result, MSB16);
7814       movLeft2Result(left, MSB32, result, MSB24);
7815       pic16_addSign(result, MSB32, sign);
7816     }
7817     else{ //shcount >= 2
7818       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7819       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7820       /* the last shift is signed */
7821       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7822       pic16_addSign(result, MSB32, sign);
7823     }
7824   }
7825   else{   /* 1 <= shCount <= 7 */
7826     if(shCount <= 2){
7827       shiftRLong(left, LSB, result, sign);
7828       if(shCount == 2)
7829         shiftRLong(result, LSB, result, sign);
7830     }
7831     else{
7832       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7833       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7834       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7835     }
7836   }
7837 }
7838
7839 /*-----------------------------------------------------------------*/
7840 /* genRightShiftLiteral - right shifting by known count            */
7841 /*-----------------------------------------------------------------*/
7842 static void genRightShiftLiteral (operand *left,
7843                                   operand *right,
7844                                   operand *result,
7845                                   iCode *ic,
7846                                   int sign)
7847 {    
7848   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7849   int lsize,res_size;
7850
7851   pic16_freeAsmop(right,NULL,ic,TRUE);
7852
7853   pic16_aopOp(left,ic,FALSE);
7854   pic16_aopOp(result,ic,FALSE);
7855
7856   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7857
7858 #if VIEW_SIZE
7859   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7860                  AOP_SIZE(left));
7861 #endif
7862
7863   lsize = pic16_getDataSize(left);
7864   res_size = pic16_getDataSize(result);
7865   /* test the LEFT size !!! */
7866
7867   /* I suppose that the left size >= result size */
7868   if(shCount == 0){
7869     while(res_size--)
7870       movLeft2Result(left, lsize, result, res_size);
7871   }
7872
7873   else if(shCount >= (lsize * 8)){
7874
7875     if(res_size == 1) {
7876       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
7877       if(sign) {
7878         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7879         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
7880       }
7881     } else {
7882
7883       if(sign) {
7884         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7885         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7886         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7887         while(res_size--)
7888           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
7889
7890       } else {
7891
7892         while(res_size--)
7893           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
7894       }
7895     }
7896   } else {
7897
7898     switch (res_size) {
7899     case 1:
7900       genrshOne (result,left,shCount,sign);
7901       break;
7902
7903     case 2:
7904       genrshTwo (result,left,shCount,sign);
7905       break;
7906
7907     case 4:
7908       genrshFour (result,left,shCount,sign);
7909       break;
7910     default :
7911       break;
7912     }
7913
7914   }
7915
7916   pic16_freeAsmop(left,NULL,ic,TRUE);
7917   pic16_freeAsmop(result,NULL,ic,TRUE);
7918 }
7919
7920 /*-----------------------------------------------------------------*/
7921 /* genSignedRightShift - right shift of signed number              */
7922 /*-----------------------------------------------------------------*/
7923 static void genSignedRightShift (iCode *ic)
7924 {
7925   operand *right, *left, *result;
7926   int size, offset;
7927   //  char *l;
7928   symbol *tlbl, *tlbl1 ;
7929   pCodeOp *pctemp;
7930
7931   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7932
7933   /* we do it the hard way put the shift count in b
7934      and loop thru preserving the sign */
7935   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7936
7937   right = IC_RIGHT(ic);
7938   left  = IC_LEFT(ic);
7939   result = IC_RESULT(ic);
7940
7941   pic16_aopOp(right,ic,FALSE);  
7942   pic16_aopOp(left,ic,FALSE);
7943   pic16_aopOp(result,ic,FALSE);
7944
7945
7946   if ( AOP_TYPE(right) == AOP_LIT) {
7947     genRightShiftLiteral (left,right,result,ic,1);
7948     return ;
7949   }
7950   /* shift count is unknown then we have to form 
7951      a loop get the loop count in B : Note: we take
7952      only the lower order byte since shifting
7953      more that 32 bits make no sense anyway, ( the
7954      largest size of an object can be only 32 bits ) */  
7955
7956   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7957   //pic16_emitcode("inc","b");
7958   //pic16_freeAsmop (right,NULL,ic,TRUE);
7959   //pic16_aopOp(left,ic,FALSE);
7960   //pic16_aopOp(result,ic,FALSE);
7961
7962   /* now move the left to the result if they are not the
7963      same */
7964   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7965       AOP_SIZE(result) > 1) {
7966
7967     size = AOP_SIZE(result);
7968     offset=0;
7969     while (size--) { 
7970       /*
7971         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7972         if (*l == '@' && IS_AOP_PREG(result)) {
7973
7974         pic16_emitcode("mov","a,%s",l);
7975         pic16_aopPut(AOP(result),"a",offset);
7976         } else
7977         pic16_aopPut(AOP(result),l,offset);
7978       */
7979       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7980       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7981
7982       offset++;
7983     }
7984   }
7985
7986   /* mov the highest order bit to OVR */    
7987   tlbl = newiTempLabel(NULL);
7988   tlbl1= newiTempLabel(NULL);
7989
7990   size = AOP_SIZE(result);
7991   offset = size - 1;
7992
7993   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7994
7995   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7996
7997   /* offset should be 0, 1 or 3 */
7998   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7999   emitSKPNZ;
8000   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8001
8002   pic16_emitpcode(POC_MOVWF, pctemp);
8003
8004
8005   pic16_emitpLabel(tlbl->key);
8006
8007   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8008   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8009
8010   while(--size) {
8011     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8012   }
8013
8014   pic16_emitpcode(POC_DECFSZ,  pctemp);
8015   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8016   pic16_emitpLabel(tlbl1->key);
8017
8018   pic16_popReleaseTempReg(pctemp);
8019 #if 0
8020   size = AOP_SIZE(result);
8021   offset = size - 1;
8022   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8023   pic16_emitcode("rlc","a");
8024   pic16_emitcode("mov","ov,c");
8025   /* if it is only one byte then */
8026   if (size == 1) {
8027     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8028     MOVA(l);
8029     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8030     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8031     pic16_emitcode("mov","c,ov");
8032     pic16_emitcode("rrc","a");
8033     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8034     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8035     pic16_aopPut(AOP(result),"a",0);
8036     goto release ;
8037   }
8038
8039   reAdjustPreg(AOP(result));
8040   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8041   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8042   pic16_emitcode("mov","c,ov");
8043   while (size--) {
8044     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8045     MOVA(l);
8046     pic16_emitcode("rrc","a");         
8047     pic16_aopPut(AOP(result),"a",offset--);
8048   }
8049   reAdjustPreg(AOP(result));
8050   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8051   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8052
8053  release:
8054 #endif
8055
8056   pic16_freeAsmop(left,NULL,ic,TRUE);
8057   pic16_freeAsmop(result,NULL,ic,TRUE);
8058   pic16_freeAsmop(right,NULL,ic,TRUE);
8059 }
8060
8061 /*-----------------------------------------------------------------*/
8062 /* genRightShift - generate code for right shifting                */
8063 /*-----------------------------------------------------------------*/
8064 static void genRightShift (iCode *ic)
8065 {
8066     operand *right, *left, *result;
8067     sym_link *letype ;
8068     int size, offset;
8069     char *l;
8070     symbol *tlbl, *tlbl1 ;
8071
8072     /* if signed then we do it the hard way preserve the
8073     sign bit moving it inwards */
8074     letype = getSpec(operandType(IC_LEFT(ic)));
8075     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8076
8077     if (!SPEC_USIGN(letype)) {
8078         genSignedRightShift (ic);
8079         return ;
8080     }
8081
8082     /* signed & unsigned types are treated the same : i.e. the
8083     signed is NOT propagated inwards : quoting from the
8084     ANSI - standard : "for E1 >> E2, is equivalent to division
8085     by 2**E2 if unsigned or if it has a non-negative value,
8086     otherwise the result is implementation defined ", MY definition
8087     is that the sign does not get propagated */
8088
8089     right = IC_RIGHT(ic);
8090     left  = IC_LEFT(ic);
8091     result = IC_RESULT(ic);
8092
8093     pic16_aopOp(right,ic,FALSE);
8094
8095     /* if the shift count is known then do it 
8096     as efficiently as possible */
8097     if (AOP_TYPE(right) == AOP_LIT) {
8098         genRightShiftLiteral (left,right,result,ic, 0);
8099         return ;
8100     }
8101
8102     /* shift count is unknown then we have to form 
8103     a loop get the loop count in B : Note: we take
8104     only the lower order byte since shifting
8105     more that 32 bits make no sense anyway, ( the
8106     largest size of an object can be only 32 bits ) */  
8107
8108     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8109     pic16_emitcode("inc","b");
8110     pic16_aopOp(left,ic,FALSE);
8111     pic16_aopOp(result,ic,FALSE);
8112
8113     /* now move the left to the result if they are not the
8114     same */
8115     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8116         AOP_SIZE(result) > 1) {
8117
8118         size = AOP_SIZE(result);
8119         offset=0;
8120         while (size--) {
8121             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8122             if (*l == '@' && IS_AOP_PREG(result)) {
8123
8124                 pic16_emitcode("mov","a,%s",l);
8125                 pic16_aopPut(AOP(result),"a",offset);
8126             } else
8127                 pic16_aopPut(AOP(result),l,offset);
8128             offset++;
8129         }
8130     }
8131
8132     tlbl = newiTempLabel(NULL);
8133     tlbl1= newiTempLabel(NULL);
8134     size = AOP_SIZE(result);
8135     offset = size - 1;
8136
8137     /* if it is only one byte then */
8138     if (size == 1) {
8139
8140       tlbl = newiTempLabel(NULL);
8141       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8142         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8143         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8144       }
8145
8146       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8147       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8148       pic16_emitpLabel(tlbl->key);
8149       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8150       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8151       emitSKPC;
8152       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8153
8154       goto release ;
8155     }
8156
8157     reAdjustPreg(AOP(result));
8158     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8159     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8160     CLRC;
8161     while (size--) {
8162         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8163         MOVA(l);
8164         pic16_emitcode("rrc","a");         
8165         pic16_aopPut(AOP(result),"a",offset--);
8166     }
8167     reAdjustPreg(AOP(result));
8168
8169     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8170     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8171
8172 release:
8173     pic16_freeAsmop(left,NULL,ic,TRUE);
8174     pic16_freeAsmop (right,NULL,ic,TRUE);
8175     pic16_freeAsmop(result,NULL,ic,TRUE);
8176 }
8177
8178 /*-----------------------------------------------------------------*/
8179 /* genUnpackBits - generates code for unpacking bits               */
8180 /*-----------------------------------------------------------------*/
8181 static void genUnpackBits (operand *result, char *rname, int ptype)
8182 {    
8183     int shCnt ;
8184     int rlen = 0 ;
8185     sym_link *etype;
8186     int offset = 0 ;
8187
8188     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8189     etype = getSpec(operandType(result));
8190
8191     /* read the first byte  */
8192     switch (ptype) {
8193
8194     case POINTER:
8195     case IPOINTER:
8196         pic16_emitcode("mov","a,@%s",rname);
8197         break;
8198         
8199     case PPOINTER:
8200         pic16_emitcode("movx","a,@%s",rname);
8201         break;
8202         
8203     case FPOINTER:
8204         pic16_emitcode("movx","a,@dptr");
8205         break;
8206
8207     case CPOINTER:
8208         pic16_emitcode("clr","a");
8209         pic16_emitcode("movc","a","@a+dptr");
8210         break;
8211
8212     case GPOINTER:
8213         pic16_emitcode("lcall","__gptrget");
8214         break;
8215     }
8216
8217     /* if we have bitdisplacement then it fits   */
8218     /* into this byte completely or if length is */
8219     /* less than a byte                          */
8220     if ((shCnt = SPEC_BSTR(etype)) || 
8221         (SPEC_BLEN(etype) <= 8))  {
8222
8223         /* shift right acc */
8224         AccRsh(shCnt);
8225
8226         pic16_emitcode("anl","a,#0x%02x",
8227                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8228         pic16_aopPut(AOP(result),"a",offset);
8229         return ;
8230     }
8231
8232     /* bit field did not fit in a byte  */
8233     rlen = SPEC_BLEN(etype) - 8;
8234     pic16_aopPut(AOP(result),"a",offset++);
8235
8236     while (1)  {
8237
8238         switch (ptype) {
8239         case POINTER:
8240         case IPOINTER:
8241             pic16_emitcode("inc","%s",rname);
8242             pic16_emitcode("mov","a,@%s",rname);
8243             break;
8244             
8245         case PPOINTER:
8246             pic16_emitcode("inc","%s",rname);
8247             pic16_emitcode("movx","a,@%s",rname);
8248             break;
8249
8250         case FPOINTER:
8251             pic16_emitcode("inc","dptr");
8252             pic16_emitcode("movx","a,@dptr");
8253             break;
8254             
8255         case CPOINTER:
8256             pic16_emitcode("clr","a");
8257             pic16_emitcode("inc","dptr");
8258             pic16_emitcode("movc","a","@a+dptr");
8259             break;
8260             
8261         case GPOINTER:
8262             pic16_emitcode("inc","dptr");
8263             pic16_emitcode("lcall","__gptrget");
8264             break;
8265         }
8266
8267         rlen -= 8;            
8268         /* if we are done */
8269         if ( rlen <= 0 )
8270             break ;
8271         
8272         pic16_aopPut(AOP(result),"a",offset++);
8273                               
8274     }
8275     
8276     if (rlen) {
8277         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8278         pic16_aopPut(AOP(result),"a",offset);          
8279     }
8280     
8281     return ;
8282 }
8283
8284 #if 0
8285 /*-----------------------------------------------------------------*/
8286 /* genDataPointerGet - generates code when ptr offset is known     */
8287 /*-----------------------------------------------------------------*/
8288 static void genDataPointerGet (operand *left, 
8289                                operand *result, 
8290                                iCode *ic)
8291 {
8292   int size , offset = 0;
8293
8294
8295   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8296
8297
8298   /* optimization - most of the time, left and result are the same
8299    * address, but different types. for the pic code, we could omit
8300    * the following
8301    */
8302
8303   pic16_aopOp(result,ic,TRUE);
8304
8305   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8306
8307   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8308
8309   size = AOP_SIZE(result);
8310
8311   while (size--) {
8312     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8313     offset++;
8314   }
8315
8316   pic16_freeAsmop(left,NULL,ic,TRUE);
8317   pic16_freeAsmop(result,NULL,ic,TRUE);
8318 }
8319 #endif
8320 /*-----------------------------------------------------------------*/
8321 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8322 /*-----------------------------------------------------------------*/
8323 static void genNearPointerGet (operand *left, 
8324                                operand *result, 
8325                                iCode *ic)
8326 {
8327     asmop *aop = NULL;
8328     //regs *preg = NULL ;
8329     char *rname ;
8330     sym_link *rtype, *retype;
8331     sym_link *ltype = operandType(left);    
8332     //char buffer[80];
8333
8334     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8335
8336     rtype = operandType(result);
8337     retype= getSpec(rtype);
8338     
8339     pic16_aopOp(left,ic,FALSE);
8340     
8341     /* if left is rematerialisable and
8342        result is not bit variable type and
8343        the left is pointer to data space i.e
8344        lower 128 bytes of space */
8345     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8346         !IS_BITVAR(retype)         &&
8347         DCL_TYPE(ltype) == POINTER) {
8348       //genDataPointerGet (left,result,ic);
8349         return ;
8350     }
8351     
8352     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8353
8354         /* if the value is already in a pointer register
8355        then don't need anything more */
8356     if (!AOP_INPREG(AOP(left))) {
8357         /* otherwise get a free pointer register */
8358     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8359 /*
8360         aop = newAsmop(0);
8361         preg = getFreePtr(ic,&aop,FALSE);
8362         pic16_emitcode("mov","%s,%s",
8363                 preg->name,
8364                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8365         rname = preg->name ;
8366 */
8367     rname ="BAD";
8368     } else
8369         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8370     
8371     pic16_aopOp (result,ic,FALSE);
8372     
8373       /* if bitfield then unpack the bits */
8374     if (IS_BITFIELD(retype)) 
8375         genUnpackBits (result,rname,POINTER);
8376     else {
8377         /* we have can just get the values */
8378       int size = AOP_SIZE(result);
8379       int offset = 0 ;  
8380         
8381       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8382
8383       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8384       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8385       while(size--) {
8386         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8387         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8388         if(size)
8389           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8390       }
8391 /*
8392         while (size--) {
8393             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8394
8395                 pic16_emitcode("mov","a,@%s",rname);
8396                 pic16_aopPut(AOP(result),"a",offset);
8397             } else {
8398                 sprintf(buffer,"@%s",rname);
8399                 pic16_aopPut(AOP(result),buffer,offset);
8400             }
8401             offset++ ;
8402             if (size)
8403                 pic16_emitcode("inc","%s",rname);
8404         }
8405 */
8406     }
8407
8408     /* now some housekeeping stuff */
8409     if (aop) {
8410         /* we had to allocate for this iCode */
8411     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8412         pic16_freeAsmop(NULL,aop,ic,TRUE);
8413     } else { 
8414         /* we did not allocate which means left
8415            already in a pointer register, then
8416            if size > 0 && this could be used again
8417            we have to point it back to where it 
8418            belongs */
8419     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8420         if (AOP_SIZE(result) > 1 &&
8421             !OP_SYMBOL(left)->remat &&
8422             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8423               ic->depth )) {
8424             int size = AOP_SIZE(result) - 1;
8425             while (size--)
8426                 pic16_emitcode("dec","%s",rname);
8427         }
8428     }
8429
8430     /* done */
8431     pic16_freeAsmop(left,NULL,ic,TRUE);
8432     pic16_freeAsmop(result,NULL,ic,TRUE);
8433      
8434 }
8435
8436 /*-----------------------------------------------------------------*/
8437 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8438 /*-----------------------------------------------------------------*/
8439 static void genPagedPointerGet (operand *left, 
8440                                operand *result, 
8441                                iCode *ic)
8442 {
8443     asmop *aop = NULL;
8444     regs *preg = NULL ;
8445     char *rname ;
8446     sym_link *rtype, *retype;    
8447
8448     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8449
8450     rtype = operandType(result);
8451     retype= getSpec(rtype);
8452     
8453     pic16_aopOp(left,ic,FALSE);
8454
8455   /* if the value is already in a pointer register
8456        then don't need anything more */
8457     if (!AOP_INPREG(AOP(left))) {
8458         /* otherwise get a free pointer register */
8459         aop = newAsmop(0);
8460         preg = getFreePtr(ic,&aop,FALSE);
8461         pic16_emitcode("mov","%s,%s",
8462                 preg->name,
8463                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8464         rname = preg->name ;
8465     } else
8466         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8467     
8468     pic16_freeAsmop(left,NULL,ic,TRUE);
8469     pic16_aopOp (result,ic,FALSE);
8470
8471     /* if bitfield then unpack the bits */
8472     if (IS_BITFIELD(retype)) 
8473         genUnpackBits (result,rname,PPOINTER);
8474     else {
8475         /* we have can just get the values */
8476         int size = AOP_SIZE(result);
8477         int offset = 0 ;        
8478         
8479         while (size--) {
8480             
8481             pic16_emitcode("movx","a,@%s",rname);
8482             pic16_aopPut(AOP(result),"a",offset);
8483             
8484             offset++ ;
8485             
8486             if (size)
8487                 pic16_emitcode("inc","%s",rname);
8488         }
8489     }
8490
8491     /* now some housekeeping stuff */
8492     if (aop) {
8493         /* we had to allocate for this iCode */
8494         pic16_freeAsmop(NULL,aop,ic,TRUE);
8495     } else { 
8496         /* we did not allocate which means left
8497            already in a pointer register, then
8498            if size > 0 && this could be used again
8499            we have to point it back to where it 
8500            belongs */
8501         if (AOP_SIZE(result) > 1 &&
8502             !OP_SYMBOL(left)->remat &&
8503             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8504               ic->depth )) {
8505             int size = AOP_SIZE(result) - 1;
8506             while (size--)
8507                 pic16_emitcode("dec","%s",rname);
8508         }
8509     }
8510
8511     /* done */
8512     pic16_freeAsmop(result,NULL,ic,TRUE);
8513     
8514         
8515 }
8516
8517 /*-----------------------------------------------------------------*/
8518 /* genFarPointerGet - gget value from far space                    */
8519 /*-----------------------------------------------------------------*/
8520 static void genFarPointerGet (operand *left,
8521                               operand *result, iCode *ic)
8522 {
8523     int size, offset ;
8524     sym_link *retype = getSpec(operandType(result));
8525
8526     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8527
8528     pic16_aopOp(left,ic,FALSE);
8529
8530     /* if the operand is already in dptr 
8531     then we do nothing else we move the value to dptr */
8532     if (AOP_TYPE(left) != AOP_STR) {
8533         /* if this is remateriazable */
8534         if (AOP_TYPE(left) == AOP_IMMD)
8535             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8536         else { /* we need to get it byte by byte */
8537             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8538             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8539             if (options.model == MODEL_FLAT24)
8540             {
8541                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8542             }
8543         }
8544     }
8545     /* so dptr know contains the address */
8546     pic16_freeAsmop(left,NULL,ic,TRUE);
8547     pic16_aopOp(result,ic,FALSE);
8548
8549     /* if bit then unpack */
8550     if (IS_BITFIELD(retype)) 
8551         genUnpackBits(result,"dptr",FPOINTER);
8552     else {
8553         size = AOP_SIZE(result);
8554         offset = 0 ;
8555
8556         while (size--) {
8557             pic16_emitcode("movx","a,@dptr");
8558             pic16_aopPut(AOP(result),"a",offset++);
8559             if (size)
8560                 pic16_emitcode("inc","dptr");
8561         }
8562     }
8563
8564     pic16_freeAsmop(result,NULL,ic,TRUE);
8565 }
8566 #if 0
8567 /*-----------------------------------------------------------------*/
8568 /* genCodePointerGet - get value from code space                  */
8569 /*-----------------------------------------------------------------*/
8570 static void genCodePointerGet (operand *left,
8571                                 operand *result, iCode *ic)
8572 {
8573     int size, offset ;
8574     sym_link *retype = getSpec(operandType(result));
8575
8576     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8577
8578     pic16_aopOp(left,ic,FALSE);
8579
8580     /* if the operand is already in dptr 
8581     then we do nothing else we move the value to dptr */
8582     if (AOP_TYPE(left) != AOP_STR) {
8583         /* if this is remateriazable */
8584         if (AOP_TYPE(left) == AOP_IMMD)
8585             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8586         else { /* we need to get it byte by byte */
8587             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8588             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8589             if (options.model == MODEL_FLAT24)
8590             {
8591                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8592             }
8593         }
8594     }
8595     /* so dptr know contains the address */
8596     pic16_freeAsmop(left,NULL,ic,TRUE);
8597     pic16_aopOp(result,ic,FALSE);
8598
8599     /* if bit then unpack */
8600     if (IS_BITFIELD(retype)) 
8601         genUnpackBits(result,"dptr",CPOINTER);
8602     else {
8603         size = AOP_SIZE(result);
8604         offset = 0 ;
8605
8606         while (size--) {
8607             pic16_emitcode("clr","a");
8608             pic16_emitcode("movc","a,@a+dptr");
8609             pic16_aopPut(AOP(result),"a",offset++);
8610             if (size)
8611                 pic16_emitcode("inc","dptr");
8612         }
8613     }
8614
8615     pic16_freeAsmop(result,NULL,ic,TRUE);
8616 }
8617 #endif
8618 /*-----------------------------------------------------------------*/
8619 /* genGenPointerGet - gget value from generic pointer space        */
8620 /*-----------------------------------------------------------------*/
8621 static void genGenPointerGet (operand *left,
8622                               operand *result, iCode *ic)
8623 {
8624   int size, offset ;
8625   sym_link *retype = getSpec(operandType(result));
8626
8627   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8628   pic16_aopOp(left,ic,FALSE);
8629   pic16_aopOp(result,ic,FALSE);
8630
8631
8632   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8633
8634   /* if the operand is already in dptr 
8635      then we do nothing else we move the value to dptr */
8636   //  if (AOP_TYPE(left) != AOP_STR) {
8637     /* if this is remateriazable */
8638     if (AOP_TYPE(left) == AOP_IMMD) {
8639       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8640       pic16_emitcode("mov","b,#%d",pointerCode(retype));
8641     }
8642     else { /* we need to get it byte by byte */
8643
8644       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8645       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8646
8647       size = AOP_SIZE(result);
8648       offset = 0 ;
8649
8650       while(size--) {
8651         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8652         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8653         if(size)
8654           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8655       }
8656       goto release;
8657     }
8658     //}
8659   /* so dptr know contains the address */
8660
8661   /* if bit then unpack */
8662         if (IS_BITFIELD(retype)) 
8663         genUnpackBits(result,"BAD",GPOINTER);
8664
8665  release:
8666   pic16_freeAsmop(left,NULL,ic,TRUE);
8667   pic16_freeAsmop(result,NULL,ic,TRUE);
8668
8669 }
8670
8671 /*-----------------------------------------------------------------*/
8672 /* genConstPointerGet - get value from const generic pointer space */
8673 /*-----------------------------------------------------------------*/
8674 static void genConstPointerGet (operand *left,
8675                                 operand *result, iCode *ic)
8676 {
8677   //sym_link *retype = getSpec(operandType(result));
8678   symbol *albl = newiTempLabel(NULL);
8679   symbol *blbl = newiTempLabel(NULL);
8680   PIC_OPCODE poc;
8681
8682   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8683   pic16_aopOp(left,ic,FALSE);
8684   pic16_aopOp(result,ic,FALSE);
8685
8686
8687   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8688
8689   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8690
8691   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
8692   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
8693   pic16_emitpLabel(albl->key);
8694
8695   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8696     
8697   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
8698   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
8699   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
8700   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
8701   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
8702
8703   pic16_emitpLabel(blbl->key);
8704
8705   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
8706
8707
8708   pic16_freeAsmop(left,NULL,ic,TRUE);
8709   pic16_freeAsmop(result,NULL,ic,TRUE);
8710
8711 }
8712 /*-----------------------------------------------------------------*/
8713 /* genPointerGet - generate code for pointer get                   */
8714 /*-----------------------------------------------------------------*/
8715 static void genPointerGet (iCode *ic)
8716 {
8717     operand *left, *result ;
8718     sym_link *type, *etype;
8719     int p_type;
8720
8721     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8722
8723     left = IC_LEFT(ic);
8724     result = IC_RESULT(ic) ;
8725
8726     /* depending on the type of pointer we need to
8727     move it to the correct pointer register */
8728     type = operandType(left);
8729     etype = getSpec(type);
8730
8731 #if 0
8732     if (IS_PTR_CONST(type))
8733 #else
8734     if (IS_CODEPTR(type))
8735 #endif
8736       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8737
8738     /* if left is of type of pointer then it is simple */
8739     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8740         p_type = DCL_TYPE(type);
8741     else {
8742         /* we have to go by the storage class */
8743         p_type = PTR_TYPE(SPEC_OCLS(etype));
8744
8745         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8746
8747         if (SPEC_OCLS(etype)->codesp ) {
8748           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8749           //p_type = CPOINTER ; 
8750         }
8751         else
8752             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8753               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8754                /*p_type = FPOINTER ;*/ 
8755             else
8756                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8757                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8758 /*                  p_type = PPOINTER; */
8759                 else
8760                     if (SPEC_OCLS(etype) == idata )
8761                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8762 /*                      p_type = IPOINTER; */
8763                     else
8764                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8765 /*                      p_type = POINTER ; */
8766     }
8767
8768     /* now that we have the pointer type we assign
8769     the pointer values */
8770     switch (p_type) {
8771
8772     case POINTER:       
8773     case IPOINTER:
8774         genNearPointerGet (left,result,ic);
8775         break;
8776
8777     case PPOINTER:
8778         genPagedPointerGet(left,result,ic);
8779         break;
8780
8781     case FPOINTER:
8782         genFarPointerGet (left,result,ic);
8783         break;
8784
8785     case CPOINTER:
8786         genConstPointerGet (left,result,ic);
8787         //pic16_emitcodePointerGet (left,result,ic);
8788         break;
8789
8790     case GPOINTER:
8791 #if 0
8792       if (IS_PTR_CONST(type))
8793         genConstPointerGet (left,result,ic);
8794       else
8795 #endif
8796         genGenPointerGet (left,result,ic);
8797       break;
8798     }
8799
8800 }
8801
8802 /*-----------------------------------------------------------------*/
8803 /* genPackBits - generates code for packed bit storage             */
8804 /*-----------------------------------------------------------------*/
8805 static void genPackBits (sym_link    *etype ,
8806                          operand *right ,
8807                          char *rname, int p_type)
8808 {
8809     int shCount = 0 ;
8810     int offset = 0  ;
8811     int rLen = 0 ;
8812     int blen, bstr ;   
8813     char *l ;
8814
8815     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8816     blen = SPEC_BLEN(etype);
8817     bstr = SPEC_BSTR(etype);
8818
8819     l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8820     MOVA(l);   
8821
8822     /* if the bit lenth is less than or    */
8823     /* it exactly fits a byte then         */
8824     if (SPEC_BLEN(etype) <= 8 )  {
8825         shCount = SPEC_BSTR(etype) ;
8826
8827         /* shift left acc */
8828         AccLsh(shCount);
8829
8830         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8831
8832
8833             switch (p_type) {
8834                 case POINTER:
8835                     pic16_emitcode ("mov","b,a");
8836                     pic16_emitcode("mov","a,@%s",rname);
8837                     break;
8838
8839                 case FPOINTER:
8840                     pic16_emitcode ("mov","b,a");
8841                     pic16_emitcode("movx","a,@dptr");
8842                     break;
8843
8844                 case GPOINTER:
8845                     pic16_emitcode ("push","b");
8846                     pic16_emitcode ("push","acc");
8847                     pic16_emitcode ("lcall","__gptrget");
8848                     pic16_emitcode ("pop","b");
8849                     break;
8850             }
8851
8852             pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
8853                       ((unsigned char)(0xFF << (blen+bstr)) | 
8854                        (unsigned char)(0xFF >> (8-bstr)) ) );
8855             pic16_emitcode ("orl","a,b");
8856             if (p_type == GPOINTER)
8857                 pic16_emitcode("pop","b");
8858         }
8859     }
8860
8861     switch (p_type) {
8862         case POINTER:
8863             pic16_emitcode("mov","@%s,a",rname);
8864             break;
8865
8866         case FPOINTER:
8867             pic16_emitcode("movx","@dptr,a");
8868             break;
8869
8870         case GPOINTER:
8871             DEBUGpic16_emitcode(";lcall","__gptrput");
8872             break;
8873     }
8874
8875     /* if we r done */
8876     if ( SPEC_BLEN(etype) <= 8 )
8877         return ;
8878
8879     pic16_emitcode("inc","%s",rname);
8880     rLen = SPEC_BLEN(etype) ;     
8881
8882     /* now generate for lengths greater than one byte */
8883     while (1) {
8884
8885         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
8886
8887         rLen -= 8 ;
8888         if (rLen <= 0 )
8889             break ;
8890
8891         switch (p_type) {
8892             case POINTER:
8893                 if (*l == '@') {
8894                     MOVA(l);
8895                     pic16_emitcode("mov","@%s,a",rname);
8896                 } else
8897                     pic16_emitcode("mov","@%s,%s",rname,l);
8898                 break;
8899
8900             case FPOINTER:
8901                 MOVA(l);
8902                 pic16_emitcode("movx","@dptr,a");
8903                 break;
8904
8905             case GPOINTER:
8906                 MOVA(l);
8907                 DEBUGpic16_emitcode(";lcall","__gptrput");
8908                 break;  
8909         }   
8910         pic16_emitcode ("inc","%s",rname);
8911     }
8912
8913     MOVA(l);
8914
8915     /* last last was not complete */
8916     if (rLen)   {
8917         /* save the byte & read byte */
8918         switch (p_type) {
8919             case POINTER:
8920                 pic16_emitcode ("mov","b,a");
8921                 pic16_emitcode("mov","a,@%s",rname);
8922                 break;
8923
8924             case FPOINTER:
8925                 pic16_emitcode ("mov","b,a");
8926                 pic16_emitcode("movx","a,@dptr");
8927                 break;
8928
8929             case GPOINTER:
8930                 pic16_emitcode ("push","b");
8931                 pic16_emitcode ("push","acc");
8932                 pic16_emitcode ("lcall","__gptrget");
8933                 pic16_emitcode ("pop","b");
8934                 break;
8935         }
8936
8937         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8938         pic16_emitcode ("orl","a,b");
8939     }
8940
8941     if (p_type == GPOINTER)
8942         pic16_emitcode("pop","b");
8943
8944     switch (p_type) {
8945
8946     case POINTER:
8947         pic16_emitcode("mov","@%s,a",rname);
8948         break;
8949         
8950     case FPOINTER:
8951         pic16_emitcode("movx","@dptr,a");
8952         break;
8953         
8954     case GPOINTER:
8955         DEBUGpic16_emitcode(";lcall","__gptrput");
8956         break;                  
8957     }
8958 }
8959 /*-----------------------------------------------------------------*/
8960 /* genDataPointerSet - remat pointer to data space                 */
8961 /*-----------------------------------------------------------------*/
8962 static void genDataPointerSet(operand *right,
8963                               operand *result,
8964                               iCode *ic)
8965 {
8966     int size, offset = 0 ;
8967     char *l, buffer[256];
8968
8969     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8970     pic16_aopOp(right,ic,FALSE);
8971     
8972     l = pic16_aopGet(AOP(result),0,FALSE,TRUE);
8973     size = AOP_SIZE(right);
8974 /*
8975     if ( AOP_TYPE(result) == AOP_PCODE) {
8976       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8977               AOP(result)->aopu.pcop->name,
8978               PCOI(AOP(result)->aopu.pcop)->offset);
8979     }
8980 */
8981
8982     // tsd, was l+1 - the underline `_' prefix was being stripped
8983     while (size--) {
8984       if (offset) {
8985         sprintf(buffer,"(%s + %d)",l,offset);
8986         fprintf(stderr,"%s:%d: oops  %s\n",__FILE__, __LINE__, buffer);
8987       } else
8988         sprintf(buffer,"%s",l);
8989
8990         if (AOP_TYPE(right) == AOP_LIT) {
8991           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8992           lit = lit >> (8*offset);
8993           if(lit&0xff) {
8994             pic16_emitcode("movlw","%d",lit);
8995             pic16_emitcode("movwf","%s",buffer);
8996
8997             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
8998             //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
8999             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9000
9001           } else {
9002             pic16_emitcode("clrf","%s",buffer);
9003             //pic16_emitpcode(POC_CLRF, pic16_popRegFromString(buffer));
9004             pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
9005           }
9006         }else {
9007           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
9008           pic16_emitcode("movwf","%s",buffer);
9009
9010           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9011           //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
9012           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9013
9014         }
9015
9016         offset++;
9017     }
9018
9019     pic16_freeAsmop(right,NULL,ic,TRUE);
9020     pic16_freeAsmop(result,NULL,ic,TRUE);
9021 }
9022
9023 /*-----------------------------------------------------------------*/
9024 /* genNearPointerSet - pic16_emitcode for near pointer put                */
9025 /*-----------------------------------------------------------------*/
9026 static void genNearPointerSet (operand *right,
9027                                operand *result, 
9028                                iCode *ic)
9029 {
9030   asmop *aop = NULL;
9031   char *l;
9032   sym_link *retype;
9033   sym_link *ptype = operandType(result);
9034
9035     
9036   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9037   retype= getSpec(operandType(right));
9038
9039   pic16_aopOp(result,ic,FALSE);
9040
9041     
9042   /* if the result is rematerializable &
9043      in data space & not a bit variable */
9044   //if (AOP_TYPE(result) == AOP_IMMD &&
9045   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
9046       DCL_TYPE(ptype) == POINTER   &&
9047       !IS_BITVAR(retype)) {
9048     genDataPointerSet (right,result,ic);
9049     pic16_freeAsmop(result,NULL,ic,TRUE);
9050     return;
9051   }
9052
9053   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9054   pic16_aopOp(right,ic,FALSE);
9055   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9056
9057   /* if the value is already in a pointer register
9058      then don't need anything more */
9059   if (!AOP_INPREG(AOP(result))) {
9060     /* otherwise get a free pointer register */
9061     //aop = newAsmop(0);
9062     //preg = getFreePtr(ic,&aop,FALSE);
9063     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9064     //pic16_emitcode("mov","%s,%s",
9065     //         preg->name,
9066     //         pic16_aopGet(AOP(result),0,FALSE,TRUE));
9067     //rname = preg->name ;
9068     //pic16_emitcode("movwf","fsr0");
9069     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0));
9070     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_fsr0));
9071     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9072     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9073     goto release;
9074
9075   }// else
9076 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9077
9078   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9079
9080   /* if bitfield then unpack the bits */
9081   if (IS_BITFIELD(retype)) {
9082     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9083            "The programmer is obviously confused");
9084 //      genPackBits (retype,right,"BAD",POINTER);
9085     exit(1);
9086   }
9087   else {
9088     /* we have can just get the values */
9089     int size = AOP_SIZE(right);
9090     int offset = 0 ;    
9091
9092     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9093     while (size--) {
9094       l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9095       if (*l == '@' ) {
9096         //MOVA(l);
9097         //pic16_emitcode("mov","@%s,a",rname);
9098         pic16_emitcode("movf","indf0,w ;1");
9099       } else {
9100
9101         if (AOP_TYPE(right) == AOP_LIT) {
9102           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9103           if(lit) {
9104             pic16_emitcode("movlw","%s",l);
9105             pic16_emitcode("movwf","indf0 ;2");
9106           } else 
9107             pic16_emitcode("clrf","indf0");
9108         }else {
9109           pic16_emitcode("movf","%s,w",l);
9110           pic16_emitcode("movwf","indf0 ;2");
9111         }
9112         //pic16_emitcode("mov","@%s,%s",rname,l);
9113       }
9114       if (size)
9115         pic16_emitcode("incf","fsr0,f ;3");
9116       //pic16_emitcode("inc","%s",rname);
9117       offset++;
9118     }
9119   }
9120
9121   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9122   /* now some housekeeping stuff */
9123   if (aop) {
9124     /* we had to allocate for this iCode */
9125     pic16_freeAsmop(NULL,aop,ic,TRUE);
9126   } else { 
9127     /* we did not allocate which means left
9128        already in a pointer register, then
9129        if size > 0 && this could be used again
9130        we have to point it back to where it 
9131        belongs */
9132     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9133     if (AOP_SIZE(right) > 1 &&
9134         !OP_SYMBOL(result)->remat &&
9135         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9136           ic->depth )) {
9137       int size = AOP_SIZE(right) - 1;
9138       while (size--)
9139         pic16_emitcode("decf","fsr0,f");
9140       //pic16_emitcode("dec","%s",rname);
9141     }
9142   }
9143
9144   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9145   /* done */
9146  release:
9147   pic16_freeAsmop(right,NULL,ic,TRUE);
9148   pic16_freeAsmop(result,NULL,ic,TRUE);
9149 }
9150
9151 /*-----------------------------------------------------------------*/
9152 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
9153 /*-----------------------------------------------------------------*/
9154 static void genPagedPointerSet (operand *right,
9155                                operand *result, 
9156                                iCode *ic)
9157 {
9158     asmop *aop = NULL;
9159     regs *preg = NULL ;
9160     char *rname , *l;
9161     sym_link *retype;
9162        
9163     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9164
9165     retype= getSpec(operandType(right));
9166     
9167     pic16_aopOp(result,ic,FALSE);
9168     
9169     /* if the value is already in a pointer register
9170        then don't need anything more */
9171     if (!AOP_INPREG(AOP(result))) {
9172         /* otherwise get a free pointer register */
9173         aop = newAsmop(0);
9174         preg = getFreePtr(ic,&aop,FALSE);
9175         pic16_emitcode("mov","%s,%s",
9176                 preg->name,
9177                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9178         rname = preg->name ;
9179     } else
9180         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9181     
9182     pic16_freeAsmop(result,NULL,ic,TRUE);
9183     pic16_aopOp (right,ic,FALSE);
9184
9185     /* if bitfield then unpack the bits */
9186     if (IS_BITFIELD(retype)) 
9187         genPackBits (retype,right,rname,PPOINTER);
9188     else {
9189         /* we have can just get the values */
9190         int size = AOP_SIZE(right);
9191         int offset = 0 ;        
9192         
9193         while (size--) {
9194             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9195             
9196             MOVA(l);
9197             pic16_emitcode("movx","@%s,a",rname);
9198
9199             if (size)
9200                 pic16_emitcode("inc","%s",rname);
9201
9202             offset++;
9203         }
9204     }
9205     
9206     /* now some housekeeping stuff */
9207     if (aop) {
9208         /* we had to allocate for this iCode */
9209         pic16_freeAsmop(NULL,aop,ic,TRUE);
9210     } else { 
9211         /* we did not allocate which means left
9212            already in a pointer register, then
9213            if size > 0 && this could be used again
9214            we have to point it back to where it 
9215            belongs */
9216         if (AOP_SIZE(right) > 1 &&
9217             !OP_SYMBOL(result)->remat &&
9218             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9219               ic->depth )) {
9220             int size = AOP_SIZE(right) - 1;
9221             while (size--)
9222                 pic16_emitcode("dec","%s",rname);
9223         }
9224     }
9225
9226     /* done */
9227     pic16_freeAsmop(right,NULL,ic,TRUE);
9228     
9229         
9230 }
9231
9232 /*-----------------------------------------------------------------*/
9233 /* genFarPointerSet - set value from far space                     */
9234 /*-----------------------------------------------------------------*/
9235 static void genFarPointerSet (operand *right,
9236                               operand *result, iCode *ic)
9237 {
9238     int size, offset ;
9239     sym_link *retype = getSpec(operandType(right));
9240
9241     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9242     pic16_aopOp(result,ic,FALSE);
9243
9244     /* if the operand is already in dptr 
9245     then we do nothing else we move the value to dptr */
9246     if (AOP_TYPE(result) != AOP_STR) {
9247         /* if this is remateriazable */
9248         if (AOP_TYPE(result) == AOP_IMMD)
9249             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9250         else { /* we need to get it byte by byte */
9251             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9252             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9253             if (options.model == MODEL_FLAT24)
9254             {
9255                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9256             }
9257         }
9258     }
9259     /* so dptr know contains the address */
9260     pic16_freeAsmop(result,NULL,ic,TRUE);
9261     pic16_aopOp(right,ic,FALSE);
9262
9263     /* if bit then unpack */
9264     if (IS_BITFIELD(retype)) 
9265         genPackBits(retype,right,"dptr",FPOINTER);
9266     else {
9267         size = AOP_SIZE(right);
9268         offset = 0 ;
9269
9270         while (size--) {
9271             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9272             MOVA(l);
9273             pic16_emitcode("movx","@dptr,a");
9274             if (size)
9275                 pic16_emitcode("inc","dptr");
9276         }
9277     }
9278
9279     pic16_freeAsmop(right,NULL,ic,TRUE);
9280 }
9281
9282 /*-----------------------------------------------------------------*/
9283 /* genGenPointerSet - set value from generic pointer space         */
9284 /*-----------------------------------------------------------------*/
9285 static void genGenPointerSet (operand *right,
9286                               operand *result, iCode *ic)
9287 {
9288   int size, offset ;
9289   sym_link *retype = getSpec(operandType(right));
9290
9291   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9292
9293   pic16_aopOp(result,ic,FALSE);
9294   pic16_aopOp(right,ic,FALSE);
9295   size = AOP_SIZE(right);
9296
9297   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9298
9299   /* if the operand is already in dptr 
9300      then we do nothing else we move the value to dptr */
9301   if (AOP_TYPE(result) != AOP_STR) {
9302     /* if this is remateriazable */
9303     if (AOP_TYPE(result) == AOP_IMMD) {
9304       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9305       pic16_emitcode("mov","b,%s + 1",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9306     }
9307     else { /* we need to get it byte by byte */
9308       //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9309       size = AOP_SIZE(right);
9310       offset = 0 ;
9311
9312       /* hack hack! see if this the FSR. If so don't load W */
9313       if(AOP_TYPE(right) != AOP_ACC) {
9314
9315 //      pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(result), pic16_popCopyReg(&pic16_pc_fsr0), 0));
9316
9317         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),0));
9318         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9319
9320         if(AOP_SIZE(result) > 1) {
9321           pic16_emitpcode(POC_BCF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9322           pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),1,FALSE,FALSE),0,0));
9323           pic16_emitpcode(POC_BSF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9324
9325         }
9326
9327         //if(size==2)
9328         //pic16_emitpcode(POC_DECF,pic16_popCopyReg(&pic16_pc_fsr0));
9329         //if(size==4) {
9330         //  pic16_emitpcode(POC_MOVLW,pic16_popGetLit(0xfd));
9331         //  pic16_emitpcode(POC_ADDWF,pic16_popCopyReg(&pic16_pc_fsr0));
9332         //}
9333
9334         while(size--) {
9335           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset++));
9336           pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9337           
9338           if(size)
9339             pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9340         }
9341
9342
9343         goto release;
9344       } 
9345
9346       if(aopIdx(AOP(result),0) != 4) {
9347
9348         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9349         goto release;
9350       }
9351
9352       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9353       goto release;
9354
9355     }
9356   }
9357   /* so dptr know contains the address */
9358
9359
9360   /* if bit then unpack */
9361   if (IS_BITFIELD(retype)) 
9362     genPackBits(retype,right,"dptr",GPOINTER);
9363   else {
9364     size = AOP_SIZE(right);
9365     offset = 0 ;
9366
9367   DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9368
9369     while (size--) {
9370
9371       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offset));
9372       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9373
9374       if (AOP_TYPE(right) == AOP_LIT) 
9375         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9376       else
9377         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9378
9379       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9380
9381       offset++;
9382     }
9383   }
9384
9385  release:
9386   pic16_freeAsmop(right,NULL,ic,TRUE);
9387   pic16_freeAsmop(result,NULL,ic,TRUE);
9388 }
9389
9390 /*-----------------------------------------------------------------*/
9391 /* genPointerSet - stores the value into a pointer location        */
9392 /*-----------------------------------------------------------------*/
9393 static void genPointerSet (iCode *ic)
9394 {    
9395     operand *right, *result ;
9396     sym_link *type, *etype;
9397     int p_type;
9398
9399     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9400
9401     right = IC_RIGHT(ic);
9402     result = IC_RESULT(ic) ;
9403
9404     /* depending on the type of pointer we need to
9405     move it to the correct pointer register */
9406     type = operandType(result);
9407     etype = getSpec(type);
9408     /* if left is of type of pointer then it is simple */
9409     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9410         p_type = DCL_TYPE(type);
9411     }
9412     else {
9413         /* we have to go by the storage class */
9414         p_type = PTR_TYPE(SPEC_OCLS(etype));
9415
9416 /*      if (SPEC_OCLS(etype)->codesp ) { */
9417 /*          p_type = CPOINTER ;  */
9418 /*      } */
9419 /*      else */
9420 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9421 /*              p_type = FPOINTER ; */
9422 /*          else */
9423 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9424 /*                  p_type = PPOINTER ; */
9425 /*              else */
9426 /*                  if (SPEC_OCLS(etype) == idata ) */
9427 /*                      p_type = IPOINTER ; */
9428 /*                  else */
9429 /*                      p_type = POINTER ; */
9430     }
9431
9432     /* now that we have the pointer type we assign
9433     the pointer values */
9434     switch (p_type) {
9435
9436     case POINTER:
9437     case IPOINTER:
9438         genNearPointerSet (right,result,ic);
9439         break;
9440
9441     case PPOINTER:
9442         genPagedPointerSet (right,result,ic);
9443         break;
9444
9445     case FPOINTER:
9446         genFarPointerSet (right,result,ic);
9447         break;
9448
9449     case GPOINTER:
9450         genGenPointerSet (right,result,ic);
9451         break;
9452
9453     default:
9454       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9455               "genPointerSet: illegal pointer type");
9456     }
9457 }
9458
9459 /*-----------------------------------------------------------------*/
9460 /* genIfx - generate code for Ifx statement                        */
9461 /*-----------------------------------------------------------------*/
9462 static void genIfx (iCode *ic, iCode *popIc)
9463 {
9464   operand *cond = IC_COND(ic);
9465   int isbit =0;
9466
9467   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9468
9469   pic16_aopOp(cond,ic,FALSE);
9470
9471   /* get the value into acc */
9472   if (AOP_TYPE(cond) != AOP_CRY)
9473     pic16_toBoolean(cond);
9474   else
9475     isbit = 1;
9476   /* the result is now in the accumulator */
9477   pic16_freeAsmop(cond,NULL,ic,TRUE);
9478
9479   /* if there was something to be popped then do it */
9480   if (popIc)
9481     genIpop(popIc);
9482
9483   /* if the condition is  a bit variable */
9484   if (isbit && IS_ITEMP(cond) && 
9485       SPIL_LOC(cond)) {
9486     genIfxJump(ic,SPIL_LOC(cond)->rname);
9487     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9488   }
9489   else {
9490     if (isbit && !IS_ITEMP(cond))
9491       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9492     else
9493       genIfxJump(ic,"a");
9494   }
9495   ic->generated = 1;
9496
9497 }
9498
9499 /*-----------------------------------------------------------------*/
9500 /* genAddrOf - generates code for address of                       */
9501 /*-----------------------------------------------------------------*/
9502 #if 0
9503 static void genAddrOf (iCode *ic)
9504 {
9505   operand *right, *result, *left;
9506   int size, offset ;
9507
9508   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9509
9510
9511   //pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9512
9513   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
9514   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9515   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9516
9517   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
9518
9519   size = AOP_SIZE(IC_RESULT(ic));
9520   offset = 0;
9521
9522
9523   while (size--) {
9524     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),offset));
9525     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9526     offset++;
9527   }
9528
9529
9530   pic16_freeAsmop(left,NULL,ic,FALSE);
9531   pic16_freeAsmop(result,NULL,ic,TRUE);
9532
9533 }
9534
9535 #else   /* new genAddrOf */
9536
9537 static void genAddrOf (iCode *ic)
9538 {
9539   operand *result, *left;
9540   int size;
9541   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
9542   pCodeOp *pcop0, *pcop1, *pcop2;
9543
9544         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9545
9546         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9547         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9548
9549         sym = OP_SYMBOL( left );
9550
9551         size = AOP_SIZE(IC_RESULT(ic));
9552
9553         if(pic16_debug_verbose) {
9554                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9555                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9556         }
9557         
9558         /* Assume that what we want the address of is in data space
9559          * since there is no stack on the PIC, yet! -- VR */
9560         /* low */
9561         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9562
9563         /* high */
9564         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9565         
9566         /* upper */
9567         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9568         
9569
9570         if (size == 3) {
9571                 pic16_emitpcode(POC_MOVLW, pcop0);
9572                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9573                 pic16_emitpcode(POC_MOVLW, pcop1);
9574                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9575                 pic16_emitpcode(POC_MOVLW, pcop2);
9576                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9577         } else
9578         if (size == 2) {
9579                 pic16_emitpcode(POC_MOVLW, pcop0);
9580                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9581                 pic16_emitpcode(POC_MOVLW, pcop1);
9582                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9583         } else {
9584                 pic16_emitpcode(POC_MOVLW, pcop0);
9585                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9586         }
9587
9588         pic16_freeAsmop(result,NULL,ic,TRUE);
9589         pic16_freeAsmop(left, NULL, ic, FALSE);
9590 }
9591
9592 #endif  /* new genAddrOf */
9593
9594 #if 0
9595 /*-----------------------------------------------------------------*/
9596 /* genFarFarAssign - assignment when both are in far space         */
9597 /*-----------------------------------------------------------------*/
9598 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9599 {
9600     int size = AOP_SIZE(right);
9601     int offset = 0;
9602     char *l ;
9603     /* first push the right side on to the stack */
9604     while (size--) {
9605         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9606         MOVA(l);
9607         pic16_emitcode ("push","acc");
9608     }
9609     
9610     pic16_freeAsmop(right,NULL,ic,FALSE);
9611     /* now assign DPTR to result */
9612     pic16_aopOp(result,ic,FALSE);
9613     size = AOP_SIZE(result);
9614     while (size--) {
9615         pic16_emitcode ("pop","acc");
9616         pic16_aopPut(AOP(result),"a",--offset);
9617     }
9618     pic16_freeAsmop(result,NULL,ic,FALSE);
9619         
9620 }
9621 #endif
9622
9623 /*-----------------------------------------------------------------*/
9624 /* genAssign - generate code for assignment                        */
9625 /*-----------------------------------------------------------------*/
9626 static void genAssign (iCode *ic)
9627 {
9628   operand *result, *right;
9629   int size, offset,know_W;
9630   unsigned long lit = 0L;
9631
9632   result = IC_RESULT(ic);
9633   right  = IC_RIGHT(ic) ;
9634
9635   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9636   
9637   /* if they are the same */
9638   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9639     return ;
9640
9641   pic16_aopOp(right,ic,FALSE);
9642   pic16_aopOp(result,ic,TRUE);
9643
9644   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9645
9646   /* if they are the same registers */
9647   if (pic16_sameRegs(AOP(right),AOP(result)))
9648     goto release;
9649
9650   /* if the result is a bit */
9651   if (AOP_TYPE(result) == AOP_CRY) {
9652     /* if the right size is a literal then
9653        we know what the value is */
9654     if (AOP_TYPE(right) == AOP_LIT) {
9655           
9656       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9657                   pic16_popGet(AOP(result),0));
9658
9659       if (((int) operandLitValue(right))) 
9660         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9661                        AOP(result)->aopu.aop_dir,
9662                        AOP(result)->aopu.aop_dir);
9663       else
9664         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9665                        AOP(result)->aopu.aop_dir,
9666                        AOP(result)->aopu.aop_dir);
9667       goto release;
9668     }
9669
9670     /* the right is also a bit variable */
9671     if (AOP_TYPE(right) == AOP_CRY) {
9672       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9673       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9674       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9675
9676       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9677                      AOP(result)->aopu.aop_dir,
9678                      AOP(result)->aopu.aop_dir);
9679       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
9680                      AOP(right)->aopu.aop_dir,
9681                      AOP(right)->aopu.aop_dir);
9682       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9683                      AOP(result)->aopu.aop_dir,
9684                      AOP(result)->aopu.aop_dir);
9685       goto release ;
9686     }
9687
9688     /* we need to or */
9689     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9690     pic16_toBoolean(right);
9691     emitSKPZ;
9692     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9693     //pic16_aopPut(AOP(result),"a",0);
9694     goto release ;
9695   }
9696
9697   /* bit variables done */
9698   /* general case */
9699   size = AOP_SIZE(result);
9700   offset = 0 ;
9701   if(AOP_TYPE(right) == AOP_LIT)
9702     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9703
9704 /* VR - What is this?! */
9705   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9706   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9707     if(aopIdx(AOP(result),0) == 4) {
9708   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9709       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9710       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9711       goto release;
9712     } else
9713       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9714   }
9715
9716   know_W=-1;
9717   while (size--) {
9718   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9719     if(AOP_TYPE(right) == AOP_LIT) {
9720       if(lit&0xff) {
9721         if(know_W != (lit&0xff))
9722           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9723         know_W = lit&0xff;
9724         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9725       } else
9726         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9727
9728       lit >>= 8;
9729
9730     } else if (AOP_TYPE(right) == AOP_CRY) {
9731       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9732       if(offset == 0) {
9733         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
9734         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9735       }
9736     } else {
9737   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9738
9739 #if 1
9740         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
9741            normally should work, but mind that the W register live range
9742            is not checked, so if the code generator assumes that the W
9743            is already loaded after such a pair, wrong code will be generated.
9744            
9745            Checking the live range is the next step.
9746            This is experimental code yet and has not been fully tested yet.
9747            USE WITH CARE. Revert to old code by setting 0 to the condition above.
9748            Vangelis Rokas 030603 (vrokas@otenet.gr) */
9749            
9750         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9751 #else   
9752         /* This is the old code, which is assumed(?!) that works fine(!?) */
9753
9754         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9755         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9756 #endif
9757     }
9758             
9759     offset++;
9760   }
9761
9762     
9763  release:
9764   pic16_freeAsmop (right,NULL,ic,FALSE);
9765   pic16_freeAsmop (result,NULL,ic,TRUE);
9766 }   
9767
9768 /*-----------------------------------------------------------------*/
9769 /* genJumpTab - generates code for jump table                       */
9770 /*-----------------------------------------------------------------*/
9771 static void genJumpTab (iCode *ic)
9772 {
9773     symbol *jtab;
9774     char *l;
9775
9776     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9777
9778     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9779     /* get the condition into accumulator */
9780     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9781     MOVA(l);
9782     /* multiply by three */
9783     pic16_emitcode("add","a,acc");
9784     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9785
9786     jtab = newiTempLabel(NULL);
9787     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9788     pic16_emitcode("jmp","@a+dptr");
9789     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9790
9791     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9792     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9793     emitSKPNC;
9794     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9795     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9796     pic16_emitpLabel(jtab->key);
9797
9798     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9799
9800     /* now generate the jump labels */
9801     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9802          jtab = setNextItem(IC_JTLABELS(ic))) {
9803         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9804         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9805         
9806     }
9807
9808 }
9809
9810 /*-----------------------------------------------------------------*/
9811 /* genMixedOperation - gen code for operators between mixed types  */
9812 /*-----------------------------------------------------------------*/
9813 /*
9814   TSD - Written for the PIC port - but this unfortunately is buggy.
9815   This routine is good in that it is able to efficiently promote 
9816   types to different (larger) sizes. Unfortunately, the temporary
9817   variables that are optimized out by this routine are sometimes
9818   used in other places. So until I know how to really parse the 
9819   iCode tree, I'm going to not be using this routine :(.
9820 */
9821 static int genMixedOperation (iCode *ic)
9822 {
9823 #if 0
9824   operand *result = IC_RESULT(ic);
9825   sym_link *ctype = operandType(IC_LEFT(ic));
9826   operand *right = IC_RIGHT(ic);
9827   int ret = 0;
9828   int big,small;
9829   int offset;
9830
9831   iCode *nextic;
9832   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9833
9834   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9835
9836   nextic = ic->next;
9837   if(!nextic)
9838     return 0;
9839
9840   nextright = IC_RIGHT(nextic);
9841   nextleft  = IC_LEFT(nextic);
9842   nextresult = IC_RESULT(nextic);
9843
9844   pic16_aopOp(right,ic,FALSE);
9845   pic16_aopOp(result,ic,FALSE);
9846   pic16_aopOp(nextright,  nextic, FALSE);
9847   pic16_aopOp(nextleft,   nextic, FALSE);
9848   pic16_aopOp(nextresult, nextic, FALSE);
9849
9850   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9851
9852     operand *t = right;
9853     right = nextright;
9854     nextright = t; 
9855
9856     pic16_emitcode(";remove right +","");
9857
9858   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9859 /*
9860     operand *t = right;
9861     right = nextleft;
9862     nextleft = t; 
9863 */
9864     pic16_emitcode(";remove left +","");
9865   } else
9866     return 0;
9867
9868   big = AOP_SIZE(nextleft);
9869   small = AOP_SIZE(nextright);
9870
9871   switch(nextic->op) {
9872
9873   case '+':
9874     pic16_emitcode(";optimize a +","");
9875     /* if unsigned or not an integral type */
9876     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9877       pic16_emitcode(";add a bit to something","");
9878     } else {
9879
9880       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9881
9882       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9883         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9884         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9885       } else
9886         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9887
9888       offset = 0;
9889       while(--big) {
9890
9891         offset++;
9892
9893         if(--small) {
9894           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9895             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9896             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9897           }
9898
9899           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9900           emitSKPNC;
9901           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9902                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9903                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9904           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9905           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9906
9907         } else {
9908           pic16_emitcode("rlf","known_zero,w");
9909
9910           /*
9911             if right is signed
9912               btfsc  right,7
9913                addlw ff
9914           */
9915           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9916             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9917             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9918           } else {
9919             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9920           }
9921         }
9922       }
9923       ret = 1;
9924     }
9925   }
9926   ret = 1;
9927
9928 release:
9929   pic16_freeAsmop(right,NULL,ic,TRUE);
9930   pic16_freeAsmop(result,NULL,ic,TRUE);
9931   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9932   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9933   if(ret)
9934     nextic->generated = 1;
9935
9936   return ret;
9937 #else
9938   return 0;
9939 #endif
9940 }
9941 /*-----------------------------------------------------------------*/
9942 /* genCast - gen code for casting                                  */
9943 /*-----------------------------------------------------------------*/
9944 static void genCast (iCode *ic)
9945 {
9946   operand *result = IC_RESULT(ic);
9947   sym_link *ctype = operandType(IC_LEFT(ic));
9948   sym_link *rtype = operandType(IC_RIGHT(ic));
9949   operand *right = IC_RIGHT(ic);
9950   int size, offset ;
9951
9952         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9953         /* if they are equivalent then do nothing */
9954         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9955                 return ;
9956
9957         pic16_aopOp(right,ic,FALSE) ;
9958         pic16_aopOp(result,ic,FALSE);
9959
9960         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9961
9962         /* if the result is a bit */
9963         if (AOP_TYPE(result) == AOP_CRY) {
9964         
9965                 /* if the right size is a literal then
9966                  * we know what the value is */
9967                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9968
9969                 if (AOP_TYPE(right) == AOP_LIT) {
9970                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9971                                 pic16_popGet(AOP(result),0));
9972
9973                         if (((int) operandLitValue(right))) 
9974                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9975                                         AOP(result)->aopu.aop_dir,
9976                                         AOP(result)->aopu.aop_dir);
9977                         else
9978                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9979                                         AOP(result)->aopu.aop_dir,
9980                                         AOP(result)->aopu.aop_dir);
9981                         goto release;
9982                 }
9983
9984                 /* the right is also a bit variable */
9985                 if (AOP_TYPE(right) == AOP_CRY) {
9986                         emitCLRC;
9987                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9988
9989                         pic16_emitcode("clrc","");
9990                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9991                                 AOP(right)->aopu.aop_dir,
9992                                 AOP(right)->aopu.aop_dir);
9993                         pic16_aopPut(AOP(result),"c",0);
9994                         goto release ;
9995                 }
9996
9997                 /* we need to or */
9998                 if (AOP_TYPE(right) == AOP_REG) {
9999                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10000                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10001                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10002                 }
10003                 pic16_toBoolean(right);
10004                 pic16_aopPut(AOP(result),"a",0);
10005                 goto release ;
10006         }
10007
10008         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10009           int offset = 1;
10010
10011                 size = AOP_SIZE(result);
10012
10013                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10014
10015                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10016                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10017                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10018
10019                 while (size--)
10020                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10021
10022                 goto release;
10023         }
10024
10025         /* if they are the same size : or less */
10026         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10027
10028                 /* if they are in the same place */
10029                 if (pic16_sameRegs(AOP(right),AOP(result)))
10030                         goto release;
10031
10032                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10033 #if 0
10034                 if (IS_PTR_CONST(rtype))
10035 #else
10036                 if (IS_CODEPTR(rtype))
10037 #endif
10038                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10039
10040 #if 0
10041                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10042 #else
10043                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10044 #endif
10045                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10046
10047 #if 0
10048                 if(AOP_TYPE(right) == AOP_IMMD) {
10049                   pCodeOp *pcop0, *pcop1, *pcop2;
10050                   symbol *sym = OP_SYMBOL( right );
10051
10052                         size = AOP_SIZE(result);
10053                         /* low */
10054                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10055                         /* high */
10056                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10057                         /* upper */
10058                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10059         
10060                         if (size == 3) {
10061                                 pic16_emitpcode(POC_MOVLW, pcop0);
10062                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10063                                 pic16_emitpcode(POC_MOVLW, pcop1);
10064                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10065                                 pic16_emitpcode(POC_MOVLW, pcop2);
10066                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10067                         } else
10068                         if (size == 2) {
10069                                 pic16_emitpcode(POC_MOVLW, pcop0);
10070                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10071                                 pic16_emitpcode(POC_MOVLW, pcop1);
10072                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10073                         } else {
10074                                 pic16_emitpcode(POC_MOVLW, pcop0);
10075                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10076                         }
10077                 } else
10078 #endif
10079                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10080                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10081                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10082                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10083                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10084                         if(AOP_SIZE(result) <2)
10085                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10086                 } else {
10087                         /* if they in different places then copy */
10088                         size = AOP_SIZE(result);
10089                         offset = 0 ;
10090                         while (size--) {
10091                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10092                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10093                                 offset++;
10094                         }
10095                 }
10096                 goto release;
10097         }
10098
10099         /* if the result is of type pointer */
10100         if (IS_PTR(ctype)) {
10101           int p_type;
10102           sym_link *type = operandType(right);
10103           sym_link *etype = getSpec(type);
10104
10105                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10106
10107                 /* pointer to generic pointer */
10108                 if (IS_GENPTR(ctype)) {
10109                   char *l = zero;
10110             
10111                         if (IS_PTR(type)) 
10112                                 p_type = DCL_TYPE(type);
10113                         else {
10114                 /* we have to go by the storage class */
10115                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10116
10117 /*              if (SPEC_OCLS(etype)->codesp )  */
10118 /*                  p_type = CPOINTER ;  */
10119 /*              else */
10120 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10121 /*                      p_type = FPOINTER ; */
10122 /*                  else */
10123 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10124 /*                          p_type = PPOINTER; */
10125 /*                      else */
10126 /*                          if (SPEC_OCLS(etype) == idata ) */
10127 /*                              p_type = IPOINTER ; */
10128 /*                          else */
10129 /*                              p_type = POINTER ; */
10130             }
10131                 
10132             /* the first two bytes are known */
10133       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10134             size = GPTRSIZE - 1; 
10135             offset = 0 ;
10136             while (size--) {
10137               if(offset < AOP_SIZE(right)) {
10138       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10139                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10140                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10141                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10142                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10143                 } else { 
10144                   pic16_aopPut(AOP(result),
10145                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10146                          offset);
10147                 }
10148               } else 
10149                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10150               offset++;
10151             }
10152             /* the last byte depending on type */
10153             switch (p_type) {
10154             case IPOINTER:
10155             case POINTER:
10156                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10157                 break;
10158             case FPOINTER:
10159               pic16_emitcode(";BUG!? ","%d",__LINE__);
10160                 l = one;
10161                 break;
10162             case CPOINTER:
10163               pic16_emitcode(";BUG!? ","%d",__LINE__);
10164                 l = "#0x02";
10165                 break;                          
10166             case PPOINTER:
10167               pic16_emitcode(";BUG!? ","%d",__LINE__);
10168                 l = "#0x03";
10169                 break;
10170                 
10171             default:
10172                 /* this should never happen */
10173                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10174                        "got unknown pointer type");
10175                 exit(1);
10176             }
10177             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
10178             goto release ;
10179         }
10180         
10181         /* just copy the pointers */
10182         size = AOP_SIZE(result);
10183         offset = 0 ;
10184         while (size--) {
10185             pic16_aopPut(AOP(result),
10186                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10187                    offset);
10188             offset++;
10189         }
10190         goto release ;
10191     }
10192     
10193
10194
10195     /* so we now know that the size of destination is greater
10196     than the size of the source.
10197     Now, if the next iCode is an operator then we might be
10198     able to optimize the operation without performing a cast.
10199     */
10200     if(genMixedOperation(ic))
10201       goto release;
10202
10203     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10204     
10205     /* we move to result for the size of source */
10206     size = AOP_SIZE(right);
10207     offset = 0 ;
10208     while (size--) {
10209       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
10210       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
10211       offset++;
10212     }
10213
10214     /* now depending on the sign of the destination */
10215     size = AOP_SIZE(result) - AOP_SIZE(right);
10216     /* if unsigned or not an integral type */
10217     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10218       while (size--)
10219         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10220     } else {
10221       /* we need to extend the sign :( */
10222
10223       if(size == 1) {
10224         /* Save one instruction of casting char to int */
10225         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
10226         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10227         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
10228       } else {
10229         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10230
10231         if(offset)
10232           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10233         else
10234           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10235         
10236         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
10237
10238         while (size--)
10239           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
10240       }
10241     }
10242
10243 release:
10244     pic16_freeAsmop(right,NULL,ic,TRUE);
10245     pic16_freeAsmop(result,NULL,ic,TRUE);
10246
10247 }
10248
10249 /*-----------------------------------------------------------------*/
10250 /* genDjnz - generate decrement & jump if not zero instrucion      */
10251 /*-----------------------------------------------------------------*/
10252 static int genDjnz (iCode *ic, iCode *ifx)
10253 {
10254     symbol *lbl, *lbl1;
10255     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10256
10257     if (!ifx)
10258         return 0;
10259     
10260     /* if the if condition has a false label
10261        then we cannot save */
10262     if (IC_FALSE(ifx))
10263         return 0;
10264
10265     /* if the minus is not of the form 
10266        a = a - 1 */
10267     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10268         !IS_OP_LITERAL(IC_RIGHT(ic)))
10269         return 0;
10270
10271     if (operandLitValue(IC_RIGHT(ic)) != 1)
10272         return 0;
10273
10274     /* if the size of this greater than one then no
10275        saving */
10276     if (getSize(operandType(IC_RESULT(ic))) > 1)
10277         return 0;
10278
10279     /* otherwise we can save BIG */
10280     lbl = newiTempLabel(NULL);
10281     lbl1= newiTempLabel(NULL);
10282
10283     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10284     
10285     if (IS_AOP_PREG(IC_RESULT(ic))) {
10286         pic16_emitcode("dec","%s",
10287                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10288         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10289         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10290     } else {    
10291
10292
10293       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10294       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10295
10296       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10297       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10298
10299     }
10300 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10301 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10302 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10303 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10304
10305     
10306     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10307     ifx->generated = 1;
10308     return 1;
10309 }
10310
10311 /*-----------------------------------------------------------------*/
10312 /* genReceive - generate code for a receive iCode                  */
10313 /*-----------------------------------------------------------------*/
10314 static void genReceive (iCode *ic)
10315 {    
10316         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10317
10318         if (isOperandInFarSpace(IC_RESULT(ic)) && 
10319                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10320                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10321
10322           int size = getSize(operandType(IC_RESULT(ic)));
10323           int offset =  pic16_fReturnSizePic - size;
10324
10325                 while (size--) {
10326                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10327                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10328                         offset++;
10329                 }
10330
10331                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10332
10333                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10334                 size = AOP_SIZE(IC_RESULT(ic));
10335                 offset = 0;
10336                 while (size--) {
10337                         pic16_emitcode ("pop","acc");
10338                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10339                 }
10340         } else {
10341                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
10342
10343                 _G.accInUse++;
10344                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10345                 _G.accInUse--;
10346                 assignResultValue(IC_RESULT(ic));       
10347         }
10348
10349         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10350 }
10351
10352 /*-----------------------------------------------------------------*/
10353 /* genDummyRead - generate code for dummy read of volatiles        */
10354 /*-----------------------------------------------------------------*/
10355 static void
10356 genDummyRead (iCode * ic)
10357 {
10358   pic16_emitcode ("; genDummyRead","");
10359   pic16_emitcode ("; not implemented","");
10360
10361   ic = ic;
10362 }
10363
10364 /*-----------------------------------------------------------------*/
10365 /* genpic16Code - generate code for pic16 based controllers        */
10366 /*-----------------------------------------------------------------*/
10367 /*
10368  * At this point, ralloc.c has gone through the iCode and attempted
10369  * to optimize in a way suitable for a PIC. Now we've got to generate
10370  * PIC instructions that correspond to the iCode.
10371  *
10372  * Once the instructions are generated, we'll pass through both the
10373  * peep hole optimizer and the pCode optimizer.
10374  *-----------------------------------------------------------------*/
10375
10376 void genpic16Code (iCode *lic)
10377 {
10378     iCode *ic;
10379     int cln = 0;
10380
10381     lineHead = lineCurr = NULL;
10382
10383     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10384     pic16_addpBlock(pb);
10385
10386 #if 0
10387     /* if debug information required */
10388     if (options.debug && currFunc) {
10389       if (currFunc) {
10390         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10391         _G.debugLine = 1;
10392         if (IS_STATIC(currFunc->etype)) {
10393           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
10394           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10395         } else {
10396           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
10397           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10398         }
10399         _G.debugLine = 0;
10400       }
10401     }
10402 #endif
10403
10404 //    dumpiCode(lic);
10405
10406     for (ic = lic ; ic ; ic = ic->next ) {
10407
10408 //      fprintf(stderr, "; VR = %c %x\n", ic->op, ic->op);
10409 //      DEBUGpic16_emitcode("; VR", "");
10410       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10411         if ( cln != ic->lineno ) {
10412             if ( options.debug ) {
10413                 _G.debugLine = 1;
10414                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10415                          FileBaseName(ic->filename),ic->lineno,
10416                          ic->level,ic->block);
10417                 _G.debugLine = 0;
10418             }
10419             
10420             if(!options.noCcodeInAsm) {
10421                 pic16_addpCode2pBlock(pb,
10422                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
10423                                 printCLine(ic->filename, ic->lineno)));
10424             }
10425
10426             cln = ic->lineno ;
10427         }
10428         
10429         if(options.iCodeInAsm) {
10430                 /* insert here code to print iCode as comment */
10431                 pic16_emitcomment("; ic:%d: %s", ic->seq, printILine(ic));
10432         }
10433         
10434         /* if the result is marked as
10435            spilt and rematerializable or code for
10436            this has already been generated then
10437            do nothing */
10438         if (resultRemat(ic) || ic->generated ) 
10439             continue ;
10440         
10441         /* depending on the operation */
10442         switch (ic->op) {
10443         case '!' :
10444             pic16_genNot(ic);
10445             break;
10446             
10447         case '~' :
10448             pic16_genCpl(ic);
10449             break;
10450             
10451         case UNARYMINUS:
10452             genUminus (ic);
10453             break;
10454             
10455         case IPUSH:
10456             genIpush (ic);
10457             break;
10458             
10459         case IPOP:
10460             /* IPOP happens only when trying to restore a 
10461                spilt live range, if there is an ifx statement
10462                following this pop then the if statement might
10463                be using some of the registers being popped which
10464                would destroy the contents of the register so
10465                we need to check for this condition and handle it */
10466             if (ic->next            && 
10467                 ic->next->op == IFX &&
10468                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10469                 genIfx (ic->next,ic);
10470             else
10471                 genIpop (ic);
10472             break; 
10473             
10474         case CALL:
10475             genCall (ic);
10476             break;
10477             
10478         case PCALL:
10479             genPcall (ic);
10480             break;
10481             
10482         case FUNCTION:
10483             genFunction (ic);
10484             break;
10485             
10486         case ENDFUNCTION:
10487             genEndFunction (ic);
10488             break;
10489             
10490         case RETURN:
10491             genRet (ic);
10492             break;
10493             
10494         case LABEL:
10495             genLabel (ic);
10496             break;
10497             
10498         case GOTO:
10499             genGoto (ic);
10500             break;
10501             
10502         case '+' :
10503             pic16_genPlus (ic) ;
10504             break;
10505             
10506         case '-' :
10507             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10508                 pic16_genMinus (ic);
10509             break;
10510             
10511         case '*' :
10512             genMult (ic);
10513             break;
10514             
10515         case '/' :
10516             genDiv (ic) ;
10517             break;
10518             
10519         case '%' :
10520             genMod (ic);
10521             break;
10522             
10523         case '>' :
10524             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10525             break;
10526             
10527         case '<' :
10528             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10529             break;
10530             
10531         case LE_OP:
10532         case GE_OP:
10533         case NE_OP:
10534             
10535             /* note these two are xlated by algebraic equivalence
10536                during parsing SDCC.y */
10537             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10538                    "got '>=' or '<=' shouldn't have come here");
10539             break;      
10540             
10541         case EQ_OP:
10542             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10543             break;          
10544             
10545         case AND_OP:
10546             genAndOp (ic);
10547             break;
10548             
10549         case OR_OP:
10550             genOrOp (ic);
10551             break;
10552             
10553         case '^' :
10554             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10555             break;
10556             
10557         case '|' :
10558                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10559             break;
10560             
10561         case BITWISEAND:
10562             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10563             break;
10564             
10565         case INLINEASM:
10566             genInline (ic);
10567             break;
10568             
10569         case RRC:
10570             genRRC (ic);
10571             break;
10572             
10573         case RLC:
10574             genRLC (ic);
10575             break;
10576             
10577         case GETHBIT:
10578             genGetHbit (ic);
10579             break;
10580             
10581         case LEFT_OP:
10582             genLeftShift (ic);
10583             break;
10584             
10585         case RIGHT_OP:
10586             genRightShift (ic);
10587             break;
10588             
10589         case GET_VALUE_AT_ADDRESS:
10590             genPointerGet(ic);
10591             break;
10592             
10593         case '=' :
10594             if (POINTER_SET(ic))
10595                 genPointerSet(ic);
10596             else
10597                 genAssign(ic);
10598             break;
10599             
10600         case IFX:
10601             genIfx (ic,NULL);
10602             break;
10603             
10604         case ADDRESS_OF:
10605             genAddrOf (ic);
10606             break;
10607             
10608         case JUMPTABLE:
10609             genJumpTab (ic);
10610             break;
10611             
10612         case CAST:
10613             genCast (ic);
10614             break;
10615             
10616         case RECEIVE:
10617             genReceive(ic);
10618             break;
10619             
10620         case SEND:
10621             addSet(&_G.sendSet,ic);
10622             break;
10623
10624         case DUMMY_READ_VOLATILE:
10625           genDummyRead (ic);
10626           break;
10627
10628         default :
10629             ic = ic;
10630         }
10631     }
10632
10633
10634     /* now we are ready to call the
10635        peep hole optimizer */
10636     if (!options.nopeep) {
10637       peepHole (&lineHead);
10638     }
10639     /* now do the actual printing */
10640     printLine (lineHead,codeOutFile);
10641
10642 #ifdef PCODE_DEBUG
10643     DFPRINTF((stderr,"printing pBlock\n\n"));
10644     pic16_printpBlock(stdout,pb);
10645 #endif
10646
10647     return;
10648 }
10649