95a8aa91dc078d62e1d9895142379831317f8605
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
30                 Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45 #include "genutils.h"
46 #include "device.h"
47 #include "main.h"
48
49 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
50 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 void pic16_genMult8X8_8 (operand *, operand *,operand *);
52 pCode *pic16_AssembleLine(char *line, int peeps);
53 extern void pic16_printpBlock(FILE *of, pBlock *pb);
54 static asmop *newAsmop (short type);
55 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset);
56 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
57 static void mov2w (asmop *aop, int offset);
58 static int aopIdx (asmop *aop, int offset);
59
60 static int labelOffset=0;
61 extern int pic16_debug_verbose;
62 static int optimized_for_speed = 0;
63 /*
64   hack hack
65
66 */
67
68 /* max_key keeps track of the largest label number used in 
69    a function. This is then used to adjust the label offset
70    for the next function.
71 */
72 static int max_key=0;
73 static int GpsuedoStkPtr=0;
74
75 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
76 unsigned int pic16aopLiteral (value *val, int offset);
77 const char *pic16_AopType(short type);
78 static iCode *ifxForOp ( operand *op, iCode *ic );
79
80 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
81
82 /* this is the down and dirty file with all kinds of 
83    kludgy & hacky stuff. This is what it is all about
84    CODE GENERATION for a specific MCU . some of the
85    routines may be reusable, will have to see */
86
87 static char *zero = "#0x00";
88 static char *one  = "#0x01";
89 static char *spname = "sp";
90
91 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
92 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
93 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
94 static char **fReturn = fReturnpic16;
95
96 static char *accUse[] = {"a","b"};
97
98 //static short rbank = -1;
99
100 static struct {
101     short r0Pushed;
102     short r1Pushed;
103     short accInUse;
104     short inLine;
105     short debugLine;
106     short nRegsSaved;
107     set *sendSet;
108 } _G;
109
110 /* Resolved ifx structure. This structure stores information
111    about an iCode ifx that makes it easier to generate code.
112 */
113 typedef struct resolvedIfx {
114   symbol *lbl;     /* pointer to a label */
115   int condition;   /* true or false ifx */
116   int generated;   /* set true when the code associated with the ifx
117                     * is generated */
118 } resolvedIfx;
119
120 extern int pic16_ptrRegReq ;
121 extern int pic16_nRegs;
122 extern FILE *codeOutFile;
123 static void saverbank (int, iCode *,bool);
124
125 static lineNode *lineHead = NULL;
126 static lineNode *lineCurr = NULL;
127
128 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
129 0xE0, 0xC0, 0x80, 0x00};
130 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
131 0x07, 0x03, 0x01, 0x00};
132
133 static  pBlock *pb;
134
135 /*-----------------------------------------------------------------*/
136 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
137 /*                 exponent of 2 is returned, otherwise -1 is      */
138 /*                 returned.                                       */
139 /* note that this is similar to the function `powof2' in SDCCsymt  */
140 /* if(n == 2^y)                                                    */
141 /*   return y;                                                     */
142 /* return -1;                                                      */
143 /*-----------------------------------------------------------------*/
144 static int my_powof2 (unsigned long num)
145 {
146   if(num) {
147     if( (num & (num-1)) == 0) {
148       int nshifts = -1;
149       while(num) {
150         num>>=1;
151         nshifts++;
152       }
153       return nshifts;
154     }
155   }
156
157   return -1;
158 }
159
160 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
161 {
162
163   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
164                        line_no,
165                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
166                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
167                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
168                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
169                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
170                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
171                        ((result) ? AOP_SIZE(result) : 0));
172
173 }
174
175 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
176 {
177
178   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
179                        line_no,
180                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
181                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
182                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
183                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
184                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
185                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
186
187 }
188
189 void pic16_emitcomment (char *fmt, ...)
190 {
191     va_list ap;
192     char lb[INITIAL_INLINEASM];  
193     char *lbp = lb;
194
195     if(!pic16_debug_verbose)
196       return;
197
198     va_start(ap,fmt);   
199
200     lb[0] = ';';
201     vsprintf(lb+1,fmt,ap);
202
203     while (isspace(*lbp)) lbp++;
204
205     if (lbp && *lbp) 
206         lineCurr = (lineCurr ?
207                     connectLine(lineCurr,newLineNode(lb)) :
208                     (lineHead = newLineNode(lb)));
209     lineCurr->isInline = _G.inLine;
210     lineCurr->isDebug  = _G.debugLine;
211
212     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
213     va_end(ap);
214
215 //      fprintf(stderr, "%s\n", lb);
216 }
217
218 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
219 {
220     va_list ap;
221     char lb[INITIAL_INLINEASM];  
222     char *lbp = lb;
223
224     if(!pic16_debug_verbose)
225       return;
226
227     va_start(ap,fmt);   
228
229     if (inst && *inst) {
230         if (fmt && *fmt)
231             sprintf(lb,"%s\t",inst);
232         else
233             sprintf(lb,"%s",inst);
234         vsprintf(lb+(strlen(lb)),fmt,ap);
235     }  else
236         vsprintf(lb,fmt,ap);
237
238     while (isspace(*lbp)) lbp++;
239
240     if (lbp && *lbp) 
241         lineCurr = (lineCurr ?
242                     connectLine(lineCurr,newLineNode(lb)) :
243                     (lineHead = newLineNode(lb)));
244     lineCurr->isInline = _G.inLine;
245     lineCurr->isDebug  = _G.debugLine;
246
247     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
248     va_end(ap);
249
250 //      fprintf(stderr, "%s\n", lb);
251 }
252
253 void pic16_emitpLabel(int key)
254 {
255   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
256 }
257
258 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
259 {
260
261   if(pcop)
262     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
263   else
264     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
265     
266 //    fprintf(stderr, "%s\n", pcop->name);
267 }
268
269 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
270 {
271
272   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
273
274 }
275
276
277 #if 1
278 #define pic16_emitcode  DEBUGpic16_emitcode
279 #else
280 /*-----------------------------------------------------------------*/
281 /* pic16_emitcode - writes the code into a file : for now it is simple    */
282 /*-----------------------------------------------------------------*/
283 void pic16_emitcode (char *inst,char *fmt, ...)
284 {
285     va_list ap;
286     char lb[INITIAL_INLINEASM];  
287     char *lbp = lb;
288
289     va_start(ap,fmt);   
290
291     if (inst && *inst) {
292         if (fmt && *fmt)
293             sprintf(lb,"%s\t",inst);
294         else
295             sprintf(lb,"%s",inst);
296         vsprintf(lb+(strlen(lb)),fmt,ap);
297     }  else
298         vsprintf(lb,fmt,ap);
299
300     while (isspace(*lbp)) lbp++;
301
302     if (lbp && *lbp) 
303         lineCurr = (lineCurr ?
304                     connectLine(lineCurr,newLineNode(lb)) :
305                     (lineHead = newLineNode(lb)));
306     lineCurr->isInline = _G.inLine;
307     lineCurr->isDebug  = _G.debugLine;
308
309 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
310
311 //    if(pic16_debug_verbose)
312 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
313
314     va_end(ap);
315 }
316 #endif
317
318
319 /*-----------------------------------------------------------------*/
320 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
321 /*-----------------------------------------------------------------*/
322 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
323 {
324     bool r0iu = FALSE , r1iu = FALSE;
325     bool r0ou = FALSE , r1ou = FALSE;
326
327         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
328
329     /* the logic: if r0 & r1 used in the instruction
330     then we are in trouble otherwise */
331
332     /* first check if r0 & r1 are used by this
333     instruction, in which case we are in trouble */
334     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
335         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
336     {
337         goto endOfWorld;      
338     }
339
340     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
341     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
342
343     /* if no usage of r0 then return it */
344     if (!r0iu && !r0ou) {
345         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
346         (*aopp)->type = AOP_R0;
347         
348         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
349     }
350
351     /* if no usage of r1 then return it */
352     if (!r1iu && !r1ou) {
353         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
354         (*aopp)->type = AOP_R1;
355
356         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
357     }    
358
359     /* now we know they both have usage */
360     /* if r0 not used in this instruction */
361     if (!r0iu) {
362         /* push it if not already pushed */
363         if (!_G.r0Pushed) {
364           //pic16_emitcode ("push","%s",
365           //          pic16_regWithIdx(R0_IDX)->dname);
366             _G.r0Pushed++ ;
367         }
368         
369         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
370         (*aopp)->type = AOP_R0;
371
372         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
373     }
374
375     /* if r1 not used then */
376
377     if (!r1iu) {
378         /* push it if not already pushed */
379         if (!_G.r1Pushed) {
380           //pic16_emitcode ("push","%s",
381           //          pic16_regWithIdx(R1_IDX)->dname);
382             _G.r1Pushed++ ;
383         }
384         
385         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
386         (*aopp)->type = AOP_R1;
387         return pic16_regWithIdx(R1_IDX);
388     }
389
390 endOfWorld :
391     /* I said end of world but not quite end of world yet */
392     /* if this is a result then we can push it on the stack*/
393     if (result) {
394         (*aopp)->type = AOP_STK;    
395         return NULL;
396     }
397
398     /* other wise this is true end of the world */
399     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
400            "getFreePtr should never reach here");
401     exit(0);
402 }
403
404 /*-----------------------------------------------------------------*/
405 /* newAsmop - creates a new asmOp                                  */
406 /*-----------------------------------------------------------------*/
407 static asmop *newAsmop (short type)
408 {
409     asmop *aop;
410
411     aop = Safe_calloc(1,sizeof(asmop));
412     aop->type = type;
413     return aop;
414 }
415
416 static void genSetDPTR(int n)
417 {
418     if (!n)
419     {
420         pic16_emitcode(";", "Select standard DPTR");
421         pic16_emitcode("mov", "dps, #0x00");
422     }
423     else
424     {
425         pic16_emitcode(";", "Select alternate DPTR");
426         pic16_emitcode("mov", "dps, #0x01");
427     }
428 }
429
430 /*-----------------------------------------------------------------*/
431 /* resolveIfx - converts an iCode ifx into a form more useful for  */
432 /*              generating code                                    */
433 /*-----------------------------------------------------------------*/
434 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
435 {
436   if(!resIfx) 
437     return;
438
439   //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
440
441   resIfx->condition = 1;    /* assume that the ifx is true */
442   resIfx->generated = 0;    /* indicate that the ifx has not been used */
443
444   if(!ifx) {
445     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
446 /*
447     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
448                         __FUNCTION__,__LINE__,resIfx->lbl->key);
449 */
450   } else {
451     if(IC_TRUE(ifx)) {
452       resIfx->lbl = IC_TRUE(ifx);
453     } else {
454       resIfx->lbl = IC_FALSE(ifx);
455       resIfx->condition = 0;
456     }
457 /*
458     if(IC_TRUE(ifx)) 
459       DEBUGpic16_emitcode("; ***","ifx true is non-null");
460     if(IC_FALSE(ifx)) 
461       DEBUGpic16_emitcode("; ***","ifx false is non-null");
462 */
463   }
464
465   //  DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
466
467 }
468 #if 0
469 /*-----------------------------------------------------------------*/
470 /* pointerCode - returns the code for a pointer type               */
471 /*-----------------------------------------------------------------*/
472 static int pointerCode (sym_link *etype)
473 {
474
475     return PTR_TYPE(SPEC_OCLS(etype));
476
477 }
478 #endif
479 /*-----------------------------------------------------------------*/
480 /* aopForSym - for a true symbol                                   */
481 /*-----------------------------------------------------------------*/
482 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
483 {
484     asmop *aop;
485     memmap *space= SPEC_OCLS(sym->etype);
486
487     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
488     /* if already has one */
489     if (sym->aop) {
490             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
491         return sym->aop;
492     }
493
494     /* assign depending on the storage class */
495     /* if it is on the stack or indirectly addressable */
496     /* space we need to assign either r0 or r1 to it   */    
497     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
498         sym->aop = aop = newAsmop(0);
499         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
500         aop->size = getSize(sym->type);
501
502         /* now assign the address of the variable to 
503         the pointer register */
504         if (aop->type != AOP_STK) {
505
506             if (sym->onStack) {
507                     if ( _G.accInUse )
508                         pic16_emitcode("push","acc");
509
510                     pic16_emitcode("mov","a,_bp");
511                     pic16_emitcode("add","a,#0x%02x",
512                              ((sym->stack < 0) ?
513                               ((char)(sym->stack - _G.nRegsSaved )) :
514                               ((char)sym->stack)) & 0xff);
515                     pic16_emitcode("mov","%s,a",
516                              aop->aopu.aop_ptr->name);
517
518                     if ( _G.accInUse )
519                         pic16_emitcode("pop","acc");
520             } else
521                 pic16_emitcode("mov","%s,#%s",
522                          aop->aopu.aop_ptr->name,
523                          sym->rname);
524             aop->paged = space->paged;
525         } else
526             aop->aopu.aop_stk = sym->stack;
527         return aop;
528     }
529     
530     if (sym->onStack && options.stack10bit)
531     {
532         /* It's on the 10 bit stack, which is located in
533          * far data space.
534          */
535          
536       //DEBUGpic16_emitcode(";","%d",__LINE__);
537
538         if ( _G.accInUse )
539                 pic16_emitcode("push","acc");
540
541         pic16_emitcode("mov","a,_bp");
542         pic16_emitcode("add","a,#0x%02x",
543                  ((sym->stack < 0) ?
544                    ((char)(sym->stack - _G.nRegsSaved )) :
545                    ((char)sym->stack)) & 0xff);
546         
547         genSetDPTR(1);
548         pic16_emitcode ("mov","dpx1,#0x40");
549         pic16_emitcode ("mov","dph1,#0x00");
550         pic16_emitcode ("mov","dpl1, a");
551         genSetDPTR(0);
552         
553         if ( _G.accInUse )
554             pic16_emitcode("pop","acc");
555             
556         sym->aop = aop = newAsmop(AOP_DPTR2);
557         aop->size = getSize(sym->type); 
558         return aop;
559     }
560
561     //DEBUGpic16_emitcode(";","%d",__LINE__);
562     /* if in bit space */
563     if (IN_BITSPACE(space)) {
564         sym->aop = aop = newAsmop (AOP_CRY);
565         aop->aopu.aop_dir = sym->rname ;
566         aop->size = getSize(sym->type);
567         //DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
568         return aop;
569     }
570     /* if it is in direct space */
571     if (IN_DIRSPACE(space)) {
572         sym->aop = aop = newAsmop (AOP_DIR);
573         aop->aopu.aop_dir = sym->rname ;
574         aop->size = getSize(sym->type);
575         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
576         return aop;
577     }
578
579     /* special case for a function */
580     if (IS_FUNC(sym->type)) {   
581         sym->aop = aop = newAsmop(AOP_IMMD);    
582         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
583         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
584         strcpy(aop->aopu.aop_immd,sym->rname);
585         aop->size = FPTRSIZE; 
586         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
587         return aop;
588     }
589
590
591     /* only remaining is far space */
592     /* in which case DPTR gets the address */
593     sym->aop = aop = newAsmop(AOP_PCODE);
594
595     aop->aopu.pcop = pic16_popGetImmd(sym->rname,0,0);
596     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
597     PCOI(aop->aopu.pcop)->index = 0;
598
599     DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
600                         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
601
602     pic16_allocDirReg (IC_LEFT(ic));
603
604     aop->size = FPTRSIZE; 
605 /*
606     DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
607     sym->aop = aop = newAsmop(AOP_DPTR);
608     pic16_emitcode ("mov","dptr,#%s", sym->rname);
609     aop->size = getSize(sym->type);
610
611     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
612 */
613
614     /* if it is in code space */
615     if (IN_CODESPACE(space))
616         aop->code = 1;
617
618     return aop;     
619 }
620
621 /*-----------------------------------------------------------------*/
622 /* aopForRemat - rematerialzes an object                           */
623 /*-----------------------------------------------------------------*/
624 static asmop *aopForRemat (operand *op) // x symbol *sym)
625 {
626   symbol *sym = OP_SYMBOL(op);
627   iCode *ic = NULL;
628   asmop *aop = newAsmop(AOP_PCODE);
629   int val = 0;
630   int offset = 0;
631
632   ic = sym->rematiCode;
633
634   DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
635   if(IS_OP_POINTER(op)) {
636     DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
637   }
638   for (;;) {
639     if (ic->op == '+') {
640       val += (int) operandLitValue(IC_RIGHT(ic));
641     } else if (ic->op == '-') {
642       val -= (int) operandLitValue(IC_RIGHT(ic));
643     } else
644       break;
645         
646     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
647   }
648
649   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
650   aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
651 #if 0
652   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
653 #else
654   PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
655 #endif
656   PCOI(aop->aopu.pcop)->index = val;
657
658   DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
659                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
660 #if 0
661                       val, IS_PTR_CONST(operandType(op)));
662 #else
663                       val, IS_CODEPTR(operandType(op)));
664 #endif
665
666   //    DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
667
668   pic16_allocDirReg (IC_LEFT(ic));
669
670   return aop;        
671 }
672
673 static int aopIdx (asmop *aop, int offset)
674 {
675   if(!aop)
676     return -1;
677
678   if(aop->type !=  AOP_REG)
679     return -2;
680         
681   return aop->aopu.aop_reg[offset]->rIdx;
682
683 }
684 /*-----------------------------------------------------------------*/
685 /* regsInCommon - two operands have some registers in common       */
686 /*-----------------------------------------------------------------*/
687 static bool regsInCommon (operand *op1, operand *op2)
688 {
689     symbol *sym1, *sym2;
690     int i;
691
692     /* if they have registers in common */
693     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
694         return FALSE ;
695
696     sym1 = OP_SYMBOL(op1);
697     sym2 = OP_SYMBOL(op2);
698
699     if (sym1->nRegs == 0 || sym2->nRegs == 0)
700         return FALSE ;
701
702     for (i = 0 ; i < sym1->nRegs ; i++) {
703         int j;
704         if (!sym1->regs[i])
705             continue ;
706
707         for (j = 0 ; j < sym2->nRegs ;j++ ) {
708             if (!sym2->regs[j])
709                 continue ;
710
711             if (sym2->regs[j] == sym1->regs[i])
712                 return TRUE ;
713         }
714     }
715
716     return FALSE ;
717 }
718
719 /*-----------------------------------------------------------------*/
720 /* operandsEqu - equivalent                                        */
721 /*-----------------------------------------------------------------*/
722 static bool operandsEqu ( operand *op1, operand *op2)
723 {
724     symbol *sym1, *sym2;
725
726     /* if they not symbols */
727     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
728         return FALSE;
729
730     sym1 = OP_SYMBOL(op1);
731     sym2 = OP_SYMBOL(op2);
732
733     /* if both are itemps & one is spilt
734        and the other is not then false */
735     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
736         sym1->isspilt != sym2->isspilt )
737         return FALSE ;
738
739     /* if they are the same */
740     if (sym1 == sym2)
741         return TRUE ;
742
743     if (strcmp(sym1->rname,sym2->rname) == 0)
744         return TRUE;
745
746
747     /* if left is a tmp & right is not */
748     if (IS_ITEMP(op1)  && 
749         !IS_ITEMP(op2) &&
750         sym1->isspilt  &&
751         (sym1->usl.spillLoc == sym2))
752         return TRUE;
753
754     if (IS_ITEMP(op2)  && 
755         !IS_ITEMP(op1) &&
756         sym2->isspilt  &&
757         sym1->level > 0 &&
758         (sym2->usl.spillLoc == sym1))
759         return TRUE ;
760
761     return FALSE ;
762 }
763
764 /*-----------------------------------------------------------------*/
765 /* pic16_sameRegs - two asmops have the same registers                   */
766 /*-----------------------------------------------------------------*/
767 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
768 {
769     int i;
770
771     if (aop1 == aop2)
772         return TRUE ;
773
774     if (aop1->type != AOP_REG ||
775         aop2->type != AOP_REG )
776         return FALSE ;
777
778     if (aop1->size != aop2->size )
779         return FALSE ;
780
781     for (i = 0 ; i < aop1->size ; i++ )
782         if (aop1->aopu.aop_reg[i] !=
783             aop2->aopu.aop_reg[i] )
784             return FALSE ;
785
786     return TRUE ;
787 }
788
789 /*-----------------------------------------------------------------*/
790 /* pic16_aopOp - allocates an asmop for an operand  :                    */
791 /*-----------------------------------------------------------------*/
792 void pic16_aopOp (operand *op, iCode *ic, bool result)
793 {
794     asmop *aop;
795     symbol *sym;
796     int i;
797
798     if (!op)
799         return ;
800
801 //      DEBUGpic16_emitcode(";","%d",__LINE__);
802
803     /* if this a literal */
804     if (IS_OP_LITERAL(op)) {
805         op->aop = aop = newAsmop(AOP_LIT);
806         aop->aopu.aop_lit = op->operand.valOperand;
807         aop->size = getSize(operandType(op));
808         return;
809     }
810
811     {
812       sym_link *type = operandType(op);
813 #if 0
814       if(IS_PTR_CONST(type))
815 #else
816       if(IS_CODEPTR(type))
817 #endif
818         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
819     }
820
821     /* if already has a asmop then continue */
822     if (op->aop)
823         return ;
824
825     /* if the underlying symbol has a aop */
826     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
827       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
828         op->aop = OP_SYMBOL(op)->aop;
829         return;
830     }
831
832     /* if this is a true symbol */
833     if (IS_TRUE_SYMOP(op)) {    
834         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
835       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
836       return ;
837     }
838
839     /* this is a temporary : this has
840     only four choices :
841     a) register
842     b) spillocation
843     c) rematerialize 
844     d) conditional   
845     e) can be a return use only */
846
847     sym = OP_SYMBOL(op);
848
849         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
850     /* if the type is a conditional */
851     if (sym->regType == REG_CND) {
852         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
853         aop->size = 0;
854         return;
855     }
856
857     /* if it is spilt then two situations
858     a) is rematerialize 
859     b) has a spill location */
860     if (sym->isspilt || sym->nRegs == 0) {
861
862       DEBUGpic16_emitcode(";","%d",__LINE__);
863         /* rematerialize it NOW */
864         if (sym->remat) {
865
866             sym->aop = op->aop = aop =
867                                       aopForRemat (op);
868             aop->size = getSize(sym->type);
869             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
870             return;
871         }
872
873         if (sym->accuse) {
874             int i;
875             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
876             aop->size = getSize(sym->type);
877             for ( i = 0 ; i < 2 ; i++ )
878                 aop->aopu.aop_str[i] = accUse[i];
879             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
880             return;  
881         }
882
883         if (sym->ruonly ) {
884           /*
885           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
886           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
887           //pic16_allocDirReg (IC_LEFT(ic));
888           aop->size = getSize(sym->type);
889           */
890
891           unsigned i;
892
893           aop = op->aop = sym->aop = newAsmop(AOP_STR);
894           aop->size = getSize(sym->type);
895           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
896             aop->aopu.aop_str[i] = fReturn[i];
897
898           DEBUGpic16_emitcode(";","%d",__LINE__);
899           return;
900         }
901
902         /* else spill location  */
903         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
904             /* force a new aop if sizes differ */
905             sym->usl.spillLoc->aop = NULL;
906         }
907         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
908                             __FUNCTION__,__LINE__,
909                             sym->usl.spillLoc->rname,
910                             sym->rname, sym->usl.spillLoc->offset);
911
912         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
913         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
914         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
915                                           getSize(sym->type), 
916                                           sym->usl.spillLoc->offset);
917         aop->size = getSize(sym->type);
918
919         return;
920     }
921
922     {
923       sym_link *type = operandType(op);
924 #if 0
925       if(IS_PTR_CONST(type)) 
926 #else
927       if(IS_CODEPTR(type)) 
928 #endif
929         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
930     }
931
932     /* must be in a register */
933     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
934     sym->aop = op->aop = aop = newAsmop(AOP_REG);
935     aop->size = sym->nRegs;
936     for ( i = 0 ; i < sym->nRegs ;i++)
937         aop->aopu.aop_reg[i] = sym->regs[i];
938 }
939
940 /*-----------------------------------------------------------------*/
941 /* pic16_freeAsmop - free up the asmop given to an operand               */
942 /*----------------------------------------------------------------*/
943 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
944 {   
945     asmop *aop ;
946
947     if (!op)
948         aop = aaop;
949     else 
950         aop = op->aop;
951
952     if (!aop)
953         return ;
954
955     if (aop->freed)
956         goto dealloc; 
957
958     aop->freed = 1;
959
960     /* depending on the asmop type only three cases need work AOP_RO
961        , AOP_R1 && AOP_STK */
962 #if 0
963     switch (aop->type) {
964         case AOP_R0 :
965             if (_G.r0Pushed ) {
966                 if (pop) {
967                     pic16_emitcode ("pop","ar0");     
968                     _G.r0Pushed--;
969                 }
970             }
971             bitVectUnSetBit(ic->rUsed,R0_IDX);
972             break;
973
974         case AOP_R1 :
975             if (_G.r1Pushed ) {
976                 if (pop) {
977                     pic16_emitcode ("pop","ar1");
978                     _G.r1Pushed--;
979                 }
980             }
981             bitVectUnSetBit(ic->rUsed,R1_IDX);          
982             break;
983
984         case AOP_STK :
985         {
986             int sz = aop->size;    
987             int stk = aop->aopu.aop_stk + aop->size;
988             bitVectUnSetBit(ic->rUsed,R0_IDX);
989             bitVectUnSetBit(ic->rUsed,R1_IDX);          
990
991             getFreePtr(ic,&aop,FALSE);
992             
993             if (options.stack10bit)
994             {
995                 /* I'm not sure what to do here yet... */
996                 /* #STUB */
997                 fprintf(stderr, 
998                         "*** Warning: probably generating bad code for "
999                         "10 bit stack mode.\n");
1000             }
1001             
1002             if (stk) {
1003                 pic16_emitcode ("mov","a,_bp");
1004                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1005                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1006             } else {
1007                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1008             }
1009
1010             while (sz--) {
1011                 pic16_emitcode("pop","acc");
1012                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1013                 if (!sz) break;
1014                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1015             }
1016             op->aop = aop;
1017             pic16_freeAsmop(op,NULL,ic,TRUE);
1018             if (_G.r0Pushed) {
1019                 pic16_emitcode("pop","ar0");
1020                 _G.r0Pushed--;
1021             }
1022
1023             if (_G.r1Pushed) {
1024                 pic16_emitcode("pop","ar1");
1025                 _G.r1Pushed--;
1026             }       
1027         }
1028     }
1029 #endif
1030
1031 dealloc:
1032     /* all other cases just dealloc */
1033     if (op ) {
1034         op->aop = NULL;
1035         if (IS_SYMOP(op)) {
1036             OP_SYMBOL(op)->aop = NULL;    
1037             /* if the symbol has a spill */
1038             if (SPIL_LOC(op))
1039                 SPIL_LOC(op)->aop = NULL;
1040         }
1041     }
1042 }
1043
1044 /*-----------------------------------------------------------------*/
1045 /* pic16_aopGet - for fetching value of the aop                          */
1046 /*-----------------------------------------------------------------*/
1047 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1048 {
1049     char *s = buffer ;
1050     char *rs;
1051
1052     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1053     /* offset is greater than
1054     size then zero */
1055     if (offset > (aop->size - 1) &&
1056         aop->type != AOP_LIT)
1057         return zero;
1058
1059     /* depending on type */
1060     switch (aop->type) {
1061         
1062     case AOP_R0:
1063     case AOP_R1:
1064         DEBUGpic16_emitcode(";","%d",__LINE__);
1065         /* if we need to increment it */       
1066         while (offset > aop->coff) {        
1067             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1068             aop->coff++;
1069         }
1070         
1071         while (offset < aop->coff) {
1072             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1073             aop->coff--;
1074         }
1075         
1076         aop->coff = offset ;
1077         if (aop->paged) {
1078             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1079             return (dname ? "acc" : "a");
1080         }       
1081         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1082         rs = Safe_calloc(1,strlen(s)+1);
1083         strcpy(rs,s);   
1084         return rs;
1085         
1086     case AOP_DPTR:
1087     case AOP_DPTR2:
1088         DEBUGpic16_emitcode(";","%d",__LINE__);
1089     if (aop->type == AOP_DPTR2)
1090     {
1091         genSetDPTR(1);
1092     }
1093     
1094         while (offset > aop->coff) {
1095             pic16_emitcode ("inc","dptr");
1096             aop->coff++;
1097         }
1098         
1099         while (offset < aop->coff) {        
1100             pic16_emitcode("lcall","__decdptr");
1101             aop->coff--;
1102         }
1103         
1104         aop->coff = offset;
1105         if (aop->code) {
1106             pic16_emitcode("clr","a");
1107             pic16_emitcode("movc","a,@a+dptr");
1108         }
1109     else {
1110             pic16_emitcode("movx","a,@dptr");
1111     }
1112             
1113     if (aop->type == AOP_DPTR2)
1114     {
1115         genSetDPTR(0);
1116     }
1117             
1118     return (dname ? "acc" : "a");
1119         
1120         
1121     case AOP_IMMD:
1122         if (bit16) 
1123             sprintf (s,"%s",aop->aopu.aop_immd);
1124         else
1125             if (offset) 
1126                 sprintf(s,"(%s >> %d)",
1127                         aop->aopu.aop_immd,
1128                         offset*8);
1129             else
1130                 sprintf(s,"%s",
1131                         aop->aopu.aop_immd);
1132         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1133         rs = Safe_calloc(1,strlen(s)+1);
1134         strcpy(rs,s);   
1135         return rs;
1136         
1137     case AOP_DIR:
1138       if (offset) {
1139         sprintf(s,"(%s + %d)",
1140                 aop->aopu.aop_dir,
1141                 offset);
1142         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1143       } else
1144             sprintf(s,"%s",aop->aopu.aop_dir);
1145         rs = Safe_calloc(1,strlen(s)+1);
1146         strcpy(rs,s);   
1147         return rs;
1148         
1149     case AOP_REG:
1150       //if (dname) 
1151       //    return aop->aopu.aop_reg[offset]->dname;
1152       //else
1153             return aop->aopu.aop_reg[offset]->name;
1154         
1155     case AOP_CRY:
1156       //pic16_emitcode(";","%d",__LINE__);
1157       return aop->aopu.aop_dir;
1158         
1159     case AOP_ACC:
1160         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1161         return "AOP_accumulator_bug";
1162
1163     case AOP_LIT:
1164         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1165         rs = Safe_calloc(1,strlen(s)+1);
1166         strcpy(rs,s);   
1167         return rs;
1168         
1169     case AOP_STR:
1170         aop->coff = offset ;
1171         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1172             dname)
1173             return "acc";
1174         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1175         
1176         return aop->aopu.aop_str[offset];
1177         
1178     case AOP_PCODE:
1179       {
1180         pCodeOp *pcop = aop->aopu.pcop;
1181         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1182         if(pcop->name) {
1183           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1184           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1185           sprintf(s,"%s", pcop->name);
1186         } else
1187           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1188
1189       }
1190       rs = Safe_calloc(1,strlen(s)+1);
1191       strcpy(rs,s);   
1192       return rs;
1193
1194     }
1195
1196     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1197            "aopget got unsupported aop->type");
1198     exit(0);
1199 }
1200
1201
1202 /*-----------------------------------------------------------------*/
1203 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1204 /*-----------------------------------------------------------------*/
1205 pCodeOp *pic16_popGetTempReg(void)
1206 {
1207
1208   pCodeOp *pcop;
1209
1210   pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1211   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1212     PCOR(pcop)->r->wasUsed=1;
1213     PCOR(pcop)->r->isFree=0;
1214   }
1215
1216   return pcop;
1217 }
1218
1219 /*-----------------------------------------------------------------*/
1220 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1221 /*-----------------------------------------------------------------*/
1222 void pic16_popReleaseTempReg(pCodeOp *pcop)
1223 {
1224
1225   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1226     PCOR(pcop)->r->isFree = 1;
1227
1228 }
1229 /*-----------------------------------------------------------------*/
1230 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1231 /*-----------------------------------------------------------------*/
1232 pCodeOp *pic16_popGetLabel(unsigned int key)
1233 {
1234
1235   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1236
1237   if(key>max_key)
1238     max_key = key;
1239
1240   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1241 }
1242
1243 /*-----------------------------------------------------------------*/
1244 /* pic16_popCopyReg - copy a pcode operator                              */
1245 /*-----------------------------------------------------------------*/
1246 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1247 {
1248   pCodeOpReg *pcor;
1249
1250   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1251   pcor->pcop.type = pc->pcop.type;
1252   if(pc->pcop.name) {
1253     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1254       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1255   } else
1256     pcor->pcop.name = NULL;
1257
1258   pcor->r = pc->r;
1259   pcor->rIdx = pc->rIdx;
1260   pcor->r->wasUsed=1;
1261
1262   //DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1263
1264   return PCOP(pcor);
1265 }
1266
1267 /*-----------------------------------------------------------------*/
1268 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1269 /*-----------------------------------------------------------------*/
1270 pCodeOp *pic16_popGetLit(unsigned int lit)
1271 {
1272   return pic16_newpCodeOpLit(lit);
1273 }
1274
1275 /*-----------------------------------------------------------------*/
1276 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1277 /*-----------------------------------------------------------------*/
1278 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1279 {
1280   return pic16_newpCodeOpLit2(lit, arg2);
1281 }
1282
1283
1284 /*-----------------------------------------------------------------*/
1285 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1286 /*-----------------------------------------------------------------*/
1287 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1288 {
1289
1290   return pic16_newpCodeOpImmd(name, offset,index, 0);
1291 }
1292
1293
1294 /*-----------------------------------------------------------------*/
1295 /* pic16_popGet - asm operator to pcode operator conversion              */
1296 /*-----------------------------------------------------------------*/
1297 pCodeOp *pic16_popGetWithString(char *str)
1298 {
1299   pCodeOp *pcop;
1300
1301
1302   if(!str) {
1303     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1304     exit (1);
1305   }
1306
1307   pcop = pic16_newpCodeOp(str,PO_STR);
1308
1309   return pcop;
1310 }
1311
1312 /*-----------------------------------------------------------------*/
1313 /* pic16_popRegFromString -                                        */
1314 /*-----------------------------------------------------------------*/
1315 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1316 {
1317
1318   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1319   pcop->type = PO_DIR;
1320
1321   DEBUGpic16_emitcode(";","%d %s %s",__LINE__, __FUNCTION__, str);
1322 //  fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1323
1324   if(!str)
1325     str = "BAD_STRING";
1326
1327   pcop->name = Safe_calloc(1,strlen(str)+1);
1328   strcpy(pcop->name,str);
1329
1330   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1331
1332   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1333   if(PCOR(pcop)->r == NULL) {
1334 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1335 //              __FUNCTION__, __LINE__, str, size, offset);
1336     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1337
1338         //fprintf(stderr, "allocating new register -> %s\n", str);
1339
1340     DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1341   } else {
1342     DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1343   }
1344   PCOR(pcop)->instance = offset;
1345
1346   return pcop;
1347 }
1348
1349 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1350 {
1351   pCodeOp *pcop;
1352
1353 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1354
1355         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1356         PCOR(pcop)->rIdx = rIdx;
1357         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1358         PCOR(pcop)->r->isFree = 0;
1359         PCOR(pcop)->r->wasUsed = 1;
1360
1361         pcop->type = PCOR(pcop)->r->pc_type;
1362
1363   return pcop;
1364 }
1365
1366 /*---------------------------------------------------------------------------------*/
1367 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1368 /*                 VR 030601                                                       */
1369 /*---------------------------------------------------------------------------------*/
1370 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1371 {
1372   pCodeOpReg2 *pcop2;
1373   pCodeOp *temp;
1374   
1375         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1376
1377         /* comment the following check, so errors to throw up */
1378 //      if(!pcop2)return NULL;
1379
1380         temp = pic16_popGet(aop_dst, offset);
1381         pcop2->pcop2 = temp;
1382         
1383   return PCOP(pcop2);
1384 }
1385
1386
1387
1388 /*--------------------------------------------------------------------------------.-*/
1389 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1390 /*                  VR 030601 , adapted by Hans Dorn                                */
1391 /*--------------------------------------------------------------------------------.-*/
1392 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1393 {
1394         pCodeOpReg2 *pcop2;
1395  
1396         pcop2 = (pCodeOpReg2 *) src;
1397         pcop2->pcop2 = dst;
1398         
1399         return PCOP(pcop2);
1400 }
1401
1402
1403
1404 /*---------------------------------------------------------------------------------*/
1405 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1406 /*                     movff instruction                                           */
1407 /*---------------------------------------------------------------------------------*/
1408 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1409 {
1410   pCodeOpReg2 *pcop2;
1411
1412         if(!noalloc) {
1413                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1414                 pcop2->pcop2 = pic16_popCopyReg(dst);
1415         } else {
1416                 /* the pCodeOp may be already allocated */
1417                 pcop2 = (pCodeOpReg2 *)(src);
1418                 pcop2->pcop2 = (pCodeOp *)(dst);
1419         }
1420
1421   return PCOP(pcop2);
1422 }
1423
1424
1425 /*-----------------------------------------------------------------*/
1426 /* pic16_popGet - asm operator to pcode operator conversion              */
1427 /*-----------------------------------------------------------------*/
1428 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1429 {
1430   //char *s = buffer ;
1431     //char *rs;
1432
1433     pCodeOp *pcop;
1434
1435     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1436     /* offset is greater than
1437     size then zero */
1438
1439     if (offset > (aop->size - 1) &&
1440         aop->type != AOP_LIT)
1441       return NULL;  //zero;
1442
1443     /* depending on type */
1444     switch (aop->type) {
1445         
1446     case AOP_R0:
1447     case AOP_R1:
1448     case AOP_DPTR:
1449     case AOP_DPTR2:
1450     case AOP_ACC:
1451         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1452         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1453         return NULL;
1454         
1455     case AOP_IMMD:
1456       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1457       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1458
1459     case AOP_DIR:
1460       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1461       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1462         
1463     case AOP_REG:
1464       {
1465         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1466
1467         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1468         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1469         PCOR(pcop)->rIdx = rIdx;
1470         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1471         PCOR(pcop)->r->wasUsed=1;
1472         PCOR(pcop)->r->isFree=0;
1473
1474         PCOR(pcop)->instance = offset;
1475         pcop->type = PCOR(pcop)->r->pc_type;
1476         //rs = aop->aopu.aop_reg[offset]->name;
1477         //DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1478         return pcop;
1479       }
1480
1481     case AOP_CRY:
1482         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1483
1484       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1485       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1486       //if(PCOR(pcop)->r == NULL)
1487       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1488       return pcop;
1489         
1490     case AOP_LIT:
1491         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1492       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1493
1494     case AOP_STR:
1495       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1496       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1497
1498       /*
1499       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1500       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1501       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1502       pcop->type = PCOR(pcop)->r->pc_type;
1503       pcop->name = PCOR(pcop)->r->name;
1504
1505       return pcop;
1506       */
1507
1508     case AOP_PCODE:
1509       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s",pic16_pCodeOpType(aop->aopu.pcop),
1510                           __LINE__, 
1511                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1512       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1513       PCOI(pcop)->offset = offset;
1514       return pcop;
1515     }
1516
1517     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1518            "pic16_popGet got unsupported aop->type");
1519     exit(0);
1520 }
1521 /*-----------------------------------------------------------------*/
1522 /* pic16_aopPut - puts a string for a aop                                */
1523 /*-----------------------------------------------------------------*/
1524 void pic16_aopPut (asmop *aop, char *s, int offset)
1525 {
1526     char *d = buffer ;
1527     symbol *lbl ;
1528
1529     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1530
1531     if (aop->size && offset > ( aop->size - 1)) {
1532         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1533                "pic16_aopPut got offset > aop->size");
1534         exit(0);
1535     }
1536
1537     /* will assign value to value */
1538     /* depending on where it is ofcourse */
1539     switch (aop->type) {
1540     case AOP_DIR:
1541       if (offset) {
1542         sprintf(d,"(%s + %d)",
1543                 aop->aopu.aop_dir,offset);
1544         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1545
1546       } else
1547             sprintf(d,"%s",aop->aopu.aop_dir);
1548         
1549         if (strcmp(d,s)) {
1550           DEBUGpic16_emitcode(";","%d",__LINE__);
1551           if(strcmp(s,"W"))
1552             pic16_emitcode("movf","%s,w",s);
1553           pic16_emitcode("movwf","%s",d);
1554
1555           if(strcmp(s,"W")) {
1556             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1557             if(offset >= aop->size) {
1558               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1559               break;
1560             } else
1561               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1562           }
1563
1564           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1565
1566
1567         }
1568         break;
1569         
1570     case AOP_REG:
1571       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1572         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1573           /*
1574             if (*s == '@'           ||
1575                 strcmp(s,"r0") == 0 ||
1576                 strcmp(s,"r1") == 0 ||
1577                 strcmp(s,"r2") == 0 ||
1578                 strcmp(s,"r3") == 0 ||
1579                 strcmp(s,"r4") == 0 ||
1580                 strcmp(s,"r5") == 0 ||
1581                 strcmp(s,"r6") == 0 || 
1582                 strcmp(s,"r7") == 0 )
1583                 pic16_emitcode("mov","%s,%s  ; %d",
1584                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1585             else
1586           */
1587
1588           if(strcmp(s,"W")==0 )
1589             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1590
1591           pic16_emitcode("movwf","%s",
1592                    aop->aopu.aop_reg[offset]->name);
1593
1594           if(strcmp(s,zero)==0) {
1595             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1596
1597           } else if(strcmp(s,"W")==0) {
1598             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1599             pcop->type = PO_GPR_REGISTER;
1600
1601             PCOR(pcop)->rIdx = -1;
1602             PCOR(pcop)->r = NULL;
1603
1604             DEBUGpic16_emitcode(";","%d",__LINE__);
1605             pcop->name = Safe_strdup(s);
1606             pic16_emitpcode(POC_MOVFW,pcop);
1607             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1608           } else if(strcmp(s,one)==0) {
1609             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1610             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1611           } else {
1612             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1613           }
1614         }
1615         break;
1616         
1617     case AOP_DPTR:
1618     case AOP_DPTR2:
1619     
1620     if (aop->type == AOP_DPTR2)
1621     {
1622         genSetDPTR(1);
1623     }
1624     
1625         if (aop->code) {
1626             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1627                    "pic16_aopPut writting to code space");
1628             exit(0);
1629         }
1630         
1631         while (offset > aop->coff) {
1632             aop->coff++;
1633             pic16_emitcode ("inc","dptr");
1634         }
1635         
1636         while (offset < aop->coff) {
1637             aop->coff-- ;
1638             pic16_emitcode("lcall","__decdptr");
1639         }
1640         
1641         aop->coff = offset;
1642         
1643         /* if not in accumulater */
1644         MOVA(s);        
1645         
1646         pic16_emitcode ("movx","@dptr,a");
1647         
1648     if (aop->type == AOP_DPTR2)
1649     {
1650         genSetDPTR(0);
1651     }
1652         break;
1653         
1654     case AOP_R0:
1655     case AOP_R1:
1656         while (offset > aop->coff) {
1657             aop->coff++;
1658             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1659         }
1660         while (offset < aop->coff) {
1661             aop->coff-- ;
1662             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1663         }
1664         aop->coff = offset;
1665         
1666         if (aop->paged) {
1667             MOVA(s);           
1668             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1669             
1670         } else
1671             if (*s == '@') {
1672                 MOVA(s);
1673                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1674             } else
1675                 if (strcmp(s,"r0") == 0 ||
1676                     strcmp(s,"r1") == 0 ||
1677                     strcmp(s,"r2") == 0 ||
1678                     strcmp(s,"r3") == 0 ||
1679                     strcmp(s,"r4") == 0 ||
1680                     strcmp(s,"r5") == 0 ||
1681                     strcmp(s,"r6") == 0 || 
1682                     strcmp(s,"r7") == 0 ) {
1683                     char buffer[10];
1684                     sprintf(buffer,"a%s",s);
1685                     pic16_emitcode("mov","@%s,%s",
1686                              aop->aopu.aop_ptr->name,buffer);
1687                 } else
1688                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1689         
1690         break;
1691         
1692     case AOP_STK:
1693         if (strcmp(s,"a") == 0)
1694             pic16_emitcode("push","acc");
1695         else
1696             pic16_emitcode("push","%s",s);
1697         
1698         break;
1699         
1700     case AOP_CRY:
1701         /* if bit variable */
1702         if (!aop->aopu.aop_dir) {
1703             pic16_emitcode("clr","a");
1704             pic16_emitcode("rlc","a");
1705         } else {
1706             if (s == zero) 
1707                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1708             else
1709                 if (s == one)
1710                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1711                 else
1712                     if (!strcmp(s,"c"))
1713                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1714                     else {
1715                         lbl = newiTempLabel(NULL);
1716                         
1717                         if (strcmp(s,"a")) {
1718                             MOVA(s);
1719                         }
1720                         pic16_emitcode("clr","c");
1721                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1722                         pic16_emitcode("cpl","c");
1723                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1724                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1725                     }
1726         }
1727         break;
1728         
1729     case AOP_STR:
1730         aop->coff = offset;
1731         if (strcmp(aop->aopu.aop_str[offset],s))
1732             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1733         break;
1734         
1735     case AOP_ACC:
1736         aop->coff = offset;
1737         if (!offset && (strcmp(s,"acc") == 0))
1738             break;
1739         
1740         if (strcmp(aop->aopu.aop_str[offset],s))
1741             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1742         break;
1743
1744     default :
1745         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1746                "pic16_aopPut got unsupported aop->type");
1747         exit(0);    
1748     }    
1749
1750 }
1751
1752 /*-----------------------------------------------------------------*/
1753 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1754 /*-----------------------------------------------------------------*/
1755 static void mov2w (asmop *aop, int offset)
1756 {
1757
1758   if(!aop)
1759     return;
1760
1761   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1762
1763   if ( aop->type == AOP_PCODE ||
1764        aop->type == AOP_LIT )
1765     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1766   else
1767     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1768
1769 }
1770
1771
1772 void pic16_pushpCodeOpReg(pCodeOpReg *pcop)
1773 {
1774         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pcop, &pic16_pc_postdec1, 0));
1775 }
1776
1777 void pic16_poppCodeOpReg(pCodeOpReg *pcop)
1778 {
1779         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, pcop, 0));
1780 }
1781
1782
1783 /*-----------------------------------------------------------------*/
1784 /* pushw - pushes wreg to stack                                    */
1785 /*-----------------------------------------------------------------*/
1786 void pushw(void)
1787 {
1788         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1789         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1790 }
1791
1792                 
1793 /*-----------------------------------------------------------------*/
1794 /* pushaop - pushes aop to stack                                   */
1795 /*-----------------------------------------------------------------*/
1796 void pushaop(asmop *aop, int offset)
1797 {
1798         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1799         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1800 }
1801
1802 /*-----------------------------------------------------------------*/
1803 /* popaop - pops aop from stack                                    */
1804 /*-----------------------------------------------------------------*/
1805 void popaop(asmop *aop, int offset)
1806 {
1807         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1808         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1809 }
1810
1811 void popaopidx(asmop *aop, int offset, int index)
1812 {
1813   int ofs=1;
1814
1815         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1816
1817         if(STACK_MODEL_LARGE)ofs++;
1818
1819         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1820         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1821 }
1822
1823 /*-----------------------------------------------------------------*/
1824 /* reAdjustPreg - points a register back to where it should        */
1825 /*-----------------------------------------------------------------*/
1826 static void reAdjustPreg (asmop *aop)
1827 {
1828     int size ;
1829
1830     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1831     aop->coff = 0;
1832     if ((size = aop->size) <= 1)
1833         return ;
1834     size-- ;
1835     switch (aop->type) {
1836         case AOP_R0 :
1837         case AOP_R1 :
1838             while (size--)
1839                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1840             break;          
1841         case AOP_DPTR :
1842         case AOP_DPTR2:
1843             if (aop->type == AOP_DPTR2)
1844             {
1845                 genSetDPTR(1);
1846             } 
1847             while (size--)
1848             {
1849                 pic16_emitcode("lcall","__decdptr");
1850             }
1851                 
1852             if (aop->type == AOP_DPTR2)
1853             {
1854                 genSetDPTR(0);
1855             }                
1856             break;  
1857
1858     }   
1859
1860 }
1861
1862
1863 #if 0
1864 /*-----------------------------------------------------------------*/
1865 /* opIsGptr: returns non-zero if the passed operand is             */   
1866 /* a generic pointer type.                                         */
1867 /*-----------------------------------------------------------------*/ 
1868 static int opIsGptr(operand *op)
1869 {
1870     sym_link *type = operandType(op);
1871     
1872     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1873     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1874     {
1875         return 1;
1876     }
1877     return 0;        
1878 }
1879 #endif
1880
1881 /*-----------------------------------------------------------------*/
1882 /* pic16_getDataSize - get the operand data size                         */
1883 /*-----------------------------------------------------------------*/
1884 int pic16_getDataSize(operand *op)
1885 {
1886     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1887
1888
1889     return AOP_SIZE(op);
1890
1891     // tsd- in the pic port, the genptr size is 1, so this code here
1892     // fails. ( in the 8051 port, the size was 4).
1893 #if 0
1894     int size;
1895     size = AOP_SIZE(op);
1896     if (size == GPTRSIZE)
1897     {
1898         sym_link *type = operandType(op);
1899         if (IS_GENPTR(type))
1900         {
1901             /* generic pointer; arithmetic operations
1902              * should ignore the high byte (pointer type).
1903              */
1904             size--;
1905     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1906         }
1907     }
1908     return size;
1909 #endif
1910 }
1911
1912 /*-----------------------------------------------------------------*/
1913 /* pic16_outAcc - output Acc                                             */
1914 /*-----------------------------------------------------------------*/
1915 void pic16_outAcc(operand *result)
1916 {
1917   int size,offset;
1918   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1919   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
1920
1921
1922   size = pic16_getDataSize(result);
1923   if(size){
1924     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
1925     size--;
1926     offset = 1;
1927     /* unsigned or positive */
1928     while(size--)
1929       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1930   }
1931
1932 }
1933
1934 /*-----------------------------------------------------------------*/
1935 /* pic16_outBitC - output a bit C                                        */
1936 /*-----------------------------------------------------------------*/
1937 void pic16_outBitC(operand *result)
1938 {
1939
1940     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1941     /* if the result is bit */
1942     if (AOP_TYPE(result) == AOP_CRY) 
1943         pic16_aopPut(AOP(result),"c",0);
1944     else {
1945         pic16_emitcode("clr","a  ; %d", __LINE__);
1946         pic16_emitcode("rlc","a");
1947         pic16_outAcc(result);
1948     }
1949 }
1950
1951 /*-----------------------------------------------------------------*/
1952 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
1953 /*-----------------------------------------------------------------*/
1954 void pic16_toBoolean(operand *oper)
1955 {
1956     int size = AOP_SIZE(oper) - 1;
1957     int offset = 1;
1958
1959     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1960
1961     if ( AOP_TYPE(oper) != AOP_ACC) {
1962       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
1963     }
1964     while (size--) {
1965       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
1966     }
1967 }
1968
1969
1970 #if !defined(GEN_Not)
1971 /*-----------------------------------------------------------------*/
1972 /* genNot - generate code for ! operation                          */
1973 /*-----------------------------------------------------------------*/
1974 static void pic16_genNot (iCode *ic)
1975 {
1976   symbol *tlbl;
1977   int size;
1978
1979   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1980   /* assign asmOps to operand & result */
1981   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1982   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1983
1984   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1985   /* if in bit space then a special case */
1986   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1987     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1988       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1989       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1990     } else {
1991       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1992       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
1993       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1994     }
1995     goto release;
1996   }
1997
1998   size = AOP_SIZE(IC_LEFT(ic));
1999   if(size == 1) {
2000     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2001     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2002     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2003     goto release;
2004   }
2005   pic16_toBoolean(IC_LEFT(ic));
2006
2007   tlbl = newiTempLabel(NULL);
2008   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2009   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2010   pic16_outBitC(IC_RESULT(ic));
2011
2012  release:    
2013   /* release the aops */
2014   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2015   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2016 }
2017 #endif
2018
2019
2020 #if !defined(GEN_Cpl)
2021 /*-----------------------------------------------------------------*/
2022 /* genCpl - generate code for complement                           */
2023 /*-----------------------------------------------------------------*/
2024 static void pic16_genCpl (iCode *ic)
2025 {
2026     int offset = 0;
2027     int size ;
2028
2029
2030     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2031     /* assign asmOps to operand & result */
2032     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2033     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2034
2035     /* if both are in bit space then 
2036     a special case */
2037     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2038         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2039
2040         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2041         pic16_emitcode("cpl","c"); 
2042         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2043         goto release; 
2044     } 
2045
2046     size = AOP_SIZE(IC_RESULT(ic));
2047     while (size--) {
2048 /*
2049         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2050         MOVA(l);       
2051         pic16_emitcode("cpl","a");
2052         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2053 */
2054         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2055               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2056         } else {
2057                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2058                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2059         }
2060         offset++;
2061
2062     }
2063
2064
2065 release:
2066     /* release the aops */
2067     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2068     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2069 }
2070 #endif
2071
2072 /*-----------------------------------------------------------------*/
2073 /* genUminusFloat - unary minus for floating points                */
2074 /*-----------------------------------------------------------------*/
2075 static void genUminusFloat(operand *op,operand *result)
2076 {
2077     int size ,offset =0 ;
2078     char *l;
2079
2080     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2081     /* for this we just need to flip the 
2082     first it then copy the rest in place */
2083     size = AOP_SIZE(op) - 1;
2084     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2085
2086     MOVA(l);    
2087
2088     pic16_emitcode("cpl","acc.7");
2089     pic16_aopPut(AOP(result),"a",3);    
2090
2091     while(size--) {
2092         pic16_aopPut(AOP(result),
2093                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2094                offset);
2095         offset++;
2096     }          
2097 }
2098
2099 /*-----------------------------------------------------------------*/
2100 /* genUminus - unary minus code generation                         */
2101 /*-----------------------------------------------------------------*/
2102 static void genUminus (iCode *ic)
2103 {
2104   int size, i;
2105   sym_link *optype, *rtype;
2106
2107
2108   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2109   /* assign asmops */
2110   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2111   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2112
2113   /* if both in bit space then special
2114      case */
2115   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2116       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2117
2118     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2119     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2120     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2121
2122     goto release; 
2123   } 
2124
2125   optype = operandType(IC_LEFT(ic));
2126   rtype = operandType(IC_RESULT(ic));
2127
2128   /* if float then do float stuff */
2129   if (IS_FLOAT(optype)) {
2130     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2131     goto release;
2132   }
2133
2134   /* otherwise subtract from zero by taking the 2's complement */
2135   size = AOP_SIZE(IC_LEFT(ic));
2136
2137   for(i=0; i<size; i++) {
2138     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2139       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2140     else {
2141       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2142       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2143     }
2144   }
2145
2146   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2147   for(i=1; i<size; i++) {
2148     emitSKPNZ;
2149     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2150   }
2151
2152  release:
2153   /* release the aops */
2154   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2155   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2156 }
2157
2158 /*-----------------------------------------------------------------*/
2159 /* saveRegisters - will look for a call and save the registers     */
2160 /*-----------------------------------------------------------------*/
2161 static void saveRegisters(iCode *lic) 
2162 {
2163     int i;
2164     iCode *ic;
2165     bitVect *rsave;
2166     sym_link *dtype;
2167
2168     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2169     /* look for call */
2170     for (ic = lic ; ic ; ic = ic->next) 
2171         if (ic->op == CALL || ic->op == PCALL)
2172             break;
2173
2174     if (!ic) {
2175         fprintf(stderr,"found parameter push with no function call\n");
2176         return ;
2177     }
2178
2179     /* if the registers have been saved already then
2180     do nothing */
2181     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2182         return ;
2183
2184     /* find the registers in use at this time 
2185     and push them away to safety */
2186     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2187                           ic->rUsed);
2188
2189     ic->regsSaved = 1;
2190     if (options.useXstack) {
2191         if (bitVectBitValue(rsave,R0_IDX))
2192             pic16_emitcode("mov","b,r0");
2193         pic16_emitcode("mov","r0,%s",spname);
2194         for (i = 0 ; i < pic16_nRegs ; i++) {
2195             if (bitVectBitValue(rsave,i)) {
2196                 if (i == R0_IDX)
2197                     pic16_emitcode("mov","a,b");
2198                 else
2199                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2200                 pic16_emitcode("movx","@r0,a");
2201                 pic16_emitcode("inc","r0");
2202             }
2203         }
2204         pic16_emitcode("mov","%s,r0",spname);
2205         if (bitVectBitValue(rsave,R0_IDX))
2206             pic16_emitcode("mov","r0,b");           
2207     }// else
2208     //for (i = 0 ; i < pic16_nRegs ; i++) {
2209     //    if (bitVectBitValue(rsave,i))
2210     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2211     //}
2212
2213     dtype = operandType(IC_LEFT(ic));
2214     if (currFunc && dtype && 
2215         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2216         IFFUNC_ISISR(currFunc->type) &&
2217         !ic->bankSaved) 
2218
2219         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2220
2221 }
2222 /*-----------------------------------------------------------------*/
2223 /* unsaveRegisters - pop the pushed registers                      */
2224 /*-----------------------------------------------------------------*/
2225 static void unsaveRegisters (iCode *ic)
2226 {
2227     int i;
2228     bitVect *rsave;
2229
2230     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2231     /* find the registers in use at this time 
2232     and push them away to safety */
2233     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2234                           ic->rUsed);
2235     
2236     if (options.useXstack) {
2237         pic16_emitcode("mov","r0,%s",spname);   
2238         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2239             if (bitVectBitValue(rsave,i)) {
2240                 pic16_emitcode("dec","r0");
2241                 pic16_emitcode("movx","a,@r0");
2242                 if (i == R0_IDX)
2243                     pic16_emitcode("mov","b,a");
2244                 else
2245                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2246             }       
2247
2248         }
2249         pic16_emitcode("mov","%s,r0",spname);
2250         if (bitVectBitValue(rsave,R0_IDX))
2251             pic16_emitcode("mov","r0,b");
2252     } //else
2253     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2254     //    if (bitVectBitValue(rsave,i))
2255     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2256     //}
2257
2258 }  
2259
2260
2261 /*-----------------------------------------------------------------*/
2262 /* pushSide -                                                      */
2263 /*-----------------------------------------------------------------*/
2264 static void pushSide(operand * oper, int size)
2265 {
2266 #if 0
2267         int offset = 0;
2268     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2269         while (size--) {
2270                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2271                 if (AOP_TYPE(oper) != AOP_REG &&
2272                     AOP_TYPE(oper) != AOP_DIR &&
2273                     strcmp(l,"a") ) {
2274                         pic16_emitcode("mov","a,%s",l);
2275                         pic16_emitcode("push","acc");
2276                 } else
2277                         pic16_emitcode("push","%s",l);
2278         }
2279 #endif
2280 }
2281
2282 /*-----------------------------------------------------------------*/
2283 /* assignResultValue -                                             */
2284 /*-----------------------------------------------------------------*/
2285 static void assignResultValue(operand * oper)
2286 {
2287   int size = AOP_SIZE(oper);
2288
2289         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2290         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2291
2292         if(!GpsuedoStkPtr) {
2293 //              DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2294                 /* The last byte in the assignment is in W */
2295                 size--;
2296                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2297                 GpsuedoStkPtr++;
2298         }
2299
2300         while (size--) {
2301 //              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2302 //              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2303                 
2304 #if STACK_SUPPORT
2305                 if(USE_STACK) {
2306                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2307                 } else {
2308                         pic16_emitpcode(POC_MOVFW, pic16_popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2309                 }
2310 #else
2311                 pic16_emitpcode(POC_MOVFW, pic16_popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2312 #endif  /* STACK_SUPPORT */
2313                 GpsuedoStkPtr++;
2314
2315 #if STACK_SUPPORT
2316                 if(!USE_STACK)
2317                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2318 #else
2319                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2320 #endif
2321
2322         }
2323                 
2324 }
2325
2326
2327 /*-----------------------------------------------------------------*/
2328 /* genIpush - genrate code for pushing this gets a little complex  */
2329 /*-----------------------------------------------------------------*/
2330 static void genIpush (iCode *ic)
2331 {
2332
2333   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2334 #if 0
2335     int size, offset = 0 ;
2336     char *l;
2337
2338
2339     /* if this is not a parm push : ie. it is spill push 
2340     and spill push is always done on the local stack */
2341     if (!ic->parmPush) {
2342
2343         /* and the item is spilt then do nothing */
2344         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2345             return ;
2346
2347         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2348         size = AOP_SIZE(IC_LEFT(ic));
2349         /* push it on the stack */
2350         while(size--) {
2351             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2352             if (*l == '#') {
2353                 MOVA(l);
2354                 l = "acc";
2355             }
2356             pic16_emitcode("push","%s",l);
2357         }
2358         return ;        
2359     }
2360
2361     /* this is a paramter push: in this case we call
2362     the routine to find the call and save those
2363     registers that need to be saved */   
2364     saveRegisters(ic);
2365
2366     /* then do the push */
2367     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2368
2369
2370         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2371     size = AOP_SIZE(IC_LEFT(ic));
2372
2373     while (size--) {
2374         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2375         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2376             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2377             strcmp(l,"a") ) {
2378             pic16_emitcode("mov","a,%s",l);
2379             pic16_emitcode("push","acc");
2380         } else
2381             pic16_emitcode("push","%s",l);
2382     }       
2383
2384     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2385 #endif
2386 }
2387
2388 /*-----------------------------------------------------------------*/
2389 /* genIpop - recover the registers: can happen only for spilling   */
2390 /*-----------------------------------------------------------------*/
2391 static void genIpop (iCode *ic)
2392 {
2393   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2394 #if 0
2395     int size,offset ;
2396
2397
2398     /* if the temp was not pushed then */
2399     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2400         return ;
2401
2402     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2403     size = AOP_SIZE(IC_LEFT(ic));
2404     offset = (size-1);
2405     while (size--) 
2406         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2407                                    FALSE,TRUE));
2408
2409     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2410 #endif
2411 }
2412
2413 /*-----------------------------------------------------------------*/
2414 /* unsaverbank - restores the resgister bank from stack            */
2415 /*-----------------------------------------------------------------*/
2416 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2417 {
2418   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2419 #if 0
2420     int i;
2421     asmop *aop ;
2422     regs *r = NULL;
2423
2424     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2425     if (popPsw) {
2426         if (options.useXstack) {
2427             aop = newAsmop(0);
2428             r = getFreePtr(ic,&aop,FALSE);
2429             
2430             
2431             pic16_emitcode("mov","%s,_spx",r->name);
2432             pic16_emitcode("movx","a,@%s",r->name);
2433             pic16_emitcode("mov","psw,a");
2434             pic16_emitcode("dec","%s",r->name);
2435             
2436         }else
2437             pic16_emitcode ("pop","psw");
2438     }
2439
2440     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2441         if (options.useXstack) {       
2442             pic16_emitcode("movx","a,@%s",r->name);
2443             //pic16_emitcode("mov","(%s+%d),a",
2444             //       regspic16[i].base,8*bank+regspic16[i].offset);
2445             pic16_emitcode("dec","%s",r->name);
2446
2447         } else 
2448           pic16_emitcode("pop",""); //"(%s+%d)",
2449         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2450     }
2451
2452     if (options.useXstack) {
2453
2454         pic16_emitcode("mov","_spx,%s",r->name);
2455         pic16_freeAsmop(NULL,aop,ic,TRUE);
2456
2457     }
2458 #endif 
2459 }
2460
2461 /*-----------------------------------------------------------------*/
2462 /* saverbank - saves an entire register bank on the stack          */
2463 /*-----------------------------------------------------------------*/
2464 static void saverbank (int bank, iCode *ic, bool pushPsw)
2465 {
2466   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2467 #if 0
2468     int i;
2469     asmop *aop ;
2470     regs *r = NULL;
2471
2472     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2473     if (options.useXstack) {
2474
2475         aop = newAsmop(0);
2476         r = getFreePtr(ic,&aop,FALSE);  
2477         pic16_emitcode("mov","%s,_spx",r->name);
2478
2479     }
2480
2481     for (i = 0 ; i < pic16_nRegs ;i++) {
2482         if (options.useXstack) {
2483             pic16_emitcode("inc","%s",r->name);
2484             //pic16_emitcode("mov","a,(%s+%d)",
2485             //         regspic16[i].base,8*bank+regspic16[i].offset);
2486             pic16_emitcode("movx","@%s,a",r->name);           
2487         } else 
2488           pic16_emitcode("push","");// "(%s+%d)",
2489                      //regspic16[i].base,8*bank+regspic16[i].offset);
2490     }
2491     
2492     if (pushPsw) {
2493         if (options.useXstack) {
2494             pic16_emitcode("mov","a,psw");
2495             pic16_emitcode("movx","@%s,a",r->name);     
2496             pic16_emitcode("inc","%s",r->name);
2497             pic16_emitcode("mov","_spx,%s",r->name);       
2498             pic16_freeAsmop (NULL,aop,ic,TRUE);
2499             
2500         } else
2501             pic16_emitcode("push","psw");
2502         
2503         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2504     }
2505     ic->bankSaved = 1;
2506 #endif
2507 }
2508
2509
2510
2511 /*-----------------------------------------------------------------*/
2512 /* genCall - generates a call statement                            */
2513 /*-----------------------------------------------------------------*/
2514 static void genCall (iCode *ic)
2515 {
2516   sym_link *dtype;   
2517   int stackParms=0;
2518   
2519         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2520
2521         /* if caller saves & we have not saved then */
2522         if (!ic->regsSaved)
2523                 saveRegisters(ic);
2524
2525         /* if we are calling a function that is not using
2526          * the same register bank then we need to save the
2527          * destination registers on the stack */
2528         dtype = operandType(IC_LEFT(ic));
2529         if (currFunc && dtype && 
2530                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2531                 IFFUNC_ISISR(currFunc->type) &&
2532                 !ic->bankSaved) 
2533
2534                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2535
2536         /* if send set is not empty the assign */
2537         if (_G.sendSet) {
2538           iCode *sic;
2539
2540                 /* For the Pic port, there is no data stack.
2541                  * So parameters passed to functions are stored
2542                  * in registers. (The pCode optimizer will get
2543                  * rid of most of these :). */
2544
2545           int psuedoStkPtr=-1; 
2546           int firstTimeThruLoop = 1;
2547
2548                 _G.sendSet = reverseSet(_G.sendSet);
2549
2550                 /* First figure how many parameters are getting passed */
2551                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2552                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2553                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2554                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2555                 }
2556
2557                 stackParms = psuedoStkPtr;
2558
2559                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2560                   int size, offset = 0;
2561
2562                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2563                         size = AOP_SIZE(IC_LEFT(sic));
2564
2565                         while (size--) {
2566                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2567                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2568                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2569
2570                                 if(!firstTimeThruLoop) {
2571                                         /* If this is not the first time we've been through the loop
2572                                          * then we need to save the parameter in a temporary
2573                                          * register. The last byte of the last parameter is
2574                                          * passed in W. */
2575
2576 #if STACK_SUPPORT
2577                                         if(USE_STACK) {
2578                                                 pushw();
2579                                                 --psuedoStkPtr;         // sanity check
2580                                         } else {
2581                                                 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2582                                         }
2583 #else
2584                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2585 #endif  /* STACK_SUPPORT */
2586                                 }
2587                         
2588                                 firstTimeThruLoop=0;
2589
2590                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2591                                 offset++;
2592                         }
2593                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2594                 }
2595                 _G.sendSet = NULL;
2596         }
2597
2598         /* make the call */
2599         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2600                         OP_SYMBOL(IC_LEFT(ic))->rname :
2601                         OP_SYMBOL(IC_LEFT(ic))->name));
2602
2603         GpsuedoStkPtr=0;
2604         /* if we need assign a result value */
2605         if ((IS_ITEMP(IC_RESULT(ic)) && 
2606                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2607                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2608                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2609
2610                 _G.accInUse++;
2611                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2612                 _G.accInUse--;
2613
2614                 assignResultValue(IC_RESULT(ic));
2615
2616                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2617                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2618                 
2619                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2620         }
2621
2622 #if STACK_SUPPORT
2623         if(USE_STACK && stackParms>0) {
2624                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2625                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2626                 if(STACK_MODEL_LARGE) {
2627                         emitSKPNC;
2628                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2629                 }
2630         }
2631 #endif
2632
2633         /* adjust the stack for parameters if required */
2634 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2635
2636         if (ic->parmBytes) {
2637           int i;
2638
2639                 if (ic->parmBytes > 3) {
2640                         pic16_emitcode("mov","a,%s",spname);
2641                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2642                         pic16_emitcode("mov","%s,a",spname);
2643                 } else 
2644                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2645                                 pic16_emitcode("dec","%s",spname);
2646         }
2647
2648         /* if register bank was saved then pop them */
2649         if (ic->bankSaved)
2650                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2651
2652         /* if we hade saved some registers then unsave them */
2653         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2654                 unsaveRegisters (ic);
2655 }
2656
2657 /*-----------------------------------------------------------------*/
2658 /* genPcall - generates a call by pointer statement                */
2659 /*-----------------------------------------------------------------*/
2660 static void genPcall (iCode *ic)
2661 {
2662     sym_link *dtype;
2663     symbol *rlbl = newiTempLabel(NULL);
2664
2665
2666     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2667     /* if caller saves & we have not saved then */
2668     if (!ic->regsSaved)
2669         saveRegisters(ic);
2670
2671     /* if we are calling a function that is not using
2672     the same register bank then we need to save the
2673     destination registers on the stack */
2674     dtype = operandType(IC_LEFT(ic));
2675     if (currFunc && dtype && 
2676         IFFUNC_ISISR(currFunc->type) &&
2677         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2678         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2679
2680
2681     /* push the return address on to the stack */
2682     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2683     pic16_emitcode("push","acc");    
2684     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2685     pic16_emitcode("push","acc");
2686     
2687     if (options.model == MODEL_FLAT24)
2688     {
2689         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2690         pic16_emitcode("push","acc");    
2691     }
2692
2693     /* now push the calling address */
2694     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2695
2696     pushSide(IC_LEFT(ic), FPTRSIZE);
2697
2698     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2699
2700     /* if send set is not empty the assign */
2701     if (_G.sendSet) {
2702         iCode *sic ;
2703
2704         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2705              sic = setNextItem(_G.sendSet)) {
2706             int size, offset = 0;
2707             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2708             size = AOP_SIZE(IC_LEFT(sic));
2709             while (size--) {
2710                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
2711                                 FALSE,FALSE);
2712                 if (strcmp(l,fReturn[offset]))
2713                     pic16_emitcode("mov","%s,%s",
2714                              fReturn[offset],
2715                              l);
2716                 offset++;
2717             }
2718             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2719         }
2720         _G.sendSet = NULL;
2721     }
2722
2723     pic16_emitcode("ret","");
2724     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
2725
2726
2727     /* if we need assign a result value */
2728     if ((IS_ITEMP(IC_RESULT(ic)) &&
2729          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2730           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2731         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2732
2733         _G.accInUse++;
2734         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2735         _G.accInUse--;
2736         
2737         assignResultValue(IC_RESULT(ic));
2738
2739         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2740     }
2741
2742     /* adjust the stack for parameters if 
2743     required */
2744     if (ic->parmBytes) {
2745         int i;
2746         if (ic->parmBytes > 3) {
2747             pic16_emitcode("mov","a,%s",spname);
2748             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2749             pic16_emitcode("mov","%s,a",spname);
2750         } else 
2751             for ( i = 0 ; i <  ic->parmBytes ;i++)
2752                 pic16_emitcode("dec","%s",spname);
2753
2754     }
2755
2756     /* if register bank was saved then unsave them */
2757     if (currFunc && dtype && 
2758         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2759         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2760
2761     /* if we hade saved some registers then
2762     unsave them */
2763     if (ic->regsSaved)
2764         unsaveRegisters (ic);
2765
2766 }
2767
2768 /*-----------------------------------------------------------------*/
2769 /* resultRemat - result  is rematerializable                       */
2770 /*-----------------------------------------------------------------*/
2771 static int resultRemat (iCode *ic)
2772 {
2773   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2774   if (SKIP_IC(ic) || ic->op == IFX)
2775     return 0;
2776
2777   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2778     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2779     if (sym->remat && !POINTER_SET(ic)) 
2780       return 1;
2781   }
2782
2783   return 0;
2784 }
2785
2786 #if defined(__BORLANDC__) || defined(_MSC_VER)
2787 #define STRCASECMP stricmp
2788 #else
2789 #define STRCASECMP strcasecmp
2790 #endif
2791
2792 #if 0
2793 /*-----------------------------------------------------------------*/
2794 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2795 /*-----------------------------------------------------------------*/
2796 static bool inExcludeList(char *s)
2797 {
2798   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2799     int i =0;
2800     
2801     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2802     if (options.excludeRegs[i] &&
2803     STRCASECMP(options.excludeRegs[i],"none") == 0)
2804         return FALSE ;
2805
2806     for ( i = 0 ; options.excludeRegs[i]; i++) {
2807         if (options.excludeRegs[i] &&
2808         STRCASECMP(s,options.excludeRegs[i]) == 0)
2809             return TRUE;
2810     }
2811     return FALSE ;
2812 }
2813 #endif
2814
2815 /*-----------------------------------------------------------------*/
2816 /* genFunction - generated code for function entry                 */
2817 /*-----------------------------------------------------------------*/
2818 static void genFunction (iCode *ic)
2819 {
2820   symbol *sym;
2821   sym_link *ftype;
2822
2823         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2824
2825         labelOffset += (max_key+4);
2826         max_key=0;
2827         GpsuedoStkPtr=0;
2828         _G.nRegsSaved = 0;
2829         /* create the function header */
2830         pic16_emitcode(";","-----------------------------------------");
2831         pic16_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2832         pic16_emitcode(";","-----------------------------------------");
2833
2834         pic16_emitcode("","%s:",sym->rname);
2835         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
2836
2837         {
2838           absSym *ab;
2839
2840                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
2841                         if(strcmp(ab->name, sym->name)) {
2842                                 pic16_pBlockConvert2Absolute(pb);
2843                                 break;
2844                         }
2845                 
2846         }
2847
2848         ftype = operandType(IC_LEFT(ic));
2849
2850         if(IFFUNC_ISNAKED(ftype)) {
2851                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
2852                 return;
2853         }
2854         
2855
2856         /* if critical function then turn interrupts off */
2857         if (IFFUNC_ISCRITICAL(ftype))
2858                 pic16_emitcode("clr","ea");
2859
2860         /* here we need to generate the equates for the
2861          * register bank if required */
2862 #if 0
2863         if (FUNC_REGBANK(ftype) != rbank) {
2864           int i ;
2865
2866                 rbank = FUNC_REGBANK(ftype);
2867                 for ( i = 0 ; i < pic16_nRegs ; i++ ) {
2868                         if (strcmp(regspic16[i].base,"0") == 0)
2869                                 pic16_emitcode("","%s = 0x%02x",
2870                                         regspic16[i].dname,
2871                                         8*rbank+regspic16[i].offset);
2872                         else
2873                                 pic16_emitcode ("","%s = %s + 0x%02x",
2874                                         regspic16[i].dname,
2875                                         regspic16[i].base,
2876                                         *rbank+regspic16[i].offset);
2877                 }
2878         }
2879 #endif
2880
2881         /* if this is an interrupt service routine then
2882          * save acc, b, dpl, dph  */
2883         if (IFFUNC_ISISR(sym->type)) {
2884                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_wsave));
2885                 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_status));
2886                 pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2887                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_ssave));
2888
2889                 pic16_pBlockConvert2ISR(pb);
2890 #if 0  
2891                 if (!inExcludeList("acc"))          
2892                         pic16_emitcode ("push","acc");  
2893                 if (!inExcludeList("b"))
2894                         pic16_emitcode ("push","b");
2895                 if (!inExcludeList("dpl"))
2896                         pic16_emitcode ("push","dpl");
2897                 if (!inExcludeList("dph"))
2898                         pic16_emitcode ("push","dph");
2899                 
2900                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx")) {
2901                         pic16_emitcode ("push", "dpx");
2902
2903                         /* Make sure we're using standard DPTR */
2904                         pic16_emitcode ("push", "dps");
2905                         pic16_emitcode ("mov", "dps, #0x00");
2906                         if (options.stack10bit) {       
2907                                 /* This ISR could conceivably use DPTR2. Better save it. */
2908                                 pic16_emitcode ("push", "dpl1");
2909                                 pic16_emitcode ("push", "dph1");
2910                                 pic16_emitcode ("push", "dpx1");
2911                         }
2912                 }
2913
2914                 /* if this isr has no bank i.e. is going to
2915                  * run with bank 0 , then we need to save more
2916                  * registers :-) */
2917                 if (!FUNC_REGBANK(sym->type)) {
2918
2919                         /* if this function does not call any other
2920                          * function then we can be economical and
2921                          * save only those registers that are used */
2922                         if (! IFFUNC_HASFCALL(sym->type)) {
2923                           int i;
2924
2925                                 /* if any registers used */
2926                                 if (sym->regsUsed) {
2927                                         /* save the registers used */
2928                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2929                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2930                                                         (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2931                                                 pic16_emitcode("push","junk");//"%s",pic16_regWithIdx(i)->dname);                           
2932                                         }
2933                                 }
2934
2935                         } else {
2936                                 /* this function has  a function call cannot
2937                                  * determines register usage so we will have the
2938                                  * entire bank */
2939                                 saverbank(0,ic,FALSE);
2940                         }           
2941                 }
2942 #endif
2943         } else {
2944 #if STACK_SUPPORT
2945                 /* emit code to setup stack frame if user enabled,
2946                  * and function is not main() */
2947          
2948 //              fprintf(stderr, "function name: %s\n", sym->name);
2949                 if(USE_STACK && strcmp(sym->name, "main")) {
2950                         if(!options.ommitFramePtr || sym->regsUsed) {
2951                         /* setup the stack frame */
2952                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
2953                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
2954                                 if(STACK_MODEL_LARGE)
2955                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
2956                         }
2957                 }
2958 #endif
2959
2960                 /* if callee-save to be used for this function
2961                 * then save the registers being used in this function */
2962                 if (IFFUNC_CALLEESAVES(sym->type)) {
2963                   int i;
2964             
2965 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %p\n", __FILE__, __LINE__, sym->regsUsed);
2966                         
2967                         /* if any registers used */
2968                         if (sym->regsUsed
2969 #if STACK_SUPPORT
2970                                 && USE_STACK
2971 #endif
2972                                 ) {
2973                                 /* save the registers used */
2974                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
2975                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2976                                         if (bitVectBitValue(sym->regsUsed,i)) {
2977 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
2978 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
2979 //                                                              pic16_regWithIdx(i)->name);
2980
2981                                                 pic16_pushpCodeOpReg( PCOR(pic16_popRegFromIdx(i) ));
2982 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
2983 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
2984 //                                                      &pic16_pc_postdec1, 0));
2985                                                 _G.nRegsSaved++;
2986                                         }
2987                                 }
2988                         }
2989                 }
2990         }
2991
2992
2993         
2994 #if 0
2995         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2996
2997                 if (options.useXstack) {
2998                         pic16_emitcode("mov","r0,%s",spname);
2999                         pic16_emitcode("mov","a,_bp");
3000                         pic16_emitcode("movx","@r0,a");
3001                         pic16_emitcode("inc","%s",spname);
3002                 } else {
3003                         /* set up the stack */
3004                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3005                 }
3006                 pic16_emitcode ("mov","_bp,%s",spname);
3007         }
3008 #endif
3009         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3010
3011         /* adjust the stack for the function */
3012         if (sym->stack) {
3013           int i = sym->stack;
3014
3015                 if (i > 127 ) 
3016                         werror(W_STACK_OVERFLOW,sym->name);
3017
3018                 if (i > 3 && sym->recvSize < 4) {              
3019                         pic16_emitcode ("mov","a,sp");
3020                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3021                         pic16_emitcode ("mov","sp,a");
3022                 } else
3023                         while(i--)
3024                                 pic16_emitcode("inc","sp");
3025         }
3026
3027         if (sym->xstack) {
3028                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3029
3030                 pic16_emitcode ("mov","a,_spx");
3031                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3032                 pic16_emitcode ("mov","_spx,a");
3033         }
3034     
3035 }
3036
3037 /*-----------------------------------------------------------------*/
3038 /* genEndFunction - generates epilogue for functions               */
3039 /*-----------------------------------------------------------------*/
3040 static void genEndFunction (iCode *ic)
3041 {
3042     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3043
3044     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3045
3046     if(IFFUNC_ISNAKED(sym->type)) {
3047         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3048         return;
3049     }
3050
3051 #if 0
3052     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3053     {
3054         pic16_emitcode ("mov","%s,_bp",spname);
3055     }
3056 #endif
3057
3058     /* if use external stack but some variables were
3059     added to the local stack then decrement the
3060     local stack */
3061     if (options.useXstack && sym->stack) {      
3062         pic16_emitcode("mov","a,sp");
3063         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3064         pic16_emitcode("mov","sp,a");
3065     }
3066
3067
3068 #if 0
3069     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3070         if (options.useXstack) {
3071             pic16_emitcode("mov","r0,%s",spname);
3072             pic16_emitcode("movx","a,@r0");
3073             pic16_emitcode("mov","_bp,a");
3074             pic16_emitcode("dec","%s",spname);
3075         }
3076         else
3077         {
3078             pic16_emitcode ("pop","_bp");
3079         }
3080     }
3081 #endif
3082
3083     /* restore the register bank  */    
3084     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3085         pic16_emitcode ("pop","psw");
3086
3087     if (IFFUNC_ISISR(sym->type)) {
3088
3089         /* now we need to restore the registers */
3090         /* if this isr has no bank i.e. is going to
3091            run with bank 0 , then we need to save more
3092            registers :-) */
3093         if (!FUNC_REGBANK(sym->type)) {
3094             
3095             /* if this function does not call any other
3096                function then we can be economical and
3097                save only those registers that are used */
3098             if (! IFFUNC_HASFCALL(sym->type)) {
3099                 int i;
3100                 
3101                 /* if any registers used */
3102                 if (sym->regsUsed) {
3103                     /* save the registers used */
3104                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3105                         if (bitVectBitValue(sym->regsUsed,i) ||
3106                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3107                           pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
3108                     }
3109                 }
3110                 
3111             } else {
3112                 /* this function has  a function call cannot
3113                    determines register usage so we will have the
3114                    entire bank */
3115                 unsaverbank(0,ic,FALSE);
3116             }       
3117         }
3118 #if 0
3119         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3120         {
3121             if (options.stack10bit)
3122             {
3123                 pic16_emitcode ("pop", "dpx1");
3124                 pic16_emitcode ("pop", "dph1");
3125                 pic16_emitcode ("pop", "dpl1");
3126             }   
3127             pic16_emitcode ("pop", "dps");
3128             pic16_emitcode ("pop", "dpx");
3129         }
3130         if (!inExcludeList("dph"))
3131             pic16_emitcode ("pop","dph");
3132         if (!inExcludeList("dpl"))
3133             pic16_emitcode ("pop","dpl");
3134         if (!inExcludeList("b"))
3135             pic16_emitcode ("pop","b");
3136         if (!inExcludeList("acc"))
3137             pic16_emitcode ("pop","acc");
3138
3139         if (IFFUNC_ISCRITICAL(sym->type))
3140             pic16_emitcode("setb","ea");
3141 #endif
3142
3143         /* if debug then send end of function */
3144 /*      if (options.debug && currFunc) { */
3145         if (currFunc) {
3146             _G.debugLine = 1;
3147             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3148                      FileBaseName(ic->filename),currFunc->lastLine,
3149                      ic->level,ic->block); 
3150             if (IS_STATIC(currFunc->etype))         
3151                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3152             else
3153                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3154             _G.debugLine = 0;
3155         }
3156         
3157 //      pic16_emitcode ("reti","");
3158
3159         pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
3160         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
3161         pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
3162         pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
3163         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
3164
3165 #if 0
3166         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("END_OF_INTERRUPT",-1));
3167 #endif
3168
3169         pic16_emitpcodeNULLop(POC_RETFIE);
3170
3171     }
3172     else {
3173         if (IFFUNC_ISCRITICAL(sym->type))
3174             pic16_emitcode("setb","ea");
3175         
3176         /* if any registers used */
3177         if (sym->regsUsed
3178 #if STACK_SUPPORT
3179                 && USE_STACK
3180 #endif
3181         ) {
3182           int i;
3183                 /* save the registers used */
3184                 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3185                 for ( i = sym->regsUsed->size; i >= 0; i--) {
3186                         if (bitVectBitValue(sym->regsUsed,i)) {
3187 //                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3188 //                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3189 //                                              pic16_regWithIdx(i)->name);
3190         
3191                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3192                                         &pic16_pc_preinc1,
3193                                         PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3194                         }
3195                 }
3196         }
3197         
3198
3199         /* if debug then send end of function */
3200         if (currFunc) {
3201             _G.debugLine = 1;
3202             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3203                      FileBaseName(ic->filename),currFunc->lastLine,
3204                      ic->level,ic->block); 
3205             if (IS_STATIC(currFunc->etype))         
3206                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3207             else
3208                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3209             _G.debugLine = 0;
3210         }
3211
3212 #if STACK_SUPPORT
3213         /* insert code to restore stack frame, if user enabled it
3214          * and function is not main() */
3215          
3216         if(USE_STACK && strcmp(sym->name, "main")) {
3217                 if(!options.ommitFramePtr || sym->regsUsed) {
3218                         /* restore stack frame */
3219                         if(STACK_MODEL_LARGE)
3220                                 pic16_emitpcode(POC_MOVFF,
3221                                         pic16_popCombine2( &pic16_pc_postinc1, &pic16_pc_fsr2h, 0));
3222                         pic16_emitpcode(POC_MOVFF,
3223                                         pic16_popCombine2( &pic16_pc_postinc1, &pic16_pc_fsr2l, 0));
3224                 }
3225         }
3226 #endif
3227
3228         pic16_emitcode ("return","");
3229         pic16_emitpcodeNULLop(POC_RETURN);
3230
3231         /* Mark the end of a function */
3232         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3233     }
3234
3235 }
3236
3237 /*-----------------------------------------------------------------*/
3238 /* genRet - generate code for return statement                     */
3239 /*-----------------------------------------------------------------*/
3240 static void genRet (iCode *ic)
3241 {
3242   int size,offset = 0 , pushed = 0;
3243     
3244   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3245   /* if we have no return value then
3246      just generate the "ret" */
3247   if (!IC_LEFT(ic)) 
3248     goto jumpret;       
3249     
3250   /* we have something to return then
3251      move the return value into place */
3252   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3253   size = AOP_SIZE(IC_LEFT(ic));
3254     
3255   while (size--) {
3256     char *l ;
3257     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3258       /* #NOCHANGE */
3259       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,
3260                  FALSE,TRUE);
3261       pic16_emitcode("push","%s",l);
3262       pushed++;
3263     } else {
3264         DEBUGpic16_emitcode(";", "%d", __LINE__);
3265       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,
3266                  FALSE,FALSE);
3267         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3268       if (strcmp(fReturn[offset],l)) {
3269         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3270             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3271           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3272         }else {
3273           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3274         }
3275         if(size) {
3276           pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3277         }
3278         offset++;
3279       }
3280     }
3281   }    
3282
3283   if (pushed) {
3284     while(pushed) {
3285       pushed--;
3286       if (strcmp(fReturn[pushed],"a"))
3287         pic16_emitcode("pop",fReturn[pushed]);
3288       else
3289         pic16_emitcode("pop","acc");
3290     }
3291   }
3292   pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3293     
3294  jumpret:
3295   /* generate a jump to the return label
3296      if the next is not the return statement */
3297   if (!(ic->next && ic->next->op == LABEL &&
3298         IC_LABEL(ic->next) == returnLabel)) {
3299         
3300     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3301     pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3302   }
3303     
3304 }
3305
3306 /*-----------------------------------------------------------------*/
3307 /* genLabel - generates a label                                    */
3308 /*-----------------------------------------------------------------*/
3309 static void genLabel (iCode *ic)
3310 {
3311     /* special case never generate */
3312     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3313     if (IC_LABEL(ic) == entryLabel)
3314         return ;
3315
3316     pic16_emitpLabel(IC_LABEL(ic)->key);
3317     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3318 }
3319
3320 /*-----------------------------------------------------------------*/
3321 /* genGoto - generates a goto                                      */
3322 /*-----------------------------------------------------------------*/
3323 //tsd
3324 static void genGoto (iCode *ic)
3325 {
3326   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3327   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3328 }
3329
3330
3331 /*-----------------------------------------------------------------*/
3332 /* genMultbits :- multiplication of bits                           */
3333 /*-----------------------------------------------------------------*/
3334 static void genMultbits (operand *left, 
3335                          operand *right, 
3336                          operand *result)
3337 {
3338   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3339
3340   if(!pic16_sameRegs(AOP(result),AOP(right)))
3341     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3342
3343   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3344   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3345   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3346
3347 }
3348
3349
3350 /*-----------------------------------------------------------------*/
3351 /* genMultOneByte : 8 bit multiplication & division                */
3352 /*-----------------------------------------------------------------*/
3353 static void genMultOneByte (operand *left,
3354                             operand *right,
3355                             operand *result)
3356 {
3357   sym_link *opetype = operandType(result);
3358
3359   // symbol *lbl ;
3360   int size,offset;
3361
3362   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3363   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3364   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3365
3366   /* (if two literals, the value is computed before) */
3367   /* if one literal, literal on the right */
3368   if (AOP_TYPE(left) == AOP_LIT){
3369     operand *t = right;
3370     right = left;
3371     left = t;
3372   }
3373
3374   size = AOP_SIZE(result);
3375   if(size == 1) {
3376
3377     if (AOP_TYPE(right) == AOP_LIT){
3378       pic16_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3379                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3380                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3381                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3382       pic16_emitcode("call","genMultLit");
3383     } else {
3384       pic16_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3385                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3386                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3387                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3388       pic16_emitcode("call","pic16_genMult8X8_8");
3389
3390     }
3391     pic16_genMult8X8_8 (left, right,result);
3392
3393
3394     /* signed or unsigned */
3395     //pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3396     //l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3397     //MOVA(l);       
3398     //pic16_emitcode("mul","ab");
3399     /* if result size = 1, mul signed = mul unsigned */
3400     //pic16_aopPut(AOP(result),"a",0);
3401
3402   } else {  // (size > 1)
3403
3404     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3405                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3406                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3407                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3408
3409     if (SPEC_USIGN(opetype)){
3410       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3411       pic16_genUMult8X8_16 (left, right, result, NULL);
3412
3413       if (size > 2) {
3414         /* for filling the MSBs */
3415         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3416         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3417       }
3418     }
3419     else{
3420       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3421
3422       pic16_emitcode("mov","a,b");
3423
3424       /* adjust the MSB if left or right neg */
3425
3426       /* if one literal */
3427       if (AOP_TYPE(right) == AOP_LIT){
3428         pic16_emitcode("multiply ","right is a lit");
3429         /* AND literal negative */
3430         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3431           /* adjust MSB (c==0 after mul) */
3432           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3433         }
3434       }
3435       else{
3436         pic16_genSMult8X8_16 (left, right, result, NULL);
3437       }
3438
3439       if(size > 2){
3440         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3441         /* get the sign */
3442         pic16_emitcode("rlc","a");
3443         pic16_emitcode("subb","a,acc");
3444       }
3445     }
3446
3447     size -= 2;   
3448     offset = 2;
3449     if (size > 0)
3450       while (size--)
3451         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3452     //pic16_aopPut(AOP(result),"a",offset++);
3453   }
3454 }
3455
3456 /*-----------------------------------------------------------------*/
3457 /* genMult - generates code for multiplication                     */
3458 /*-----------------------------------------------------------------*/
3459 static void genMult (iCode *ic)
3460 {
3461     operand *left = IC_LEFT(ic);
3462     operand *right = IC_RIGHT(ic);
3463     operand *result= IC_RESULT(ic);   
3464
3465     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3466     /* assign the amsops */
3467     pic16_aopOp (left,ic,FALSE);
3468     pic16_aopOp (right,ic,FALSE);
3469     pic16_aopOp (result,ic,TRUE);
3470
3471   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3472
3473     /* special cases first */
3474     /* both are bits */
3475     if (AOP_TYPE(left) == AOP_CRY &&
3476         AOP_TYPE(right)== AOP_CRY) {
3477         genMultbits(left,right,result);
3478         goto release ;
3479     }
3480
3481     /* if both are of size == 1 */
3482     if (AOP_SIZE(left) == 1 &&
3483         AOP_SIZE(right) == 1 ) {
3484         genMultOneByte(left,right,result);
3485         goto release ;
3486     }
3487
3488     pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3489
3490     /* should have been converted to function call */
3491     //assert(0) ;
3492
3493 release :
3494     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3495     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3496     pic16_freeAsmop(result,NULL,ic,TRUE); 
3497 }
3498
3499 /*-----------------------------------------------------------------*/
3500 /* genDivbits :- division of bits                                  */
3501 /*-----------------------------------------------------------------*/
3502 static void genDivbits (operand *left, 
3503                         operand *right, 
3504                         operand *result)
3505 {
3506
3507     char *l;
3508
3509     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3510     /* the result must be bit */    
3511     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3512     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3513
3514     MOVA(l);    
3515
3516     pic16_emitcode("div","ab");
3517     pic16_emitcode("rrc","a");
3518     pic16_aopPut(AOP(result),"c",0);
3519 }
3520
3521 /*-----------------------------------------------------------------*/
3522 /* genDivOneByte : 8 bit division                                  */
3523 /*-----------------------------------------------------------------*/
3524 static void genDivOneByte (operand *left,
3525                            operand *right,
3526                            operand *result)
3527 {
3528     sym_link *opetype = operandType(result);
3529     char *l ;
3530     symbol *lbl ;
3531     int size,offset;
3532
3533     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3534     size = AOP_SIZE(result) - 1;
3535     offset = 1;
3536     /* signed or unsigned */
3537     if (SPEC_USIGN(opetype)) {
3538         /* unsigned is easy */
3539         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3540         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3541         MOVA(l);        
3542         pic16_emitcode("div","ab");
3543         pic16_aopPut(AOP(result),"a",0);
3544         while (size--)
3545             pic16_aopPut(AOP(result),zero,offset++);
3546         return ;
3547     }
3548
3549     /* signed is a little bit more difficult */
3550
3551     /* save the signs of the operands */
3552     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3553     MOVA(l);    
3554     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3555     pic16_emitcode("push","acc"); /* save it on the stack */
3556
3557     /* now sign adjust for both left & right */
3558     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3559     MOVA(l);       
3560     lbl = newiTempLabel(NULL);
3561     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3562     pic16_emitcode("cpl","a");   
3563     pic16_emitcode("inc","a");
3564     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3565     pic16_emitcode("mov","b,a");
3566
3567     /* sign adjust left side */
3568     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3569     MOVA(l);
3570
3571     lbl = newiTempLabel(NULL);
3572     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3573     pic16_emitcode("cpl","a");
3574     pic16_emitcode("inc","a");
3575     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3576
3577     /* now the division */
3578     pic16_emitcode("div","ab");
3579     /* we are interested in the lower order
3580     only */
3581     pic16_emitcode("mov","b,a");
3582     lbl = newiTempLabel(NULL);
3583     pic16_emitcode("pop","acc");   
3584     /* if there was an over flow we don't 
3585     adjust the sign of the result */
3586     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3587     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3588     CLRC;
3589     pic16_emitcode("clr","a");
3590     pic16_emitcode("subb","a,b");
3591     pic16_emitcode("mov","b,a");
3592     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3593
3594     /* now we are done */
3595     pic16_aopPut(AOP(result),"b",0);
3596     if(size > 0){
3597         pic16_emitcode("mov","c,b.7");
3598         pic16_emitcode("subb","a,acc");   
3599     }
3600     while (size--)
3601         pic16_aopPut(AOP(result),"a",offset++);
3602
3603 }
3604
3605 /*-----------------------------------------------------------------*/
3606 /* genDiv - generates code for division                            */
3607 /*-----------------------------------------------------------------*/
3608 static void genDiv (iCode *ic)
3609 {
3610     operand *left = IC_LEFT(ic);
3611     operand *right = IC_RIGHT(ic);
3612     operand *result= IC_RESULT(ic);   
3613
3614     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3615     /* assign the amsops */
3616     pic16_aopOp (left,ic,FALSE);
3617     pic16_aopOp (right,ic,FALSE);
3618     pic16_aopOp (result,ic,TRUE);
3619
3620     /* special cases first */
3621     /* both are bits */
3622     if (AOP_TYPE(left) == AOP_CRY &&
3623         AOP_TYPE(right)== AOP_CRY) {
3624         genDivbits(left,right,result);
3625         goto release ;
3626     }
3627
3628     /* if both are of size == 1 */
3629     if (AOP_SIZE(left) == 1 &&
3630         AOP_SIZE(right) == 1 ) {
3631         genDivOneByte(left,right,result);
3632         goto release ;
3633     }
3634
3635     /* should have been converted to function call */
3636     assert(0);
3637 release :
3638     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3639     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3640     pic16_freeAsmop(result,NULL,ic,TRUE); 
3641 }
3642
3643 /*-----------------------------------------------------------------*/
3644 /* genModbits :- modulus of bits                                   */
3645 /*-----------------------------------------------------------------*/
3646 static void genModbits (operand *left, 
3647                         operand *right, 
3648                         operand *result)
3649 {
3650
3651     char *l;
3652
3653     /* the result must be bit */    
3654     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3655     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3656
3657     MOVA(l);       
3658
3659     pic16_emitcode("div","ab");
3660     pic16_emitcode("mov","a,b");
3661     pic16_emitcode("rrc","a");
3662     pic16_aopPut(AOP(result),"c",0);
3663 }
3664
3665 /*-----------------------------------------------------------------*/
3666 /* genModOneByte : 8 bit modulus                                   */
3667 /*-----------------------------------------------------------------*/
3668 static void genModOneByte (operand *left,
3669                            operand *right,
3670                            operand *result)
3671 {
3672     sym_link *opetype = operandType(result);
3673     char *l ;
3674     symbol *lbl ;
3675
3676     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3677     /* signed or unsigned */
3678     if (SPEC_USIGN(opetype)) {
3679         /* unsigned is easy */
3680         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3681         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3682         MOVA(l);    
3683         pic16_emitcode("div","ab");
3684         pic16_aopPut(AOP(result),"b",0);
3685         return ;
3686     }
3687
3688     /* signed is a little bit more difficult */
3689
3690     /* save the signs of the operands */
3691     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3692     MOVA(l);
3693
3694     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3695     pic16_emitcode("push","acc"); /* save it on the stack */
3696
3697     /* now sign adjust for both left & right */
3698     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3699     MOVA(l);
3700
3701     lbl = newiTempLabel(NULL);
3702     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3703     pic16_emitcode("cpl","a");   
3704     pic16_emitcode("inc","a");
3705     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3706     pic16_emitcode("mov","b,a"); 
3707
3708     /* sign adjust left side */
3709     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3710     MOVA(l);
3711
3712     lbl = newiTempLabel(NULL);
3713     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3714     pic16_emitcode("cpl","a");   
3715     pic16_emitcode("inc","a");
3716     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3717
3718     /* now the multiplication */
3719     pic16_emitcode("div","ab");
3720     /* we are interested in the lower order
3721     only */
3722     lbl = newiTempLabel(NULL);
3723     pic16_emitcode("pop","acc");   
3724     /* if there was an over flow we don't 
3725     adjust the sign of the result */
3726     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3727     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3728     CLRC ;
3729     pic16_emitcode("clr","a");
3730     pic16_emitcode("subb","a,b");
3731     pic16_emitcode("mov","b,a");
3732     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3733
3734     /* now we are done */
3735     pic16_aopPut(AOP(result),"b",0);
3736
3737 }
3738
3739 /*-----------------------------------------------------------------*/
3740 /* genMod - generates code for division                            */
3741 /*-----------------------------------------------------------------*/
3742 static void genMod (iCode *ic)
3743 {
3744     operand *left = IC_LEFT(ic);
3745     operand *right = IC_RIGHT(ic);
3746     operand *result= IC_RESULT(ic);  
3747
3748     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3749     /* assign the amsops */
3750     pic16_aopOp (left,ic,FALSE);
3751     pic16_aopOp (right,ic,FALSE);
3752     pic16_aopOp (result,ic,TRUE);
3753
3754     /* special cases first */
3755     /* both are bits */
3756     if (AOP_TYPE(left) == AOP_CRY &&
3757         AOP_TYPE(right)== AOP_CRY) {
3758         genModbits(left,right,result);
3759         goto release ;
3760     }
3761
3762     /* if both are of size == 1 */
3763     if (AOP_SIZE(left) == 1 &&
3764         AOP_SIZE(right) == 1 ) {
3765         genModOneByte(left,right,result);
3766         goto release ;
3767     }
3768
3769     /* should have been converted to function call */
3770     assert(0);
3771
3772 release :
3773     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3774     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3775     pic16_freeAsmop(result,NULL,ic,TRUE); 
3776 }
3777
3778 /*-----------------------------------------------------------------*/
3779 /* genIfxJump :- will create a jump depending on the ifx           */
3780 /*-----------------------------------------------------------------*/
3781 /*
3782   note: May need to add parameter to indicate when a variable is in bit space.
3783 */
3784 static void genIfxJump (iCode *ic, char *jval)
3785 {
3786
3787     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3788     /* if true label then we jump if condition
3789     supplied is true */
3790     if ( IC_TRUE(ic) ) {
3791
3792         if(strcmp(jval,"a") == 0)
3793           emitSKPZ;
3794         else if (strcmp(jval,"c") == 0)
3795           emitSKPC;
3796         else {
3797           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3798           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
3799         }
3800
3801         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
3802         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3803
3804     }
3805     else {
3806         /* false label is present */
3807         if(strcmp(jval,"a") == 0)
3808           emitSKPNZ;
3809         else if (strcmp(jval,"c") == 0)
3810           emitSKPNC;
3811         else {
3812           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3813           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
3814         }
3815
3816         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
3817         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3818
3819     }
3820
3821
3822     /* mark the icode as generated */
3823     ic->generated = 1;
3824 }
3825
3826 /*-----------------------------------------------------------------*/
3827 /* genSkip                                                         */
3828 /*-----------------------------------------------------------------*/
3829 static void genSkip(iCode *ifx,int status_bit)
3830 {
3831   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3832   if(!ifx)
3833     return;
3834
3835   if ( IC_TRUE(ifx) ) {
3836     switch(status_bit) {
3837     case 'z':
3838       emitSKPNZ;
3839       break;
3840
3841     case 'c':
3842       emitSKPNC;
3843       break;
3844
3845     case 'd':
3846       emitSKPDC;
3847       break;
3848
3849     }
3850
3851     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3852     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3853
3854   } else {
3855
3856     switch(status_bit) {
3857
3858     case 'z':
3859       emitSKPZ;
3860       break;
3861
3862     case 'c':
3863       emitSKPC;
3864       break;
3865
3866     case 'd':
3867       emitSKPDC;
3868       break;
3869     }
3870     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3871     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3872
3873   }
3874
3875 }
3876
3877 /*-----------------------------------------------------------------*/
3878 /* genSkipc                                                        */
3879 /*-----------------------------------------------------------------*/
3880 static void genSkipc(resolvedIfx *rifx)
3881 {
3882   if(!rifx)
3883     return;
3884
3885   if(rifx->condition)
3886     emitSKPC;
3887   else
3888     emitSKPNC;
3889
3890   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3891   rifx->generated = 1;
3892 }
3893
3894 /*-----------------------------------------------------------------*/
3895 /* genSkipz2                                                       */
3896 /*-----------------------------------------------------------------*/
3897 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3898 {
3899   if(!rifx)
3900     return;
3901
3902   if( (rifx->condition ^ invert_condition) & 1)
3903     emitSKPZ;
3904   else
3905     emitSKPNZ;
3906
3907   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3908   rifx->generated = 1;
3909 }
3910
3911 #if 0
3912 /*-----------------------------------------------------------------*/
3913 /* genSkipz                                                        */
3914 /*-----------------------------------------------------------------*/
3915 static void genSkipz(iCode *ifx, int condition)
3916 {
3917   if(!ifx)
3918     return;
3919
3920   if(condition)
3921     emitSKPNZ;
3922   else
3923     emitSKPZ;
3924
3925   if ( IC_TRUE(ifx) )
3926     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3927   else
3928     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3929
3930   if ( IC_TRUE(ifx) )
3931     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3932   else
3933     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3934
3935 }
3936 #endif
3937
3938 /*-----------------------------------------------------------------*/
3939 /* genSkipCond                                                     */
3940 /*-----------------------------------------------------------------*/
3941 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3942 {
3943   if(!rifx)
3944     return;
3945
3946   if(rifx->condition)
3947     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3948   else
3949     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3950
3951
3952   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3953   rifx->generated = 1;
3954 }
3955
3956 #if 0
3957 /*-----------------------------------------------------------------*/
3958 /* genChkZeroes :- greater or less than comparison                 */
3959 /*     For each byte in a literal that is zero, inclusive or the   */
3960 /*     the corresponding byte in the operand with W                */
3961 /*     returns true if any of the bytes are zero                   */
3962 /*-----------------------------------------------------------------*/
3963 static int genChkZeroes(operand *op, int lit,  int size)
3964 {
3965
3966   int i;
3967   int flag =1;
3968
3969   while(size--) {
3970     i = (lit >> (size*8)) & 0xff;
3971
3972     if(i==0) {
3973       if(flag) 
3974         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
3975       else
3976         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
3977       flag = 0;
3978     }
3979   }
3980
3981   return (flag==0);
3982 }
3983 #endif
3984
3985 /*-----------------------------------------------------------------*/
3986 /* genCmp :- greater or less than comparison                       */
3987 /*-----------------------------------------------------------------*/
3988 static void genCmp (operand *left,operand *right,
3989                     operand *result, iCode *ifx, int sign)
3990 {
3991   int size; //, offset = 0 ;
3992   unsigned long lit = 0L,i = 0;
3993   resolvedIfx rFalseIfx;
3994   //  resolvedIfx rTrueIfx;
3995   symbol *truelbl;
3996   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3997 /*
3998   if(ifx) {
3999     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4000     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4001   }
4002 */
4003
4004   resolveIfx(&rFalseIfx,ifx);
4005   truelbl  = newiTempLabel(NULL);
4006   size = max(AOP_SIZE(left),AOP_SIZE(right));
4007
4008   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4009
4010 #define _swapp
4011
4012   /* if literal is on the right then swap with left */
4013   if ((AOP_TYPE(right) == AOP_LIT)) {
4014     operand *tmp = right ;
4015     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4016     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4017 #ifdef _swapp
4018
4019     lit = (lit - 1) & mask;
4020     right = left;
4021     left = tmp;
4022     rFalseIfx.condition ^= 1;
4023 #endif
4024
4025   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4026     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4027   }
4028
4029
4030   //if(IC_TRUE(ifx) == NULL)
4031   /* if left & right are bit variables */
4032   if (AOP_TYPE(left) == AOP_CRY &&
4033       AOP_TYPE(right) == AOP_CRY ) {
4034     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4035     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4036   } else {
4037     /* subtract right from left if at the
4038        end the carry flag is set then we know that
4039        left is greater than right */
4040
4041     //    {
4042
4043     symbol *lbl  = newiTempLabel(NULL);
4044
4045 #ifndef _swapp
4046     if(AOP_TYPE(right) == AOP_LIT) {
4047
4048       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4049
4050       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4051
4052       /* special cases */
4053
4054       if(lit == 0) {
4055
4056         if(sign != 0) 
4057           genSkipCond(&rFalseIfx,left,size-1,7);
4058         else 
4059           /* no need to compare to 0...*/
4060           /* NOTE: this is a de-generate compare that most certainly 
4061            *       creates some dead code. */
4062           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4063
4064         if(ifx) ifx->generated = 1;
4065         return;
4066
4067       }
4068       size--;
4069
4070       if(size == 0) {
4071         //i = (lit >> (size*8)) & 0xff;
4072         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4073         
4074         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4075
4076         i = ((0-lit) & 0xff);
4077         if(sign) {
4078           if( i == 0x81) { 
4079             /* lit is 0x7f, all signed chars are less than
4080              * this except for 0x7f itself */
4081             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4082             genSkipz2(&rFalseIfx,0);
4083           } else {
4084             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4085             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4086             genSkipc(&rFalseIfx);
4087           }
4088
4089         } else {
4090           if(lit == 1) {
4091             genSkipz2(&rFalseIfx,1);
4092           } else {
4093             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4094             genSkipc(&rFalseIfx);
4095           }
4096         }
4097
4098         if(ifx) ifx->generated = 1;
4099         return;
4100       }
4101
4102       /* chars are out of the way. now do ints and longs */
4103
4104
4105       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4106         
4107       /* special cases */
4108
4109       if(sign) {
4110
4111         if(lit == 0) {
4112           genSkipCond(&rFalseIfx,left,size,7);
4113           if(ifx) ifx->generated = 1;
4114           return;
4115         }
4116
4117         if(lit <0x100) {
4118           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4119
4120           //rFalseIfx.condition ^= 1;
4121           //genSkipCond(&rFalseIfx,left,size,7);
4122           //rFalseIfx.condition ^= 1;
4123
4124           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4125           if(rFalseIfx.condition)
4126             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4127           else
4128             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4129
4130           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4131           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4132           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4133
4134           while(size > 1)
4135             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4136
4137           if(rFalseIfx.condition) {
4138             emitSKPZ;
4139             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4140
4141           } else {
4142             emitSKPNZ;
4143           }
4144
4145           genSkipc(&rFalseIfx);
4146           pic16_emitpLabel(truelbl->key);
4147           if(ifx) ifx->generated = 1;
4148           return;
4149
4150         }
4151
4152         if(size == 1) {
4153
4154           if( (lit & 0xff) == 0) {
4155             /* lower byte is zero */
4156             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4157             i = ((lit >> 8) & 0xff) ^0x80;
4158             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4159             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4160             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4161             genSkipc(&rFalseIfx);
4162
4163
4164             if(ifx) ifx->generated = 1;
4165             return;
4166
4167           }
4168         } else {
4169           /* Special cases for signed longs */
4170           if( (lit & 0xffffff) == 0) {
4171             /* lower byte is zero */
4172             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4173             i = ((lit >> 8*3) & 0xff) ^0x80;
4174             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4175             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4176             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4177             genSkipc(&rFalseIfx);
4178
4179
4180             if(ifx) ifx->generated = 1;
4181             return;
4182
4183           }
4184
4185         }
4186
4187
4188         if(lit & (0x80 << (size*8))) {
4189           /* lit is negative */
4190           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4191
4192           //genSkipCond(&rFalseIfx,left,size,7);
4193
4194           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4195
4196           if(rFalseIfx.condition)
4197             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4198           else
4199             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4200
4201
4202         } else {
4203           /* lit is positive */
4204           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4205           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4206           if(rFalseIfx.condition)
4207             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4208           else
4209             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4210
4211         }
4212
4213         /*
4214           This works, but is only good for ints.
4215           It also requires a "known zero" register.
4216           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4217           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4218           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4219           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4220           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4221           genSkipc(&rFalseIfx);
4222
4223           pic16_emitpLabel(truelbl->key);
4224           if(ifx) ifx->generated = 1;
4225           return;
4226         **/
4227           
4228         /* There are no more special cases, so perform a general compare */
4229   
4230         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4231         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4232
4233         while(size--) {
4234
4235           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4236           emitSKPNZ;
4237           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4238         }
4239         //rFalseIfx.condition ^= 1;
4240         genSkipc(&rFalseIfx);
4241
4242         pic16_emitpLabel(truelbl->key);
4243
4244         if(ifx) ifx->generated = 1;
4245         return;
4246
4247
4248       }
4249
4250
4251       /* sign is out of the way. So now do an unsigned compare */
4252       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4253
4254
4255       /* General case - compare to an unsigned literal on the right.*/
4256
4257       i = (lit >> (size*8)) & 0xff;
4258       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4259       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4260       while(size--) {
4261         i = (lit >> (size*8)) & 0xff;
4262
4263         if(i) {
4264           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4265           emitSKPNZ;
4266           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4267         } else {
4268           /* this byte of the lit is zero, 
4269            *if it's not the last then OR in the variable */
4270           if(size)
4271             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4272         }
4273       }
4274
4275
4276       pic16_emitpLabel(lbl->key);
4277       //if(emitFinalCheck)
4278       genSkipc(&rFalseIfx);
4279       if(sign)
4280         pic16_emitpLabel(truelbl->key);
4281
4282       if(ifx) ifx->generated = 1;
4283       return;
4284
4285
4286     }
4287 #endif  // _swapp
4288
4289     if(AOP_TYPE(left) == AOP_LIT) {
4290       //symbol *lbl = newiTempLabel(NULL);
4291
4292       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4293
4294
4295       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4296
4297       /* Special cases */
4298       if((lit == 0) && (sign == 0)){
4299
4300         size--;
4301         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4302         while(size) 
4303           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4304
4305         genSkipz2(&rFalseIfx,0);
4306         if(ifx) ifx->generated = 1;
4307         return;
4308       }
4309
4310       if(size==1) {
4311         /* Special cases */
4312         lit &= 0xff;
4313         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4314           /* degenerate compare can never be true */
4315           if(rFalseIfx.condition == 0)
4316             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4317
4318           if(ifx) ifx->generated = 1;
4319           return;
4320         }
4321
4322         if(sign) {
4323           /* signed comparisons to a literal byte */
4324
4325           int lp1 = (lit+1) & 0xff;
4326
4327           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4328           switch (lp1) {
4329           case 0:
4330             rFalseIfx.condition ^= 1;
4331             genSkipCond(&rFalseIfx,right,0,7);
4332             break;
4333           case 0x7f:
4334             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4335             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4336             genSkipz2(&rFalseIfx,1);
4337             break;
4338           default:
4339             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4340             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4341             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4342             rFalseIfx.condition ^= 1;
4343             genSkipc(&rFalseIfx);
4344             break;
4345           }
4346         } else {
4347           /* unsigned comparisons to a literal byte */
4348
4349           switch(lit & 0xff ) {
4350           case 0:
4351             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4352             genSkipz2(&rFalseIfx,0);
4353             break;
4354           case 0x7f:
4355             rFalseIfx.condition ^= 1;
4356             genSkipCond(&rFalseIfx,right,0,7);
4357             break;
4358
4359           default:
4360             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4361             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4362             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4363             rFalseIfx.condition ^= 1;
4364             if (AOP_TYPE(result) == AOP_CRY)
4365               genSkipc(&rFalseIfx);
4366             else {
4367               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4368               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4369             }         
4370             break;
4371           }
4372         }
4373
4374         if(ifx) ifx->generated = 1;
4375         //goto check_carry;
4376         return;
4377
4378       } else {
4379
4380         /* Size is greater than 1 */
4381
4382         if(sign) {
4383           int lp1 = lit+1;
4384
4385           size--;
4386
4387           if(lp1 == 0) {
4388             /* this means lit = 0xffffffff, or -1 */
4389
4390
4391             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4392             rFalseIfx.condition ^= 1;
4393             genSkipCond(&rFalseIfx,right,size,7);
4394             if(ifx) ifx->generated = 1;
4395             return;
4396           }
4397
4398           if(lit == 0) {
4399             int s = size;
4400
4401             if(rFalseIfx.condition) {
4402               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4403               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4404             }
4405
4406             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4407             while(size--)
4408               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4409
4410
4411             emitSKPZ;
4412             if(rFalseIfx.condition) {
4413               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4414               pic16_emitpLabel(truelbl->key);
4415             }else {
4416               rFalseIfx.condition ^= 1;
4417               genSkipCond(&rFalseIfx,right,s,7);
4418             }
4419
4420             if(ifx) ifx->generated = 1;
4421             return;
4422           }
4423
4424           if((size == 1) &&  (0 == (lp1&0xff))) {
4425             /* lower byte of signed word is zero */
4426             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4427             i = ((lp1 >> 8) & 0xff) ^0x80;
4428             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4429             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4430             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4431             rFalseIfx.condition ^= 1;
4432             genSkipc(&rFalseIfx);
4433
4434
4435             if(ifx) ifx->generated = 1;
4436             return;
4437           }
4438
4439           if(lit & (0x80 << (size*8))) {
4440             /* Lit is less than zero */
4441             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4442             //rFalseIfx.condition ^= 1;
4443             //genSkipCond(&rFalseIfx,left,size,7);
4444             //rFalseIfx.condition ^= 1;
4445             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4446             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4447
4448             if(rFalseIfx.condition)
4449               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4450             else
4451               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4452
4453
4454           } else {
4455             /* Lit is greater than or equal to zero */
4456             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4457             //rFalseIfx.condition ^= 1;
4458             //genSkipCond(&rFalseIfx,right,size,7);
4459             //rFalseIfx.condition ^= 1;
4460
4461             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4462             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4463
4464             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4465             if(rFalseIfx.condition)
4466               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4467             else
4468               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4469
4470           }
4471
4472
4473           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4474           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4475
4476           while(size--) {
4477
4478             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4479             emitSKPNZ;
4480             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4481           }
4482           rFalseIfx.condition ^= 1;
4483           //rFalseIfx.condition = 1;
4484           genSkipc(&rFalseIfx);
4485
4486           pic16_emitpLabel(truelbl->key);
4487
4488           if(ifx) ifx->generated = 1;
4489           return;
4490           // end of if (sign)
4491         } else {
4492
4493           /* compare word or long to an unsigned literal on the right.*/
4494
4495
4496           size--;
4497           if(lit < 0xff) {
4498             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4499             switch (lit) {
4500             case 0:
4501               break; /* handled above */
4502 /*
4503             case 0xff:
4504               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4505               while(size--)
4506                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4507               genSkipz2(&rFalseIfx,0);
4508               break;
4509 */
4510             default:
4511               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4512               while(--size)
4513                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4514
4515               emitSKPZ;
4516               if(rFalseIfx.condition)
4517                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4518               else
4519                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4520
4521
4522               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4523               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4524
4525               rFalseIfx.condition ^= 1;
4526               genSkipc(&rFalseIfx);
4527             }
4528
4529             pic16_emitpLabel(truelbl->key);
4530
4531             if(ifx) ifx->generated = 1;
4532             return;
4533           }
4534
4535
4536           lit++;
4537           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4538           i = (lit >> (size*8)) & 0xff;
4539
4540           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4541           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4542
4543           while(size--) {
4544             i = (lit >> (size*8)) & 0xff;
4545
4546             if(i) {
4547               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4548               emitSKPNZ;
4549               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4550             } else {
4551               /* this byte of the lit is zero, 
4552                *if it's not the last then OR in the variable */
4553               if(size)
4554                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4555             }
4556           }
4557
4558
4559           pic16_emitpLabel(lbl->key);
4560
4561           rFalseIfx.condition ^= 1;
4562           genSkipc(&rFalseIfx);
4563         }
4564
4565         if(sign)
4566           pic16_emitpLabel(truelbl->key);
4567         if(ifx) ifx->generated = 1;
4568         return;
4569       }
4570     }
4571     /* Compare two variables */
4572
4573     DEBUGpic16_emitcode(";sign","%d",sign);
4574
4575     size--;
4576     if(sign) {
4577       /* Sigh. thus sucks... */
4578       if(size) {
4579         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4580         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4581         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4582         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4583         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4584         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4585       } else {
4586         /* Signed char comparison */
4587         /* Special thanks to Nikolai Golovchenko for this snippet */
4588         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4589         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4590         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
4591         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4592         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4593         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4594
4595         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4596         genSkipc(&rFalseIfx);
4597           
4598         if(ifx) ifx->generated = 1;
4599         return;
4600       }
4601
4602     } else {
4603
4604       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4605       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4606     }
4607
4608
4609     /* The rest of the bytes of a multi-byte compare */
4610     while (size) {
4611
4612       emitSKPZ;
4613       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
4614       size--;
4615
4616       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4617       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4618
4619
4620     }
4621
4622     pic16_emitpLabel(lbl->key);
4623
4624     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4625     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4626         (AOP_TYPE(result) == AOP_REG)) {
4627       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4628       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4629     } else {
4630       genSkipc(&rFalseIfx);
4631     }         
4632     //genSkipc(&rFalseIfx);
4633     if(ifx) ifx->generated = 1;
4634
4635     return;
4636
4637   }
4638
4639   // check_carry:
4640   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4641     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4642     pic16_outBitC(result);
4643   } else {
4644     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4645     /* if the result is used in the next
4646        ifx conditional branch then generate
4647        code a little differently */
4648     if (ifx )
4649       genIfxJump (ifx,"c");
4650     else
4651       pic16_outBitC(result);
4652     /* leave the result in acc */
4653   }
4654
4655 }
4656
4657 /*-----------------------------------------------------------------*/
4658 /* genCmpGt :- greater than comparison                             */
4659 /*-----------------------------------------------------------------*/
4660 static void genCmpGt (iCode *ic, iCode *ifx)
4661 {
4662     operand *left, *right, *result;
4663     sym_link *letype , *retype;
4664     int sign ;
4665
4666     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4667     left = IC_LEFT(ic);
4668     right= IC_RIGHT(ic);
4669     result = IC_RESULT(ic);
4670
4671     letype = getSpec(operandType(left));
4672     retype =getSpec(operandType(right));
4673     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4674     /* assign the amsops */
4675     pic16_aopOp (left,ic,FALSE);
4676     pic16_aopOp (right,ic,FALSE);
4677     pic16_aopOp (result,ic,TRUE);
4678
4679     genCmp(right, left, result, ifx, sign);
4680
4681     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4682     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4683     pic16_freeAsmop(result,NULL,ic,TRUE); 
4684 }
4685
4686 /*-----------------------------------------------------------------*/
4687 /* genCmpLt - less than comparisons                                */
4688 /*-----------------------------------------------------------------*/
4689 static void genCmpLt (iCode *ic, iCode *ifx)
4690 {
4691     operand *left, *right, *result;
4692     sym_link *letype , *retype;
4693     int sign ;
4694
4695     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4696     left = IC_LEFT(ic);
4697     right= IC_RIGHT(ic);
4698     result = IC_RESULT(ic);
4699
4700     letype = getSpec(operandType(left));
4701     retype =getSpec(operandType(right));
4702     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4703
4704     /* assign the amsops */
4705     pic16_aopOp (left,ic,FALSE);
4706     pic16_aopOp (right,ic,FALSE);
4707     pic16_aopOp (result,ic,TRUE);
4708
4709     genCmp(left, right, result, ifx, sign);
4710
4711     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4712     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4713     pic16_freeAsmop(result,NULL,ic,TRUE); 
4714 }
4715
4716 /*-----------------------------------------------------------------*/
4717 /* genc16bit2lit - compare a 16 bit value to a literal             */
4718 /*-----------------------------------------------------------------*/
4719 static void genc16bit2lit(operand *op, int lit, int offset)
4720 {
4721   int i;
4722
4723   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4724   if( (lit&0xff) == 0) 
4725     i=1;
4726   else
4727     i=0;
4728
4729   switch( BYTEofLONG(lit,i)) { 
4730   case 0:
4731     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4732     break;
4733   case 1:
4734     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4735     break;
4736   case 0xff:
4737     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4738     break;
4739   default:
4740     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4741     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4742   }
4743
4744   i ^= 1;
4745
4746   switch( BYTEofLONG(lit,i)) { 
4747   case 0:
4748     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
4749     break;
4750   case 1:
4751     emitSKPNZ;
4752     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4753     break;
4754   case 0xff:
4755     emitSKPNZ;
4756     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4757     break;
4758   default:
4759     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4760     emitSKPNZ;
4761     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
4762
4763   }
4764
4765 }
4766
4767 /*-----------------------------------------------------------------*/
4768 /* gencjneshort - compare and jump if not equal                    */
4769 /*-----------------------------------------------------------------*/
4770 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4771 {
4772   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4773   int offset = 0;
4774   int res_offset = 0;  /* the result may be a different size then left or right */
4775   int res_size = AOP_SIZE(result);
4776   resolvedIfx rIfx;
4777   symbol *lbl;
4778
4779   unsigned long lit = 0L;
4780   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4781   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4782   if(result)
4783     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4784   resolveIfx(&rIfx,ifx);
4785   lbl =  newiTempLabel(NULL);
4786
4787
4788   /* if the left side is a literal or 
4789      if the right is in a pointer register and left 
4790      is not */
4791   if ((AOP_TYPE(left) == AOP_LIT) || 
4792       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4793     operand *t = right;
4794     right = left;
4795     left = t;
4796   }
4797   if(AOP_TYPE(right) == AOP_LIT)
4798     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4799
4800   /* if the right side is a literal then anything goes */
4801   if (AOP_TYPE(right) == AOP_LIT &&
4802       AOP_TYPE(left) != AOP_DIR ) {
4803     switch(size) {
4804     case 2:
4805       genc16bit2lit(left, lit, 0);
4806       emitSKPNZ;
4807       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4808       break;
4809     default:
4810       while (size--) {
4811         if(lit & 0xff) {
4812           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4813           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4814         } else {
4815           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4816         }
4817
4818         emitSKPNZ;
4819         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4820         offset++;
4821         if(res_offset < res_size-1)
4822           res_offset++;
4823         lit >>= 8;
4824       }
4825       break;
4826     }
4827   }
4828
4829   /* if the right side is in a register or in direct space or
4830      if the left is a pointer register & right is not */    
4831   else if (AOP_TYPE(right) == AOP_REG ||
4832            AOP_TYPE(right) == AOP_DIR || 
4833            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4834            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4835     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4836     int lbl_key = lbl->key;
4837
4838     if(result) {
4839       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
4840       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4841     }else {
4842       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4843       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4844               __FUNCTION__,__LINE__);
4845       return;
4846     }
4847
4848 /*     switch(size) { */
4849 /*     case 2: */
4850 /*       genc16bit2lit(left, lit, 0); */
4851 /*       emitSKPNZ; */
4852 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
4853 /*       break; */
4854 /*     default: */
4855     while (size--) {
4856       int emit_skip=1;
4857       if((AOP_TYPE(left) == AOP_DIR) && 
4858          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4859
4860         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4861         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4862
4863       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4864             
4865         switch (lit & 0xff) {
4866         case 0:
4867           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4868           break;
4869         case 1:
4870           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4871           pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4872           //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4873           emit_skip=0;
4874           break;
4875         case 0xff:
4876           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4877           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4878           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4879           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4880           emit_skip=0;
4881           break;
4882         default:
4883           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4884           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4885         }
4886         lit >>= 8;
4887
4888       } else {
4889         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4890       }
4891       if(emit_skip) {
4892         if(AOP_TYPE(result) == AOP_CRY) {
4893           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4894           if(rIfx.condition)
4895             emitSKPNZ;
4896           else
4897             emitSKPZ;
4898           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4899         } else {
4900           /* fix me. probably need to check result size too */
4901           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
4902           if(rIfx.condition)
4903             emitSKPZ;
4904           else
4905             emitSKPNZ;
4906           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4907           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4908         }
4909         if(ifx)
4910           ifx->generated=1;
4911       }
4912       emit_skip++;
4913       offset++;
4914       if(res_offset < res_size-1)
4915         res_offset++;
4916     }
4917 /*       break; */
4918 /*     } */
4919   } else if(AOP_TYPE(right) == AOP_REG &&
4920             AOP_TYPE(left) != AOP_DIR){
4921
4922     while(size--) {
4923       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4924       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4925       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4926       if(rIfx.condition)
4927         emitSKPNZ;
4928       else
4929         emitSKPZ;
4930       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4931       offset++;
4932       if(res_offset < res_size-1)
4933         res_offset++;
4934     }
4935       
4936   }else{
4937     /* right is a pointer reg need both a & b */
4938     while(size--) {
4939       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
4940       if(strcmp(l,"b"))
4941         pic16_emitcode("mov","b,%s",l);
4942       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
4943       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4944       offset++;
4945     }
4946   }
4947
4948   pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4949   if(!rIfx.condition)
4950     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4951
4952   pic16_emitpLabel(lbl->key);
4953
4954   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4955
4956   if(ifx)
4957     ifx->generated = 1;
4958 }
4959
4960 #if 0
4961 /*-----------------------------------------------------------------*/
4962 /* gencjne - compare and jump if not equal                         */
4963 /*-----------------------------------------------------------------*/
4964 static void gencjne(operand *left, operand *right, iCode *ifx)
4965 {
4966     symbol *tlbl  = newiTempLabel(NULL);
4967
4968     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4969     gencjneshort(left, right, lbl);
4970
4971     pic16_emitcode("mov","a,%s",one);
4972     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4973     pic16_emitcode("","%05d_DS_:",lbl->key+100);
4974     pic16_emitcode("clr","a");
4975     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
4976
4977     pic16_emitpLabel(lbl->key);
4978     pic16_emitpLabel(tlbl->key);
4979
4980 }
4981 #endif
4982
4983 /*-----------------------------------------------------------------*/
4984 /* genCmpEq - generates code for equal to                          */
4985 /*-----------------------------------------------------------------*/
4986 static void genCmpEq (iCode *ic, iCode *ifx)
4987 {
4988     operand *left, *right, *result;
4989     unsigned long lit = 0L;
4990     int size,offset=0;
4991     symbol *falselbl  = newiTempLabel(NULL);
4992
4993
4994     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4995
4996     if(ifx)
4997       DEBUGpic16_emitcode ("; ifx is non-null","");
4998     else
4999       DEBUGpic16_emitcode ("; ifx is null","");
5000
5001     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5002     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5003     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5004
5005     size = max(AOP_SIZE(left),AOP_SIZE(right));
5006
5007     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5008
5009     /* if literal, literal on the right or 
5010     if the right is in a pointer register and left 
5011     is not */
5012     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5013         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5014       operand *tmp = right ;
5015       right = left;
5016       left = tmp;
5017     }
5018
5019
5020     if(ifx && !AOP_SIZE(result)){
5021         symbol *tlbl;
5022         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5023         /* if they are both bit variables */
5024         if (AOP_TYPE(left) == AOP_CRY &&
5025             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5026                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5027             if(AOP_TYPE(right) == AOP_LIT){
5028                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5029                 if(lit == 0L){
5030                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5031                     pic16_emitcode("cpl","c");
5032                 } else if(lit == 1L) {
5033                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5034                 } else {
5035                     pic16_emitcode("clr","c");
5036                 }
5037                 /* AOP_TYPE(right) == AOP_CRY */
5038             } else {
5039                 symbol *lbl = newiTempLabel(NULL);
5040                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5041                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5042                 pic16_emitcode("cpl","c");
5043                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5044             }
5045             /* if true label then we jump if condition
5046             supplied is true */
5047             tlbl = newiTempLabel(NULL);
5048             if ( IC_TRUE(ifx) ) {
5049                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5050                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5051             } else {
5052                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5053                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5054             }
5055             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5056
5057                 {
5058                 /* left and right are both bit variables, result is carry */
5059                         resolvedIfx rIfx;
5060               
5061                         resolveIfx(&rIfx,ifx);
5062
5063                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5064                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5065                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5066                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5067                         genSkipz2(&rIfx,0);
5068                 }
5069         } else {
5070
5071                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5072
5073                         /* They're not both bit variables. Is the right a literal? */
5074                         if(AOP_TYPE(right) == AOP_LIT) {
5075                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5076             
5077                         switch(size) {
5078
5079                                 case 1:
5080                                         switch(lit & 0xff) {
5081                                                 case 1:
5082                                                                 if ( IC_TRUE(ifx) ) {
5083                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5084                                                                         emitSKPNZ;
5085                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5086                                                                 } else {
5087                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5088                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5089                                                                 }
5090                                                                 break;
5091                                                 case 0xff:
5092                                                                 if ( IC_TRUE(ifx) ) {
5093                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5094                                                                         emitSKPNZ;
5095                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5096                                                                 } else {
5097                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5098                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5099                                                                 }
5100                                                                 break;
5101                                                 default:
5102                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5103                                                                 if(lit)
5104                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5105                                                                 genSkip(ifx,'z');
5106                                         } // switch lit
5107
5108
5109                                         /* end of size == 1 */
5110                                         break;
5111               
5112                                 case 2:
5113                                         genc16bit2lit(left,lit,offset);
5114                                         genSkip(ifx,'z');
5115                                         break;
5116                                         /* end of size == 2 */
5117
5118                                 default:
5119                                         /* size is 4 */
5120                                         if(lit==0) {
5121                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5122                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5123                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5124                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5125                                                 genSkip(ifx,'z');
5126                                         } else {
5127                                                 /* search for patterns that can be optimized */
5128
5129                                                 genc16bit2lit(left,lit,0);
5130                                                 lit >>= 16;
5131                                                 if(lit) {
5132                                                                 if(IC_TRUE(ifx))
5133                                                                 emitSKPZ; // if hi word unequal
5134                                                                 else
5135                                                                 emitSKPNZ; // if hi word equal
5136                                                                 // fail early
5137                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5138                                                         genc16bit2lit(left,lit,2);
5139                                                         genSkip(ifx,'z');
5140                                                 } else {
5141                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5142                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5143                                                         genSkip(ifx,'z');
5144                                                 }
5145                                         }
5146                                                 pic16_emitpLabel(falselbl->key);
5147                                                 break;
5148
5149                         } // switch size
5150           
5151                         ifx->generated = 1;
5152                         goto release ;
5153             
5154
5155           } else if(AOP_TYPE(right) == AOP_CRY ) {
5156             /* we know the left is not a bit, but that the right is */
5157             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5158             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5159                       pic16_popGet(AOP(right),offset));
5160             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5161
5162             /* if the two are equal, then W will be 0 and the Z bit is set
5163              * we could test Z now, or go ahead and check the high order bytes if
5164              * the variable we're comparing is larger than a byte. */
5165
5166             while(--size)
5167               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5168
5169             if ( IC_TRUE(ifx) ) {
5170               emitSKPNZ;
5171               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5172               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5173             } else {
5174               emitSKPZ;
5175               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5176               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5177             }
5178
5179           } else {
5180             /* They're both variables that are larger than bits */
5181             int s = size;
5182
5183             tlbl = newiTempLabel(NULL);
5184
5185             while(size--) {
5186               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5187               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5188
5189               if ( IC_TRUE(ifx) ) {
5190                 if(size) {
5191                   emitSKPZ;
5192                 
5193                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5194
5195                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5196                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5197                 } else {
5198                   emitSKPNZ;
5199
5200                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5201
5202
5203                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5204                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5205                 }
5206               } else {
5207                 emitSKPZ;
5208
5209                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5210
5211                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5212                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5213               }
5214               offset++;
5215             }
5216             if(s>1 && IC_TRUE(ifx)) {
5217               pic16_emitpLabel(tlbl->key);
5218               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5219             }
5220           }
5221         }
5222         /* mark the icode as generated */
5223         ifx->generated = 1;
5224         goto release ;
5225     }
5226
5227     /* if they are both bit variables */
5228     if (AOP_TYPE(left) == AOP_CRY &&
5229         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5230         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5231         if(AOP_TYPE(right) == AOP_LIT){
5232             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5233             if(lit == 0L){
5234                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5235                 pic16_emitcode("cpl","c");
5236             } else if(lit == 1L) {
5237                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5238             } else {
5239                 pic16_emitcode("clr","c");
5240             }
5241             /* AOP_TYPE(right) == AOP_CRY */
5242         } else {
5243             symbol *lbl = newiTempLabel(NULL);
5244             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5245             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5246             pic16_emitcode("cpl","c");
5247             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5248         }
5249         /* c = 1 if egal */
5250         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5251             pic16_outBitC(result);
5252             goto release ;
5253         }
5254         if (ifx) {
5255             genIfxJump (ifx,"c");
5256             goto release ;
5257         }
5258         /* if the result is used in an arithmetic operation
5259         then put the result in place */
5260         pic16_outBitC(result);
5261     } else {
5262       
5263       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5264       gencjne(left,right,result,ifx);
5265 /*
5266       if(ifx) 
5267         gencjne(left,right,newiTempLabel(NULL));
5268       else {
5269         if(IC_TRUE(ifx)->key)
5270           gencjne(left,right,IC_TRUE(ifx)->key);
5271         else
5272           gencjne(left,right,IC_FALSE(ifx)->key);
5273         ifx->generated = 1;
5274         goto release ;
5275       }
5276       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5277         pic16_aopPut(AOP(result),"a",0);
5278         goto release ;
5279       }
5280
5281       if (ifx) {
5282         genIfxJump (ifx,"a");
5283         goto release ;
5284       }
5285 */
5286       /* if the result is used in an arithmetic operation
5287          then put the result in place */
5288 /*
5289       if (AOP_TYPE(result) != AOP_CRY) 
5290         pic16_outAcc(result);
5291 */
5292       /* leave the result in acc */
5293     }
5294
5295 release:
5296     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5297     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5298     pic16_freeAsmop(result,NULL,ic,TRUE);
5299 }
5300
5301 /*-----------------------------------------------------------------*/
5302 /* ifxForOp - returns the icode containing the ifx for operand     */
5303 /*-----------------------------------------------------------------*/
5304 static iCode *ifxForOp ( operand *op, iCode *ic )
5305 {
5306     /* if true symbol then needs to be assigned */
5307     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5308     if (IS_TRUE_SYMOP(op))
5309         return NULL ;
5310
5311     /* if this has register type condition and
5312     the next instruction is ifx with the same operand
5313     and live to of the operand is upto the ifx only then */
5314     if (ic->next &&
5315         ic->next->op == IFX &&
5316         IC_COND(ic->next)->key == op->key &&
5317         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5318         return ic->next;
5319
5320     if (ic->next &&
5321         ic->next->op == IFX &&
5322         IC_COND(ic->next)->key == op->key) {
5323       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5324       return ic->next;
5325     }
5326
5327     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5328     if (ic->next &&
5329         ic->next->op == IFX)
5330       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5331
5332     if (ic->next &&
5333         ic->next->op == IFX &&
5334         IC_COND(ic->next)->key == op->key) {
5335       DEBUGpic16_emitcode ("; "," key is okay");
5336       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5337                            OP_SYMBOL(op)->liveTo,
5338                            ic->next->seq);
5339     }
5340
5341
5342     return NULL;
5343 }
5344 /*-----------------------------------------------------------------*/
5345 /* genAndOp - for && operation                                     */
5346 /*-----------------------------------------------------------------*/
5347 static void genAndOp (iCode *ic)
5348 {
5349     operand *left,*right, *result;
5350 /*     symbol *tlbl; */
5351
5352     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5353     /* note here that && operations that are in an
5354     if statement are taken away by backPatchLabels
5355     only those used in arthmetic operations remain */
5356     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5357     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5358     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5359
5360     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5361
5362     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5363     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5364     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5365
5366     /* if both are bit variables */
5367 /*     if (AOP_TYPE(left) == AOP_CRY && */
5368 /*         AOP_TYPE(right) == AOP_CRY ) { */
5369 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5370 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5371 /*         pic16_outBitC(result); */
5372 /*     } else { */
5373 /*         tlbl = newiTempLabel(NULL); */
5374 /*         pic16_toBoolean(left);     */
5375 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5376 /*         pic16_toBoolean(right); */
5377 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5378 /*         pic16_outBitAcc(result); */
5379 /*     } */
5380
5381     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5382     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5383     pic16_freeAsmop(result,NULL,ic,TRUE);
5384 }
5385
5386
5387 /*-----------------------------------------------------------------*/
5388 /* genOrOp - for || operation                                      */
5389 /*-----------------------------------------------------------------*/
5390 /*
5391   tsd pic port -
5392   modified this code, but it doesn't appear to ever get called
5393 */
5394
5395 static void genOrOp (iCode *ic)
5396 {
5397     operand *left,*right, *result;
5398     symbol *tlbl;
5399
5400     /* note here that || operations that are in an
5401     if statement are taken away by backPatchLabels
5402     only those used in arthmetic operations remain */
5403     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5404     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5405     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5406     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5407
5408     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5409
5410     /* if both are bit variables */
5411     if (AOP_TYPE(left) == AOP_CRY &&
5412         AOP_TYPE(right) == AOP_CRY ) {
5413       pic16_emitcode("clrc","");
5414       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5415                AOP(left)->aopu.aop_dir,
5416                AOP(left)->aopu.aop_dir);
5417       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5418                AOP(right)->aopu.aop_dir,
5419                AOP(right)->aopu.aop_dir);
5420       pic16_emitcode("setc","");
5421
5422     } else {
5423         tlbl = newiTempLabel(NULL);
5424         pic16_toBoolean(left);
5425         emitSKPZ;
5426         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5427         pic16_toBoolean(right);
5428         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5429
5430         pic16_outBitAcc(result);
5431     }
5432
5433     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5434     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5435     pic16_freeAsmop(result,NULL,ic,TRUE);            
5436 }
5437
5438 /*-----------------------------------------------------------------*/
5439 /* isLiteralBit - test if lit == 2^n                               */
5440 /*-----------------------------------------------------------------*/
5441 static int isLiteralBit(unsigned long lit)
5442 {
5443     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5444     0x100L,0x200L,0x400L,0x800L,
5445     0x1000L,0x2000L,0x4000L,0x8000L,
5446     0x10000L,0x20000L,0x40000L,0x80000L,
5447     0x100000L,0x200000L,0x400000L,0x800000L,
5448     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5449     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5450     int idx;
5451     
5452     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5453     for(idx = 0; idx < 32; idx++)
5454         if(lit == pw[idx])
5455             return idx+1;
5456     return 0;
5457 }
5458
5459 /*-----------------------------------------------------------------*/
5460 /* continueIfTrue -                                                */
5461 /*-----------------------------------------------------------------*/
5462 static void continueIfTrue (iCode *ic)
5463 {
5464     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5465     if(IC_TRUE(ic))
5466         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5467     ic->generated = 1;
5468 }
5469
5470 /*-----------------------------------------------------------------*/
5471 /* jmpIfTrue -                                                     */
5472 /*-----------------------------------------------------------------*/
5473 static void jumpIfTrue (iCode *ic)
5474 {
5475     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5476     if(!IC_TRUE(ic))
5477         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5478     ic->generated = 1;
5479 }
5480
5481 /*-----------------------------------------------------------------*/
5482 /* jmpTrueOrFalse -                                                */
5483 /*-----------------------------------------------------------------*/
5484 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5485 {
5486     // ugly but optimized by peephole
5487     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5488     if(IC_TRUE(ic)){
5489         symbol *nlbl = newiTempLabel(NULL);
5490         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5491         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5492         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5493         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5494     }
5495     else{
5496         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5497         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5498     }
5499     ic->generated = 1;
5500 }
5501
5502 /*-----------------------------------------------------------------*/
5503 /* genAnd  - code for and                                          */
5504 /*-----------------------------------------------------------------*/
5505 static void genAnd (iCode *ic, iCode *ifx)
5506 {
5507   operand *left, *right, *result;
5508   int size, offset=0;  
5509   unsigned long lit = 0L;
5510   int bytelit = 0;
5511   resolvedIfx rIfx;
5512
5513
5514   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5515   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5516   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5517   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5518
5519   resolveIfx(&rIfx,ifx);
5520
5521   /* if left is a literal & right is not then exchange them */
5522   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5523       AOP_NEEDSACC(left)) {
5524     operand *tmp = right ;
5525     right = left;
5526     left = tmp;
5527   }
5528
5529   /* if result = right then exchange them */
5530   if(pic16_sameRegs(AOP(result),AOP(right))){
5531     operand *tmp = right ;
5532     right = left;
5533     left = tmp;
5534   }
5535
5536   /* if right is bit then exchange them */
5537   if (AOP_TYPE(right) == AOP_CRY &&
5538       AOP_TYPE(left) != AOP_CRY){
5539     operand *tmp = right ;
5540     right = left;
5541     left = tmp;
5542   }
5543   if(AOP_TYPE(right) == AOP_LIT)
5544     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5545
5546   size = AOP_SIZE(result);
5547
5548   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5549
5550   // if(bit & yy)
5551   // result = bit & yy;
5552   if (AOP_TYPE(left) == AOP_CRY){
5553     // c = bit & literal;
5554     if(AOP_TYPE(right) == AOP_LIT){
5555       if(lit & 1) {
5556         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5557           // no change
5558           goto release;
5559         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5560       } else {
5561         // bit(result) = 0;
5562         if(size && (AOP_TYPE(result) == AOP_CRY)){
5563           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5564           goto release;
5565         }
5566         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5567           jumpIfTrue(ifx);
5568           goto release;
5569         }
5570         pic16_emitcode("clr","c");
5571       }
5572     } else {
5573       if (AOP_TYPE(right) == AOP_CRY){
5574         // c = bit & bit;
5575         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5576         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5577       } else {
5578         // c = bit & val;
5579         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5580         // c = lsb
5581         pic16_emitcode("rrc","a");
5582         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5583       }
5584     }
5585     // bit = c
5586     // val = c
5587     if(size)
5588       pic16_outBitC(result);
5589     // if(bit & ...)
5590     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5591       genIfxJump(ifx, "c");           
5592     goto release ;
5593   }
5594
5595   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5596   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5597   if((AOP_TYPE(right) == AOP_LIT) &&
5598      (AOP_TYPE(result) == AOP_CRY) &&
5599      (AOP_TYPE(left) != AOP_CRY)){
5600     int posbit = isLiteralBit(lit);
5601     /* left &  2^n */
5602     if(posbit){
5603       posbit--;
5604       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5605       // bit = left & 2^n
5606       if(size)
5607         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5608       // if(left &  2^n)
5609       else{
5610         if(ifx){
5611 /*
5612           if(IC_TRUE(ifx)) {
5613             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5614             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5615           } else {
5616             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5617             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5618           }
5619 */
5620           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5621                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5622           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5623           
5624           ifx->generated = 1;
5625         }
5626         goto release;
5627       }
5628     } else {
5629       symbol *tlbl = newiTempLabel(NULL);
5630       int sizel = AOP_SIZE(left);
5631       if(size)
5632         pic16_emitcode("setb","c");
5633       while(sizel--){
5634         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5635           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5636           // byte ==  2^n ?
5637           if((posbit = isLiteralBit(bytelit)) != 0)
5638             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5639           else{
5640             if(bytelit != 0x0FFL)
5641               pic16_emitcode("anl","a,%s",
5642                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
5643             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5644           }
5645         }
5646         offset++;
5647       }
5648       // bit = left & literal
5649       if(size){
5650         pic16_emitcode("clr","c");
5651         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5652       }
5653       // if(left & literal)
5654       else{
5655         if(ifx)
5656           jmpTrueOrFalse(ifx, tlbl);
5657         goto release ;
5658       }
5659     }
5660     pic16_outBitC(result);
5661     goto release ;
5662   }
5663
5664   /* if left is same as result */
5665   if(pic16_sameRegs(AOP(result),AOP(left))){
5666     int know_W = -1;
5667     for(;size--; offset++,lit>>=8) {
5668       if(AOP_TYPE(right) == AOP_LIT){
5669         switch(lit & 0xff) {
5670         case 0x00:
5671           /*  and'ing with 0 has clears the result */
5672 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5673           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5674           break;
5675         case 0xff:
5676           /* and'ing with 0xff is a nop when the result and left are the same */
5677           break;
5678
5679         default:
5680           {
5681             int p = my_powof2( (~lit) & 0xff );
5682             if(p>=0) {
5683               /* only one bit is set in the literal, so use a bcf instruction */
5684 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5685               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5686
5687             } else {
5688               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5689               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5690               if(know_W != (lit&0xff))
5691                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5692               know_W = lit &0xff;
5693               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5694             }
5695           }    
5696         }
5697       } else {
5698         if (AOP_TYPE(left) == AOP_ACC) {
5699           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5700         } else {                    
5701           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5702           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5703
5704         }
5705       }
5706     }
5707
5708   } else {
5709     // left & result in different registers
5710     if(AOP_TYPE(result) == AOP_CRY){
5711       // result = bit
5712       // if(size), result in bit
5713       // if(!size && ifx), conditional oper: if(left & right)
5714       symbol *tlbl = newiTempLabel(NULL);
5715       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5716       if(size)
5717         pic16_emitcode("setb","c");
5718       while(sizer--){
5719         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5720         pic16_emitcode("anl","a,%s",
5721                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5722         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5723         offset++;
5724       }
5725       if(size){
5726         CLRC;
5727         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5728         pic16_outBitC(result);
5729       } else if(ifx)
5730         jmpTrueOrFalse(ifx, tlbl);
5731     } else {
5732       for(;(size--);offset++) {
5733         // normal case
5734         // result = left & right
5735         if(AOP_TYPE(right) == AOP_LIT){
5736           int t = (lit >> (offset*8)) & 0x0FFL;
5737           switch(t) { 
5738           case 0x00:
5739             pic16_emitcode("clrf","%s",
5740                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5741             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5742             break;
5743           case 0xff:
5744             pic16_emitcode("movf","%s,w",
5745                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5746             pic16_emitcode("movwf","%s",
5747                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5748             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5749             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5750             break;
5751           default:
5752             pic16_emitcode("movlw","0x%x",t);
5753             pic16_emitcode("andwf","%s,w",
5754                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5755             pic16_emitcode("movwf","%s",
5756                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5757               
5758             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5759             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5760             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5761           }
5762           continue;
5763         }
5764
5765         if (AOP_TYPE(left) == AOP_ACC) {
5766           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5767           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5768         } else {
5769           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5770           pic16_emitcode("andwf","%s,w",
5771                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5772           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5773           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5774         }
5775         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5776         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5777       }
5778     }
5779   }
5780
5781   release :
5782     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5783   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5784   pic16_freeAsmop(result,NULL,ic,TRUE);     
5785 }
5786
5787 /*-----------------------------------------------------------------*/
5788 /* genOr  - code for or                                            */
5789 /*-----------------------------------------------------------------*/
5790 static void genOr (iCode *ic, iCode *ifx)
5791 {
5792     operand *left, *right, *result;
5793     int size, offset=0;
5794     unsigned long lit = 0L;
5795
5796     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5797
5798     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5799     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5800     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5801
5802     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5803
5804     /* if left is a literal & right is not then exchange them */
5805     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5806         AOP_NEEDSACC(left)) {
5807         operand *tmp = right ;
5808         right = left;
5809         left = tmp;
5810     }
5811
5812     /* if result = right then exchange them */
5813     if(pic16_sameRegs(AOP(result),AOP(right))){
5814         operand *tmp = right ;
5815         right = left;
5816         left = tmp;
5817     }
5818
5819     /* if right is bit then exchange them */
5820     if (AOP_TYPE(right) == AOP_CRY &&
5821         AOP_TYPE(left) != AOP_CRY){
5822         operand *tmp = right ;
5823         right = left;
5824         left = tmp;
5825     }
5826
5827     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5828
5829     if(AOP_TYPE(right) == AOP_LIT)
5830         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5831
5832     size = AOP_SIZE(result);
5833
5834     // if(bit | yy)
5835     // xx = bit | yy;
5836     if (AOP_TYPE(left) == AOP_CRY){
5837         if(AOP_TYPE(right) == AOP_LIT){
5838             // c = bit & literal;
5839             if(lit){
5840                 // lit != 0 => result = 1
5841                 if(AOP_TYPE(result) == AOP_CRY){
5842                   if(size)
5843                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5844                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5845                   //     AOP(result)->aopu.aop_dir,
5846                   //     AOP(result)->aopu.aop_dir);
5847                     else if(ifx)
5848                         continueIfTrue(ifx);
5849                     goto release;
5850                 }
5851             } else {
5852                 // lit == 0 => result = left
5853                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5854                     goto release;
5855                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5856             }
5857         } else {
5858             if (AOP_TYPE(right) == AOP_CRY){
5859               if(pic16_sameRegs(AOP(result),AOP(left))){
5860                 // c = bit | bit;
5861                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5862                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5863                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5864
5865                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5866                          AOP(result)->aopu.aop_dir,
5867                          AOP(result)->aopu.aop_dir);
5868                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5869                          AOP(right)->aopu.aop_dir,
5870                          AOP(right)->aopu.aop_dir);
5871                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5872                          AOP(result)->aopu.aop_dir,
5873                          AOP(result)->aopu.aop_dir);
5874               } else {
5875                 if( AOP_TYPE(result) == AOP_ACC) {
5876                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5877                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5878                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5879                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5880
5881                 } else {
5882
5883                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5884                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5885                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5886                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5887
5888                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5889                                  AOP(result)->aopu.aop_dir,
5890                                  AOP(result)->aopu.aop_dir);
5891                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5892                                  AOP(right)->aopu.aop_dir,
5893                                  AOP(right)->aopu.aop_dir);
5894                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5895                                  AOP(left)->aopu.aop_dir,
5896                                  AOP(left)->aopu.aop_dir);
5897                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5898                                  AOP(result)->aopu.aop_dir,
5899                                  AOP(result)->aopu.aop_dir);
5900                 }
5901               }
5902             } else {
5903                 // c = bit | val;
5904                 symbol *tlbl = newiTempLabel(NULL);
5905                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5906
5907
5908                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5909                 if( AOP_TYPE(right) == AOP_ACC) {
5910                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5911                   emitSKPNZ;
5912                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5913                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5914                 }
5915
5916
5917
5918                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5919                     pic16_emitcode(";XXX setb","c");
5920                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5921                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5922                 pic16_toBoolean(right);
5923                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5924                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5925                     jmpTrueOrFalse(ifx, tlbl);
5926                     goto release;
5927                 } else {
5928                     CLRC;
5929                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5930                 }
5931             }
5932         }
5933         // bit = c
5934         // val = c
5935         if(size)
5936             pic16_outBitC(result);
5937         // if(bit | ...)
5938         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5939             genIfxJump(ifx, "c");           
5940         goto release ;
5941     }
5942
5943     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5944     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5945     if((AOP_TYPE(right) == AOP_LIT) &&
5946        (AOP_TYPE(result) == AOP_CRY) &&
5947        (AOP_TYPE(left) != AOP_CRY)){
5948         if(lit){
5949           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5950             // result = 1
5951             if(size)
5952                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5953             else 
5954                 continueIfTrue(ifx);
5955             goto release;
5956         } else {
5957           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5958             // lit = 0, result = boolean(left)
5959             if(size)
5960                 pic16_emitcode(";XXX setb","c");
5961             pic16_toBoolean(right);
5962             if(size){
5963                 symbol *tlbl = newiTempLabel(NULL);
5964                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5965                 CLRC;
5966                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5967             } else {
5968                 genIfxJump (ifx,"a");
5969                 goto release;
5970             }
5971         }
5972         pic16_outBitC(result);
5973         goto release ;
5974     }
5975
5976     /* if left is same as result */
5977     if(pic16_sameRegs(AOP(result),AOP(left))){
5978       int know_W = -1;
5979       for(;size--; offset++,lit>>=8) {
5980         if(AOP_TYPE(right) == AOP_LIT){
5981           if((lit & 0xff) == 0)
5982             /*  or'ing with 0 has no effect */
5983             continue;
5984           else {
5985             int p = my_powof2(lit & 0xff);
5986             if(p>=0) {
5987               /* only one bit is set in the literal, so use a bsf instruction */
5988               pic16_emitpcode(POC_BSF,
5989                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5990             } else {
5991               if(know_W != (lit & 0xff))
5992                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5993               know_W = lit & 0xff;
5994               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5995             }
5996                     
5997           }
5998         } else {
5999           if (AOP_TYPE(left) == AOP_ACC) {
6000             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6001             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6002           } else {                  
6003             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6004             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6005
6006             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6007             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6008
6009           }
6010         }
6011       }
6012     } else {
6013         // left & result in different registers
6014         if(AOP_TYPE(result) == AOP_CRY){
6015             // result = bit
6016             // if(size), result in bit
6017             // if(!size && ifx), conditional oper: if(left | right)
6018             symbol *tlbl = newiTempLabel(NULL);
6019             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6020             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6021
6022
6023             if(size)
6024                 pic16_emitcode(";XXX setb","c");
6025             while(sizer--){
6026                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6027                 pic16_emitcode(";XXX orl","a,%s",
6028                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6029                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6030                 offset++;
6031             }
6032             if(size){
6033                 CLRC;
6034                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6035                 pic16_outBitC(result);
6036             } else if(ifx)
6037                 jmpTrueOrFalse(ifx, tlbl);
6038         } else for(;(size--);offset++){
6039           // normal case
6040           // result = left & right
6041           if(AOP_TYPE(right) == AOP_LIT){
6042             int t = (lit >> (offset*8)) & 0x0FFL;
6043             switch(t) { 
6044             case 0x00:
6045               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6046               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6047
6048               pic16_emitcode("movf","%s,w",
6049                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6050               pic16_emitcode("movwf","%s",
6051                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6052               break;
6053             default:
6054               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6055               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6056               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6057
6058               pic16_emitcode("movlw","0x%x",t);
6059               pic16_emitcode("iorwf","%s,w",
6060                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6061               pic16_emitcode("movwf","%s",
6062                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6063               
6064             }
6065             continue;
6066           }
6067
6068           // faster than result <- left, anl result,right
6069           // and better if result is SFR
6070           if (AOP_TYPE(left) == AOP_ACC) {
6071             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6072             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6073           } else {
6074             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6075             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6076
6077             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6078             pic16_emitcode("iorwf","%s,w",
6079                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6080           }
6081           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6082           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6083         }
6084     }
6085
6086 release :
6087     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6088     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6089     pic16_freeAsmop(result,NULL,ic,TRUE);     
6090 }
6091
6092 /*-----------------------------------------------------------------*/
6093 /* genXor - code for xclusive or                                   */
6094 /*-----------------------------------------------------------------*/
6095 static void genXor (iCode *ic, iCode *ifx)
6096 {
6097   operand *left, *right, *result;
6098   int size, offset=0;
6099   unsigned long lit = 0L;
6100
6101   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6102
6103   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6104   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6105   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6106
6107   /* if left is a literal & right is not ||
6108      if left needs acc & right does not */
6109   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6110       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6111     operand *tmp = right ;
6112     right = left;
6113     left = tmp;
6114   }
6115
6116   /* if result = right then exchange them */
6117   if(pic16_sameRegs(AOP(result),AOP(right))){
6118     operand *tmp = right ;
6119     right = left;
6120     left = tmp;
6121   }
6122
6123   /* if right is bit then exchange them */
6124   if (AOP_TYPE(right) == AOP_CRY &&
6125       AOP_TYPE(left) != AOP_CRY){
6126     operand *tmp = right ;
6127     right = left;
6128     left = tmp;
6129   }
6130   if(AOP_TYPE(right) == AOP_LIT)
6131     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6132
6133   size = AOP_SIZE(result);
6134
6135   // if(bit ^ yy)
6136   // xx = bit ^ yy;
6137   if (AOP_TYPE(left) == AOP_CRY){
6138     if(AOP_TYPE(right) == AOP_LIT){
6139       // c = bit & literal;
6140       if(lit>>1){
6141         // lit>>1  != 0 => result = 1
6142         if(AOP_TYPE(result) == AOP_CRY){
6143           if(size)
6144             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6145             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6146           else if(ifx)
6147             continueIfTrue(ifx);
6148           goto release;
6149         }
6150         pic16_emitcode("setb","c");
6151       } else{
6152         // lit == (0 or 1)
6153         if(lit == 0){
6154           // lit == 0, result = left
6155           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6156             goto release;
6157           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6158         } else{
6159           // lit == 1, result = not(left)
6160           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6161             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6162             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6163             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6164             goto release;
6165           } else {
6166             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6167             pic16_emitcode("cpl","c");
6168           }
6169         }
6170       }
6171
6172     } else {
6173       // right != literal
6174       symbol *tlbl = newiTempLabel(NULL);
6175       if (AOP_TYPE(right) == AOP_CRY){
6176         // c = bit ^ bit;
6177         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6178       }
6179       else{
6180         int sizer = AOP_SIZE(right);
6181         // c = bit ^ val
6182         // if val>>1 != 0, result = 1
6183         pic16_emitcode("setb","c");
6184         while(sizer){
6185           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6186           if(sizer == 1)
6187             // test the msb of the lsb
6188             pic16_emitcode("anl","a,#0xfe");
6189           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6190           sizer--;
6191         }
6192         // val = (0,1)
6193         pic16_emitcode("rrc","a");
6194       }
6195       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6196       pic16_emitcode("cpl","c");
6197       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6198     }
6199     // bit = c
6200     // val = c
6201     if(size)
6202       pic16_outBitC(result);
6203     // if(bit | ...)
6204     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6205       genIfxJump(ifx, "c");           
6206     goto release ;
6207   }
6208
6209   if(pic16_sameRegs(AOP(result),AOP(left))){
6210     /* if left is same as result */
6211     for(;size--; offset++) {
6212       if(AOP_TYPE(right) == AOP_LIT){
6213         int t  = (lit >> (offset*8)) & 0x0FFL;
6214         if(t == 0x00L)
6215           continue;
6216         else
6217           if (IS_AOP_PREG(left)) {
6218             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6219             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6220             pic16_aopPut(AOP(result),"a",offset);
6221           } else {
6222             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6223             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6224             pic16_emitcode("xrl","%s,%s",
6225                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6226                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6227           }
6228       } else {
6229         if (AOP_TYPE(left) == AOP_ACC)
6230           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6231         else {
6232           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6233           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6234 /*
6235           if (IS_AOP_PREG(left)) {
6236             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6237             pic16_aopPut(AOP(result),"a",offset);
6238           } else
6239             pic16_emitcode("xrl","%s,a",
6240                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6241 */
6242         }
6243       }
6244     }
6245   } else {
6246     // left & result in different registers
6247     if(AOP_TYPE(result) == AOP_CRY){
6248       // result = bit
6249       // if(size), result in bit
6250       // if(!size && ifx), conditional oper: if(left ^ right)
6251       symbol *tlbl = newiTempLabel(NULL);
6252       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6253       if(size)
6254         pic16_emitcode("setb","c");
6255       while(sizer--){
6256         if((AOP_TYPE(right) == AOP_LIT) &&
6257            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6258           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6259         } else {
6260           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6261           pic16_emitcode("xrl","a,%s",
6262                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6263         }
6264         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6265         offset++;
6266       }
6267       if(size){
6268         CLRC;
6269         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6270         pic16_outBitC(result);
6271       } else if(ifx)
6272         jmpTrueOrFalse(ifx, tlbl);
6273     } else for(;(size--);offset++){
6274       // normal case
6275       // result = left & right
6276       if(AOP_TYPE(right) == AOP_LIT){
6277         int t = (lit >> (offset*8)) & 0x0FFL;
6278         switch(t) { 
6279         case 0x00:
6280           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6281           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6282           pic16_emitcode("movf","%s,w",
6283                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6284           pic16_emitcode("movwf","%s",
6285                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6286           break;
6287         case 0xff:
6288           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6289           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6290           pic16_emitcode("comf","%s,w",
6291                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6292           pic16_emitcode("movwf","%s",
6293                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6294           break;
6295         default:
6296           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6297           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6298           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6299           pic16_emitcode("movlw","0x%x",t);
6300           pic16_emitcode("xorwf","%s,w",
6301                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6302           pic16_emitcode("movwf","%s",
6303                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6304
6305         }
6306         continue;
6307       }
6308
6309       // faster than result <- left, anl result,right
6310       // and better if result is SFR
6311       if (AOP_TYPE(left) == AOP_ACC) {
6312         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6313         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6314       } else {
6315         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6316         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6317         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6318         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6319       }
6320       if ( AOP_TYPE(result) != AOP_ACC){
6321         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6322         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6323       }
6324     }
6325   }
6326
6327   release :
6328     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6329   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6330   pic16_freeAsmop(result,NULL,ic,TRUE);     
6331 }
6332
6333 /*-----------------------------------------------------------------*/
6334 /* genInline - write the inline code out                           */
6335 /*-----------------------------------------------------------------*/
6336 static void genInline (iCode *ic)
6337 {
6338     char *buffer, *bp, *bp1;
6339     
6340     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6341
6342     _G.inLine += (!options.asmpeep);
6343
6344     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6345     strcpy(buffer,IC_INLINE(ic));
6346
6347     /* emit each line as a code */
6348     while (*bp) {
6349         if (*bp == '\n') {
6350             *bp++ = '\0';
6351
6352             if(*bp1)
6353               pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL));       //pic16_AssembleLine(bp1, 0));
6354                                         // inline directly, no process
6355             bp1 = bp;
6356         } else {
6357             if (*bp == ':') {
6358                 bp++;
6359                 *bp = '\0';
6360                 bp++;
6361                 pic16_emitcode(bp1,"");
6362                 bp1 = bp;
6363             } else
6364                 bp++;
6365         }
6366     }
6367     if ((bp1 != bp) && *bp1)
6368       pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL));               //pic16_AssembleLine(bp1, 0));
6369
6370     Safe_free(buffer);
6371
6372     _G.inLine -= (!options.asmpeep);
6373 }
6374
6375 /*-----------------------------------------------------------------*/
6376 /* genRRC - rotate right with carry                                */
6377 /*-----------------------------------------------------------------*/
6378 static void genRRC (iCode *ic)
6379 {
6380   operand *left , *result ;
6381   int size, offset = 0, same;
6382
6383   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6384
6385   /* rotate right with carry */
6386   left = IC_LEFT(ic);
6387   result=IC_RESULT(ic);
6388   pic16_aopOp (left,ic,FALSE);
6389   pic16_aopOp (result,ic,FALSE);
6390
6391   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6392
6393   same = pic16_sameRegs(AOP(result),AOP(left));
6394
6395   size = AOP_SIZE(result);    
6396
6397   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6398
6399   /* get the lsb and put it into the carry */
6400   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6401
6402   offset = 0 ;
6403
6404   while(size--) {
6405
6406     if(same) {
6407       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6408     } else {
6409       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6410       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6411     }
6412
6413     offset++;
6414   }
6415
6416   pic16_freeAsmop(left,NULL,ic,TRUE);
6417   pic16_freeAsmop(result,NULL,ic,TRUE);
6418 }
6419
6420 /*-----------------------------------------------------------------*/
6421 /* genRLC - generate code for rotate left with carry               */
6422 /*-----------------------------------------------------------------*/
6423 static void genRLC (iCode *ic)
6424 {    
6425   operand *left , *result ;
6426   int size, offset = 0;
6427   int same;
6428
6429   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6430   /* rotate right with carry */
6431   left = IC_LEFT(ic);
6432   result=IC_RESULT(ic);
6433   pic16_aopOp (left,ic,FALSE);
6434   pic16_aopOp (result,ic,FALSE);
6435
6436   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6437
6438   same = pic16_sameRegs(AOP(result),AOP(left));
6439
6440   /* move it to the result */
6441   size = AOP_SIZE(result);    
6442
6443   /* get the msb and put it into the carry */
6444   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6445
6446   offset = 0 ;
6447
6448   while(size--) {
6449
6450     if(same) {
6451       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6452     } else {
6453       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6454       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6455     }
6456
6457     offset++;
6458   }
6459
6460
6461   pic16_freeAsmop(left,NULL,ic,TRUE);
6462   pic16_freeAsmop(result,NULL,ic,TRUE);
6463 }
6464
6465 /*-----------------------------------------------------------------*/
6466 /* genGetHbit - generates code get highest order bit               */
6467 /*-----------------------------------------------------------------*/
6468 static void genGetHbit (iCode *ic)
6469 {
6470     operand *left, *result;
6471     left = IC_LEFT(ic);
6472     result=IC_RESULT(ic);
6473     pic16_aopOp (left,ic,FALSE);
6474     pic16_aopOp (result,ic,FALSE);
6475
6476     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6477     /* get the highest order byte into a */
6478     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6479     if(AOP_TYPE(result) == AOP_CRY){
6480         pic16_emitcode("rlc","a");
6481         pic16_outBitC(result);
6482     }
6483     else{
6484         pic16_emitcode("rl","a");
6485         pic16_emitcode("anl","a,#0x01");
6486         pic16_outAcc(result);
6487     }
6488
6489
6490     pic16_freeAsmop(left,NULL,ic,TRUE);
6491     pic16_freeAsmop(result,NULL,ic,TRUE);
6492 }
6493
6494 #if 0
6495 /*-----------------------------------------------------------------*/
6496 /* AccRol - rotate left accumulator by known count                 */
6497 /*-----------------------------------------------------------------*/
6498 static void AccRol (int shCount)
6499 {
6500     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6501     shCount &= 0x0007;              // shCount : 0..7
6502     switch(shCount){
6503         case 0 :
6504             break;
6505         case 1 :
6506             pic16_emitcode("rl","a");
6507             break;
6508         case 2 :
6509             pic16_emitcode("rl","a");
6510             pic16_emitcode("rl","a");
6511             break;
6512         case 3 :
6513             pic16_emitcode("swap","a");
6514             pic16_emitcode("rr","a");
6515             break;
6516         case 4 :
6517             pic16_emitcode("swap","a");
6518             break;
6519         case 5 :
6520             pic16_emitcode("swap","a");
6521             pic16_emitcode("rl","a");
6522             break;
6523         case 6 :
6524             pic16_emitcode("rr","a");
6525             pic16_emitcode("rr","a");
6526             break;
6527         case 7 :
6528             pic16_emitcode("rr","a");
6529             break;
6530     }
6531 }
6532 #endif
6533
6534 /*-----------------------------------------------------------------*/
6535 /* AccLsh - left shift accumulator by known count                  */
6536 /*-----------------------------------------------------------------*/
6537 static void AccLsh (int shCount)
6538 {
6539     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6540     switch(shCount){
6541         case 0 :
6542                         return;
6543             break;
6544         case 1 :
6545             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6546             break;
6547         case 2 :
6548             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6549             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6550             break;
6551         case 3 :
6552             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6553             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6554             break;
6555         case 4 :
6556             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6557             break;
6558         case 5 :
6559             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6560             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6561             break;
6562         case 6 :
6563             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6564             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6565             break;
6566         case 7 :
6567             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6568             break;
6569     }
6570     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6571
6572 }
6573
6574 /*-----------------------------------------------------------------*/
6575 /* AccRsh - right shift accumulator by known count                 */
6576 /*-----------------------------------------------------------------*/
6577 static void AccRsh (int shCount)
6578 {
6579     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6580     switch(shCount){
6581         case 0 :
6582                         return;
6583             break;
6584         case 1 :
6585             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6586             break;
6587         case 2 :
6588             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6589             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6590             break;
6591         case 3 :
6592             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6593             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6594             break;
6595         case 4 :
6596             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6597             break;
6598         case 5 :
6599             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6600             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6601             break;
6602         case 6 :
6603             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6604             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6605             break;
6606         case 7 :
6607             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6608             break;
6609     }
6610     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6611 }
6612
6613 #if 0
6614 /*-----------------------------------------------------------------*/
6615 /* AccSRsh - signed right shift accumulator by known count                 */
6616 /*-----------------------------------------------------------------*/
6617 static void AccSRsh (int shCount)
6618 {
6619     symbol *tlbl ;
6620     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6621     if(shCount != 0){
6622         if(shCount == 1){
6623             pic16_emitcode("mov","c,acc.7");
6624             pic16_emitcode("rrc","a");
6625         } else if(shCount == 2){
6626             pic16_emitcode("mov","c,acc.7");
6627             pic16_emitcode("rrc","a");
6628             pic16_emitcode("mov","c,acc.7");
6629             pic16_emitcode("rrc","a");
6630         } else {
6631             tlbl = newiTempLabel(NULL);
6632             /* rotate right accumulator */
6633             AccRol(8 - shCount);
6634             /* and kill the higher order bits */
6635             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6636             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6637             pic16_emitcode("orl","a,#0x%02x",
6638                      (unsigned char)~SRMask[shCount]);
6639             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6640         }
6641     }
6642 }
6643 #endif
6644 /*-----------------------------------------------------------------*/
6645 /* shiftR1Left2Result - shift right one byte from left to result   */
6646 /*-----------------------------------------------------------------*/
6647 static void shiftR1Left2ResultSigned (operand *left, int offl,
6648                                 operand *result, int offr,
6649                                 int shCount)
6650 {
6651   int same;
6652
6653   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6654
6655   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6656
6657   switch(shCount) {
6658   case 1:
6659     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6660     if(same) 
6661       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6662     else {
6663       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6664       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6665     }
6666
6667     break;
6668   case 2:
6669
6670     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6671     if(same) 
6672       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6673     else {
6674       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6675       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6676     }
6677     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6678     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6679
6680     break;
6681
6682   case 3:
6683     if(same)
6684       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6685     else {
6686       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6687       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6688     }
6689
6690     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6691     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6692     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6693
6694     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6695     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
6696
6697     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6698     break;
6699
6700   case 4:
6701     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6702     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
6703     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6704     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
6705     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6706     break;
6707   case 5:
6708     if(same) {
6709       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
6710     } else {
6711       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
6712       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6713     }
6714     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
6715     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
6716     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6717     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
6718     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6719     break;
6720
6721   case 6:
6722     if(same) {
6723       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6724       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6725       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
6726       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6727       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
6728       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6729     } else {
6730       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6731       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6732       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6733       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6734       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6735     }
6736     break;
6737
6738   case 7:
6739     if(same) {
6740       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6741       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6742       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6743       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6744     } else {
6745       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6746       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6747       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6748     }
6749
6750   default:
6751     break;
6752   }
6753 }
6754
6755 /*-----------------------------------------------------------------*/
6756 /* shiftR1Left2Result - shift right one byte from left to result   */
6757 /*-----------------------------------------------------------------*/
6758 static void shiftR1Left2Result (operand *left, int offl,
6759                                 operand *result, int offr,
6760                                 int shCount, int sign)
6761 {
6762   int same;
6763
6764   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6765
6766   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6767
6768   /* Copy the msb into the carry if signed. */
6769   if(sign) {
6770     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6771     return;
6772   }
6773
6774
6775
6776   switch(shCount) {
6777   case 1:
6778     emitCLRC;
6779     if(same) 
6780       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6781     else {
6782       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6783       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6784     }
6785     break;
6786   case 2:
6787     emitCLRC;
6788     if(same) {
6789       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6790     } else {
6791       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6792       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6793     }
6794     emitCLRC;
6795     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6796
6797     break;
6798   case 3:
6799     if(same)
6800       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6801     else {
6802       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6803       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6804     }
6805
6806     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6807     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6808     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6809     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6810     break;
6811       
6812   case 4:
6813     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6814     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6815     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6816     break;
6817
6818   case 5:
6819     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6820     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6821     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6822     emitCLRC;
6823     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6824
6825     break;
6826   case 6:
6827
6828     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
6829     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6830     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6831     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6832     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6833     break;
6834
6835   case 7:
6836
6837     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6838     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6839     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6840
6841     break;
6842
6843   default:
6844     break;
6845   }
6846 }
6847
6848 /*-----------------------------------------------------------------*/
6849 /* shiftL1Left2Result - shift left one byte from left to result    */
6850 /*-----------------------------------------------------------------*/
6851 static void shiftL1Left2Result (operand *left, int offl,
6852                                 operand *result, int offr, int shCount)
6853 {
6854   int same;
6855
6856   //    char *l;
6857   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6858
6859   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6860   DEBUGpic16_emitcode ("; ***","same =  %d",same);
6861     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6862     //    MOVA(l);
6863     /* shift left accumulator */
6864     //AccLsh(shCount); // don't comment out just yet...
6865   //    pic16_aopPut(AOP(result),"a",offr);
6866
6867   switch(shCount) {
6868   case 1:
6869     /* Shift left 1 bit position */
6870     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6871     if(same) {
6872       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
6873     } else {
6874       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
6875       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6876     }
6877     break;
6878   case 2:
6879     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6880     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
6881     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6882     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6883     break;
6884   case 3:
6885     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6886     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
6887     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6888     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6889     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6890     break;
6891   case 4:
6892     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6893     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6894     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6895     break;
6896   case 5:
6897     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6898     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6899     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6900     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6901     break;
6902   case 6:
6903     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6904     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
6905     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6906     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6907     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6908     break;
6909   case 7:
6910     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6911     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6912     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6913     break;
6914
6915   default:
6916     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6917   }
6918
6919 }
6920
6921 /*-----------------------------------------------------------------*/
6922 /* movLeft2Result - move byte from left to result                  */
6923 /*-----------------------------------------------------------------*/
6924 static void movLeft2Result (operand *left, int offl,
6925                             operand *result, int offr)
6926 {
6927   char *l;
6928   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6929   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6930     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6931
6932     if (*l == '@' && (IS_AOP_PREG(result))) {
6933       pic16_emitcode("mov","a,%s",l);
6934       pic16_aopPut(AOP(result),"a",offr);
6935     } else {
6936       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6937       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6938     }
6939   }
6940 }
6941
6942 /*-----------------------------------------------------------------*/
6943 /* shiftL2Left2Result - shift left two bytes from left to result   */
6944 /*-----------------------------------------------------------------*/
6945 static void shiftL2Left2Result (operand *left, int offl,
6946                                 operand *result, int offr, int shCount)
6947 {
6948   int same = pic16_sameRegs(AOP(result), AOP(left));
6949   int i;
6950
6951   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6952
6953   if (same && (offl != offr)) { // shift bytes
6954     if (offr > offl) {
6955        for(i=1;i>-1;i--) {
6956          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6957          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6958        }
6959     } else { // just treat as different later on
6960                 same = 0;
6961     }
6962   }
6963
6964   if(same) {
6965     switch(shCount) {
6966     case 0:
6967       break;
6968     case 1:
6969     case 2:
6970     case 3:
6971
6972       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6973       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6974       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6975
6976       while(--shCount) {
6977                 emitCLRC;
6978                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6979                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6980       }
6981
6982       break;
6983     case 4:
6984     case 5:
6985       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6986       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6987       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6988       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6989       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6990       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6991       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6992       if(shCount >=5) {
6993                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6994                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6995       }
6996       break;
6997     case 6:
6998       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6999       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7000       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7001       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7002       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7003       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7004       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7005       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7006       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7007       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7008       break;
7009     case 7:
7010       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7011       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7012       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7013       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7014       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7015     }
7016
7017   } else {
7018     switch(shCount) {
7019     case 0:
7020       break;
7021     case 1:
7022     case 2:
7023     case 3:
7024       /* note, use a mov/add for the shift since the mov has a
7025          chance of getting optimized out */
7026       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7027       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7028       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7029       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7030       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7031
7032       while(--shCount) {
7033                 emitCLRC;
7034                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7035                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7036       }
7037       break;
7038
7039     case 4:
7040     case 5:
7041       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7042       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7043       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7044       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7045       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7046       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7047       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7048       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7049
7050
7051       if(shCount == 5) {
7052                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7053                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7054       }
7055       break;
7056     case 6:
7057       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7058       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7059       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7060       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7061
7062       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7063       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7064       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7065       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7066       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7067       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7068       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7069       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7070       break;
7071     case 7:
7072       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7073       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7074       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7075       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7076       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7077     }
7078   }
7079
7080 }
7081 /*-----------------------------------------------------------------*/
7082 /* shiftR2Left2Result - shift right two bytes from left to result  */
7083 /*-----------------------------------------------------------------*/
7084 static void shiftR2Left2Result (operand *left, int offl,
7085                                 operand *result, int offr,
7086                                 int shCount, int sign)
7087 {
7088   int same = pic16_sameRegs(AOP(result), AOP(left));
7089   int i;
7090   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7091
7092   if (same && (offl != offr)) { // shift right bytes
7093     if (offr < offl) {
7094        for(i=0;i<2;i++) {
7095          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7096          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7097        }
7098     } else { // just treat as different later on
7099                 same = 0;
7100     }
7101   }
7102
7103   switch(shCount) {
7104   case 0:
7105     break;
7106   case 1:
7107   case 2:
7108   case 3:
7109     if(sign)
7110       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7111     else
7112       emitCLRC;
7113
7114     if(same) {
7115       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7116       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7117     } else {
7118       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7119       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7120       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7121       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7122     }
7123
7124     while(--shCount) {
7125       if(sign)
7126                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7127       else
7128                 emitCLRC;
7129       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7130       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7131     }
7132     break;
7133   case 4:
7134   case 5:
7135     if(same) {
7136
7137       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7138       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7139       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7140
7141       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7142       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7143       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7144       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7145     } else {
7146       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7147       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7148       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7149
7150       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7151       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7152       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7153       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7154       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7155     }
7156
7157     if(shCount >=5) {
7158       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7159       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7160     }
7161
7162     if(sign) {
7163       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7164       pic16_emitpcode(POC_BTFSC, 
7165                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7166       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7167     }
7168
7169     break;
7170
7171   case 6:
7172     if(same) {
7173
7174       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7175       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7176
7177       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7178       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7179       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7180       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7181       if(sign) {
7182         pic16_emitpcode(POC_BTFSC, 
7183                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7184         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7185       }
7186       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7187       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7188       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7189       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7190     } else {
7191       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7192       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7193       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7194       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7195       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7196       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7197       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7198       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7199       if(sign) {
7200         pic16_emitpcode(POC_BTFSC, 
7201                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7202         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7203       }
7204       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7205       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7206
7207         
7208     }
7209
7210     break;
7211   case 7:
7212     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7213     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7214     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7215     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7216     if(sign) {
7217       emitSKPNC;
7218       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7219     } else 
7220       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7221   }
7222 }
7223
7224
7225 /*-----------------------------------------------------------------*/
7226 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7227 /*-----------------------------------------------------------------*/
7228 static void shiftLLeftOrResult (operand *left, int offl,
7229                                 operand *result, int offr, int shCount)
7230 {
7231     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7232
7233     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7234     /* shift left accumulator */
7235     AccLsh(shCount);
7236     /* or with result */
7237     /* back to result */
7238     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7239 }
7240
7241 /*-----------------------------------------------------------------*/
7242 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7243 /*-----------------------------------------------------------------*/
7244 static void shiftRLeftOrResult (operand *left, int offl,
7245                                 operand *result, int offr, int shCount)
7246 {
7247     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7248     
7249     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7250     /* shift right accumulator */
7251     AccRsh(shCount);
7252     /* or with result */
7253     /* back to result */
7254     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7255 }
7256
7257 /*-----------------------------------------------------------------*/
7258 /* genlshOne - left shift a one byte quantity by known count       */
7259 /*-----------------------------------------------------------------*/
7260 static void genlshOne (operand *result, operand *left, int shCount)
7261 {       
7262     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7263     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7264 }
7265
7266 /*-----------------------------------------------------------------*/
7267 /* genlshTwo - left shift two bytes by known amount != 0           */
7268 /*-----------------------------------------------------------------*/
7269 static void genlshTwo (operand *result,operand *left, int shCount)
7270 {
7271     int size;
7272     
7273     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7274     size = pic16_getDataSize(result);
7275
7276     /* if shCount >= 8 */
7277     if (shCount >= 8) {
7278         shCount -= 8 ;
7279
7280         if (size > 1){
7281             if (shCount)
7282                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7283             else 
7284                 movLeft2Result(left, LSB, result, MSB16);
7285         }
7286         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7287     }
7288
7289     /*  1 <= shCount <= 7 */
7290     else {  
7291         if(size == 1)
7292             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7293         else 
7294             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7295     }
7296 }
7297
7298 /*-----------------------------------------------------------------*/
7299 /* shiftLLong - shift left one long from left to result            */
7300 /* offr = LSB or MSB16                                             */
7301 /*-----------------------------------------------------------------*/
7302 static void shiftLLong (operand *left, operand *result, int offr )
7303 {
7304     int size = AOP_SIZE(result);
7305     int same = pic16_sameRegs(AOP(left),AOP(result));
7306         int i;
7307
7308     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7309
7310         if (same && (offr == MSB16)) { //shift one byte
7311                 for(i=size-1;i>=MSB16;i--) {
7312                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7313                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7314                 }
7315         } else {
7316                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7317         }
7318         
7319     if (size >= LSB+offr ){
7320                 if (same) {
7321                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7322                 } else {
7323                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7324                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7325                 }
7326          }
7327
7328     if(size >= MSB16+offr){
7329                 if (same) {
7330                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7331                 } else {
7332                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7333                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7334                 }
7335     }
7336
7337     if(size >= MSB24+offr){
7338                 if (same) {
7339                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7340                 } else {
7341                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7342                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7343                 }
7344     }
7345
7346     if(size > MSB32+offr){
7347                 if (same) {
7348                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7349                 } else {
7350                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7351                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7352                 }
7353     }
7354     if(offr != LSB)
7355                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7356
7357 }
7358
7359 /*-----------------------------------------------------------------*/
7360 /* genlshFour - shift four byte by a known amount != 0             */
7361 /*-----------------------------------------------------------------*/
7362 static void genlshFour (operand *result, operand *left, int shCount)
7363 {
7364     int size;
7365
7366     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7367     size = AOP_SIZE(result);
7368
7369     /* if shifting more that 3 bytes */
7370     if (shCount >= 24 ) {
7371         shCount -= 24;
7372         if (shCount)
7373             /* lowest order of left goes to the highest
7374             order of the destination */
7375             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7376         else
7377             movLeft2Result(left, LSB, result, MSB32);
7378
7379                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7380                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7381                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7382
7383         return;
7384     }
7385
7386     /* more than two bytes */
7387     else if ( shCount >= 16 ) {
7388         /* lower order two bytes goes to higher order two bytes */
7389         shCount -= 16;
7390         /* if some more remaining */
7391         if (shCount)
7392             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7393         else {
7394             movLeft2Result(left, MSB16, result, MSB32);
7395             movLeft2Result(left, LSB, result, MSB24);
7396         }
7397                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7398                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7399         return;
7400     }    
7401
7402     /* if more than 1 byte */
7403     else if ( shCount >= 8 ) {
7404         /* lower order three bytes goes to higher order  three bytes */
7405         shCount -= 8;
7406         if(size == 2){
7407             if(shCount)
7408                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7409             else
7410                 movLeft2Result(left, LSB, result, MSB16);
7411         }
7412         else{   /* size = 4 */
7413             if(shCount == 0){
7414                 movLeft2Result(left, MSB24, result, MSB32);
7415                 movLeft2Result(left, MSB16, result, MSB24);
7416                 movLeft2Result(left, LSB, result, MSB16);
7417                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7418             }
7419             else if(shCount == 1)
7420                 shiftLLong(left, result, MSB16);
7421             else{
7422                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7423                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7424                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7425                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7426             }
7427         }
7428     }
7429
7430     /* 1 <= shCount <= 7 */
7431     else if(shCount <= 3)
7432     { 
7433         shiftLLong(left, result, LSB);
7434         while(--shCount >= 1)
7435             shiftLLong(result, result, LSB);
7436     }
7437     /* 3 <= shCount <= 7, optimize */
7438     else{
7439         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7440         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7441         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7442     }
7443 }
7444
7445 /*-----------------------------------------------------------------*/
7446 /* genLeftShiftLiteral - left shifting by known count              */
7447 /*-----------------------------------------------------------------*/
7448 static void genLeftShiftLiteral (operand *left,
7449                                  operand *right,
7450                                  operand *result,
7451                                  iCode *ic)
7452 {    
7453     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7454     int size;
7455
7456     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7457     pic16_freeAsmop(right,NULL,ic,TRUE);
7458
7459     pic16_aopOp(left,ic,FALSE);
7460     pic16_aopOp(result,ic,FALSE);
7461
7462     size = getSize(operandType(result));
7463
7464 #if VIEW_SIZE
7465     pic16_emitcode("; shift left ","result %d, left %d",size,
7466              AOP_SIZE(left));
7467 #endif
7468
7469     /* I suppose that the left size >= result size */
7470     if(shCount == 0){
7471         while(size--){
7472             movLeft2Result(left, size, result, size);
7473         }
7474     }
7475
7476     else if(shCount >= (size * 8))
7477         while(size--)
7478             pic16_aopPut(AOP(result),zero,size);
7479     else{
7480         switch (size) {
7481             case 1:
7482                 genlshOne (result,left,shCount);
7483                 break;
7484
7485             case 2:
7486             case 3:
7487                 genlshTwo (result,left,shCount);
7488                 break;
7489
7490             case 4:
7491                 genlshFour (result,left,shCount);
7492                 break;
7493         }
7494     }
7495     pic16_freeAsmop(left,NULL,ic,TRUE);
7496     pic16_freeAsmop(result,NULL,ic,TRUE);
7497 }
7498
7499 /*-----------------------------------------------------------------*
7500  * genMultiAsm - repeat assembly instruction for size of register.
7501  * if endian == 1, then the high byte (i.e base address + size of 
7502  * register) is used first else the low byte is used first;
7503  *-----------------------------------------------------------------*/
7504 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7505 {
7506
7507   int offset = 0;
7508
7509   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7510
7511   if(!reg)
7512     return;
7513
7514   if(!endian) {
7515     endian = 1;
7516   } else {
7517     endian = -1;
7518     offset = size-1;
7519   }
7520
7521   while(size--) {
7522     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7523     offset += endian;
7524   }
7525
7526 }
7527 /*-----------------------------------------------------------------*/
7528 /* genLeftShift - generates code for left shifting                 */
7529 /*-----------------------------------------------------------------*/
7530 static void genLeftShift (iCode *ic)
7531 {
7532   operand *left,*right, *result;
7533   int size, offset;
7534   char *l;
7535   symbol *tlbl , *tlbl1;
7536   pCodeOp *pctemp;
7537
7538   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7539
7540   right = IC_RIGHT(ic);
7541   left  = IC_LEFT(ic);
7542   result = IC_RESULT(ic);
7543
7544   pic16_aopOp(right,ic,FALSE);
7545
7546   /* if the shift count is known then do it 
7547      as efficiently as possible */
7548   if (AOP_TYPE(right) == AOP_LIT) {
7549     genLeftShiftLiteral (left,right,result,ic);
7550     return ;
7551   }
7552
7553   /* shift count is unknown then we have to form 
7554      a loop get the loop count in B : Note: we take
7555      only the lower order byte since shifting
7556      more that 32 bits make no sense anyway, ( the
7557      largest size of an object can be only 32 bits ) */  
7558
7559     
7560   pic16_aopOp(left,ic,FALSE);
7561   pic16_aopOp(result,ic,FALSE);
7562
7563   /* now move the left to the result if they are not the
7564      same */
7565   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7566       AOP_SIZE(result) > 1) {
7567
7568     size = AOP_SIZE(result);
7569     offset=0;
7570     while (size--) {
7571       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7572       if (*l == '@' && (IS_AOP_PREG(result))) {
7573
7574         pic16_emitcode("mov","a,%s",l);
7575         pic16_aopPut(AOP(result),"a",offset);
7576       } else {
7577         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7578         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7579         //pic16_aopPut(AOP(result),l,offset);
7580       }
7581       offset++;
7582     }
7583   }
7584
7585   size = AOP_SIZE(result);
7586
7587   /* if it is only one byte then */
7588   if (size == 1) {
7589     if(optimized_for_speed) {
7590       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7591       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7592       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7593       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7594       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7595       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7596       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7597       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7598       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7599       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7600       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7601       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7602     } else {
7603
7604       tlbl = newiTempLabel(NULL);
7605       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7606                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7607                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7608       }
7609
7610       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7611       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7612       pic16_emitpLabel(tlbl->key);
7613       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7614       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7615       emitSKPC;
7616       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7617     }
7618     goto release ;
7619   }
7620     
7621   if (pic16_sameRegs(AOP(left),AOP(result))) {
7622
7623     tlbl = newiTempLabel(NULL);
7624     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7625     genMultiAsm(POC_RRCF, result, size,1);
7626     pic16_emitpLabel(tlbl->key);
7627     genMultiAsm(POC_RLCF, result, size,0);
7628     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7629     emitSKPC;
7630     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7631     goto release;
7632   }
7633
7634   //tlbl = newiTempLabel(NULL);
7635   //offset = 0 ;   
7636   //tlbl1 = newiTempLabel(NULL);
7637
7638   //reAdjustPreg(AOP(result));    
7639     
7640   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7641   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7642   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7643   //MOVA(l);
7644   //pic16_emitcode("add","a,acc");         
7645   //pic16_aopPut(AOP(result),"a",offset++);
7646   //while (--size) {
7647   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7648   //  MOVA(l);
7649   //  pic16_emitcode("rlc","a");         
7650   //  pic16_aopPut(AOP(result),"a",offset++);
7651   //}
7652   //reAdjustPreg(AOP(result));
7653
7654   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7655   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7656
7657
7658   tlbl = newiTempLabel(NULL);
7659   tlbl1= newiTempLabel(NULL);
7660
7661   size = AOP_SIZE(result);
7662   offset = 1;
7663
7664   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7665
7666   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7667
7668   /* offset should be 0, 1 or 3 */
7669   
7670   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
7671   emitSKPNZ;
7672   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7673
7674   pic16_emitpcode(POC_MOVWF, pctemp);
7675
7676
7677   pic16_emitpLabel(tlbl->key);
7678
7679   emitCLRC;
7680   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
7681   while(--size)
7682     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
7683
7684   pic16_emitpcode(POC_DECFSZ,  pctemp);
7685   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7686   pic16_emitpLabel(tlbl1->key);
7687
7688   pic16_popReleaseTempReg(pctemp);
7689
7690
7691  release:
7692   pic16_freeAsmop (right,NULL,ic,TRUE);
7693   pic16_freeAsmop(left,NULL,ic,TRUE);
7694   pic16_freeAsmop(result,NULL,ic,TRUE);
7695 }
7696
7697 /*-----------------------------------------------------------------*/
7698 /* genrshOne - right shift a one byte quantity by known count      */
7699 /*-----------------------------------------------------------------*/
7700 static void genrshOne (operand *result, operand *left,
7701                        int shCount, int sign)
7702 {
7703     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7704     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7705 }
7706
7707 /*-----------------------------------------------------------------*/
7708 /* genrshTwo - right shift two bytes by known amount != 0          */
7709 /*-----------------------------------------------------------------*/
7710 static void genrshTwo (operand *result,operand *left,
7711                        int shCount, int sign)
7712 {
7713   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7714   /* if shCount >= 8 */
7715   if (shCount >= 8) {
7716     shCount -= 8 ;
7717     if (shCount)
7718       shiftR1Left2Result(left, MSB16, result, LSB,
7719                          shCount, sign);
7720     else
7721       movLeft2Result(left, MSB16, result, LSB);
7722
7723     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7724
7725     if(sign) {
7726       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7727       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
7728     }
7729   }
7730
7731   /*  1 <= shCount <= 7 */
7732   else
7733     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7734 }
7735
7736 /*-----------------------------------------------------------------*/
7737 /* shiftRLong - shift right one long from left to result           */
7738 /* offl = LSB or MSB16                                             */
7739 /*-----------------------------------------------------------------*/
7740 static void shiftRLong (operand *left, int offl,
7741                         operand *result, int sign)
7742 {
7743     int size = AOP_SIZE(result);
7744     int same = pic16_sameRegs(AOP(left),AOP(result));
7745     int i;
7746     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7747
7748         if (same && (offl == MSB16)) { //shift one byte right
7749                 for(i=MSB16;i<size;i++) {
7750                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7751                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7752                 }
7753         }
7754
7755     if(sign)
7756                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7757         else
7758                 emitCLRC;
7759
7760         if (same) {
7761                 if (offl == LSB)
7762                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7763         } else {
7764         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7765         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7766         }
7767
7768     if(offl == MSB16) {
7769         /* add sign of "a" */
7770         pic16_addSign(result, MSB32, sign);
7771         }
7772
7773         if (same) {
7774         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7775         } else {
7776         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7777         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7778         }
7779         
7780         if (same) {
7781         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7782         } else {
7783         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7784         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7785         }
7786
7787         if (same) {
7788         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7789         } else {
7790         if(offl == LSB){
7791                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7792                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7793         }
7794         }
7795 }
7796
7797 /*-----------------------------------------------------------------*/
7798 /* genrshFour - shift four byte by a known amount != 0             */
7799 /*-----------------------------------------------------------------*/
7800 static void genrshFour (operand *result, operand *left,
7801                         int shCount, int sign)
7802 {
7803   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7804   /* if shifting more that 3 bytes */
7805   if(shCount >= 24 ) {
7806     shCount -= 24;
7807     if(shCount)
7808       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7809     else
7810       movLeft2Result(left, MSB32, result, LSB);
7811
7812     pic16_addSign(result, MSB16, sign);
7813   }
7814   else if(shCount >= 16){
7815     shCount -= 16;
7816     if(shCount)
7817       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7818     else{
7819       movLeft2Result(left, MSB24, result, LSB);
7820       movLeft2Result(left, MSB32, result, MSB16);
7821     }
7822     pic16_addSign(result, MSB24, sign);
7823   }
7824   else if(shCount >= 8){
7825     shCount -= 8;
7826     if(shCount == 1)
7827       shiftRLong(left, MSB16, result, sign);
7828     else if(shCount == 0){
7829       movLeft2Result(left, MSB16, result, LSB);
7830       movLeft2Result(left, MSB24, result, MSB16);
7831       movLeft2Result(left, MSB32, result, MSB24);
7832       pic16_addSign(result, MSB32, sign);
7833     }
7834     else{ //shcount >= 2
7835       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7836       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7837       /* the last shift is signed */
7838       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7839       pic16_addSign(result, MSB32, sign);
7840     }
7841   }
7842   else{   /* 1 <= shCount <= 7 */
7843     if(shCount <= 2){
7844       shiftRLong(left, LSB, result, sign);
7845       if(shCount == 2)
7846         shiftRLong(result, LSB, result, sign);
7847     }
7848     else{
7849       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7850       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7851       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7852     }
7853   }
7854 }
7855
7856 /*-----------------------------------------------------------------*/
7857 /* genRightShiftLiteral - right shifting by known count            */
7858 /*-----------------------------------------------------------------*/
7859 static void genRightShiftLiteral (operand *left,
7860                                   operand *right,
7861                                   operand *result,
7862                                   iCode *ic,
7863                                   int sign)
7864 {    
7865   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7866   int lsize,res_size;
7867
7868   pic16_freeAsmop(right,NULL,ic,TRUE);
7869
7870   pic16_aopOp(left,ic,FALSE);
7871   pic16_aopOp(result,ic,FALSE);
7872
7873   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7874
7875 #if VIEW_SIZE
7876   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7877                  AOP_SIZE(left));
7878 #endif
7879
7880   lsize = pic16_getDataSize(left);
7881   res_size = pic16_getDataSize(result);
7882   /* test the LEFT size !!! */
7883
7884   /* I suppose that the left size >= result size */
7885   if(shCount == 0){
7886     while(res_size--)
7887       movLeft2Result(left, lsize, result, res_size);
7888   }
7889
7890   else if(shCount >= (lsize * 8)){
7891
7892     if(res_size == 1) {
7893       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
7894       if(sign) {
7895         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7896         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
7897       }
7898     } else {
7899
7900       if(sign) {
7901         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7902         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7903         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7904         while(res_size--)
7905           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
7906
7907       } else {
7908
7909         while(res_size--)
7910           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
7911       }
7912     }
7913   } else {
7914
7915     switch (res_size) {
7916     case 1:
7917       genrshOne (result,left,shCount,sign);
7918       break;
7919
7920     case 2:
7921       genrshTwo (result,left,shCount,sign);
7922       break;
7923
7924     case 4:
7925       genrshFour (result,left,shCount,sign);
7926       break;
7927     default :
7928       break;
7929     }
7930
7931   }
7932
7933   pic16_freeAsmop(left,NULL,ic,TRUE);
7934   pic16_freeAsmop(result,NULL,ic,TRUE);
7935 }
7936
7937 /*-----------------------------------------------------------------*/
7938 /* genSignedRightShift - right shift of signed number              */
7939 /*-----------------------------------------------------------------*/
7940 static void genSignedRightShift (iCode *ic)
7941 {
7942   operand *right, *left, *result;
7943   int size, offset;
7944   //  char *l;
7945   symbol *tlbl, *tlbl1 ;
7946   pCodeOp *pctemp;
7947
7948   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7949
7950   /* we do it the hard way put the shift count in b
7951      and loop thru preserving the sign */
7952   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7953
7954   right = IC_RIGHT(ic);
7955   left  = IC_LEFT(ic);
7956   result = IC_RESULT(ic);
7957
7958   pic16_aopOp(right,ic,FALSE);  
7959   pic16_aopOp(left,ic,FALSE);
7960   pic16_aopOp(result,ic,FALSE);
7961
7962
7963   if ( AOP_TYPE(right) == AOP_LIT) {
7964     genRightShiftLiteral (left,right,result,ic,1);
7965     return ;
7966   }
7967   /* shift count is unknown then we have to form 
7968      a loop get the loop count in B : Note: we take
7969      only the lower order byte since shifting
7970      more that 32 bits make no sense anyway, ( the
7971      largest size of an object can be only 32 bits ) */  
7972
7973   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7974   //pic16_emitcode("inc","b");
7975   //pic16_freeAsmop (right,NULL,ic,TRUE);
7976   //pic16_aopOp(left,ic,FALSE);
7977   //pic16_aopOp(result,ic,FALSE);
7978
7979   /* now move the left to the result if they are not the
7980      same */
7981   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7982       AOP_SIZE(result) > 1) {
7983
7984     size = AOP_SIZE(result);
7985     offset=0;
7986     while (size--) { 
7987       /*
7988         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7989         if (*l == '@' && IS_AOP_PREG(result)) {
7990
7991         pic16_emitcode("mov","a,%s",l);
7992         pic16_aopPut(AOP(result),"a",offset);
7993         } else
7994         pic16_aopPut(AOP(result),l,offset);
7995       */
7996       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7997       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7998
7999       offset++;
8000     }
8001   }
8002
8003   /* mov the highest order bit to OVR */    
8004   tlbl = newiTempLabel(NULL);
8005   tlbl1= newiTempLabel(NULL);
8006
8007   size = AOP_SIZE(result);
8008   offset = size - 1;
8009
8010   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8011
8012   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8013
8014   /* offset should be 0, 1 or 3 */
8015   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8016   emitSKPNZ;
8017   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8018
8019   pic16_emitpcode(POC_MOVWF, pctemp);
8020
8021
8022   pic16_emitpLabel(tlbl->key);
8023
8024   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8025   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8026
8027   while(--size) {
8028     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8029   }
8030
8031   pic16_emitpcode(POC_DECFSZ,  pctemp);
8032   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8033   pic16_emitpLabel(tlbl1->key);
8034
8035   pic16_popReleaseTempReg(pctemp);
8036 #if 0
8037   size = AOP_SIZE(result);
8038   offset = size - 1;
8039   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8040   pic16_emitcode("rlc","a");
8041   pic16_emitcode("mov","ov,c");
8042   /* if it is only one byte then */
8043   if (size == 1) {
8044     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8045     MOVA(l);
8046     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8047     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8048     pic16_emitcode("mov","c,ov");
8049     pic16_emitcode("rrc","a");
8050     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8051     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8052     pic16_aopPut(AOP(result),"a",0);
8053     goto release ;
8054   }
8055
8056   reAdjustPreg(AOP(result));
8057   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8058   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8059   pic16_emitcode("mov","c,ov");
8060   while (size--) {
8061     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8062     MOVA(l);
8063     pic16_emitcode("rrc","a");         
8064     pic16_aopPut(AOP(result),"a",offset--);
8065   }
8066   reAdjustPreg(AOP(result));
8067   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8068   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8069
8070  release:
8071 #endif
8072
8073   pic16_freeAsmop(left,NULL,ic,TRUE);
8074   pic16_freeAsmop(result,NULL,ic,TRUE);
8075   pic16_freeAsmop(right,NULL,ic,TRUE);
8076 }
8077
8078 /*-----------------------------------------------------------------*/
8079 /* genRightShift - generate code for right shifting                */
8080 /*-----------------------------------------------------------------*/
8081 static void genRightShift (iCode *ic)
8082 {
8083     operand *right, *left, *result;
8084     sym_link *letype ;
8085     int size, offset;
8086     char *l;
8087     symbol *tlbl, *tlbl1 ;
8088
8089     /* if signed then we do it the hard way preserve the
8090     sign bit moving it inwards */
8091     letype = getSpec(operandType(IC_LEFT(ic)));
8092     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8093
8094     if (!SPEC_USIGN(letype)) {
8095         genSignedRightShift (ic);
8096         return ;
8097     }
8098
8099     /* signed & unsigned types are treated the same : i.e. the
8100     signed is NOT propagated inwards : quoting from the
8101     ANSI - standard : "for E1 >> E2, is equivalent to division
8102     by 2**E2 if unsigned or if it has a non-negative value,
8103     otherwise the result is implementation defined ", MY definition
8104     is that the sign does not get propagated */
8105
8106     right = IC_RIGHT(ic);
8107     left  = IC_LEFT(ic);
8108     result = IC_RESULT(ic);
8109
8110     pic16_aopOp(right,ic,FALSE);
8111
8112     /* if the shift count is known then do it 
8113     as efficiently as possible */
8114     if (AOP_TYPE(right) == AOP_LIT) {
8115         genRightShiftLiteral (left,right,result,ic, 0);
8116         return ;
8117     }
8118
8119     /* shift count is unknown then we have to form 
8120     a loop get the loop count in B : Note: we take
8121     only the lower order byte since shifting
8122     more that 32 bits make no sense anyway, ( the
8123     largest size of an object can be only 32 bits ) */  
8124
8125     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8126     pic16_emitcode("inc","b");
8127     pic16_aopOp(left,ic,FALSE);
8128     pic16_aopOp(result,ic,FALSE);
8129
8130     /* now move the left to the result if they are not the
8131     same */
8132     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8133         AOP_SIZE(result) > 1) {
8134
8135         size = AOP_SIZE(result);
8136         offset=0;
8137         while (size--) {
8138             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8139             if (*l == '@' && IS_AOP_PREG(result)) {
8140
8141                 pic16_emitcode("mov","a,%s",l);
8142                 pic16_aopPut(AOP(result),"a",offset);
8143             } else
8144                 pic16_aopPut(AOP(result),l,offset);
8145             offset++;
8146         }
8147     }
8148
8149     tlbl = newiTempLabel(NULL);
8150     tlbl1= newiTempLabel(NULL);
8151     size = AOP_SIZE(result);
8152     offset = size - 1;
8153
8154     /* if it is only one byte then */
8155     if (size == 1) {
8156
8157       tlbl = newiTempLabel(NULL);
8158       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8159         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8160         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8161       }
8162
8163       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8164       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8165       pic16_emitpLabel(tlbl->key);
8166       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8167       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8168       emitSKPC;
8169       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8170
8171       goto release ;
8172     }
8173
8174     reAdjustPreg(AOP(result));
8175     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8176     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8177     CLRC;
8178     while (size--) {
8179         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8180         MOVA(l);
8181         pic16_emitcode("rrc","a");         
8182         pic16_aopPut(AOP(result),"a",offset--);
8183     }
8184     reAdjustPreg(AOP(result));
8185
8186     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8187     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8188
8189 release:
8190     pic16_freeAsmop(left,NULL,ic,TRUE);
8191     pic16_freeAsmop (right,NULL,ic,TRUE);
8192     pic16_freeAsmop(result,NULL,ic,TRUE);
8193 }
8194
8195 /*-----------------------------------------------------------------*/
8196 /* genUnpackBits - generates code for unpacking bits               */
8197 /*-----------------------------------------------------------------*/
8198 static void genUnpackBits (operand *result, char *rname, int ptype)
8199 {    
8200     int shCnt ;
8201     int rlen = 0 ;
8202     sym_link *etype;
8203     int offset = 0 ;
8204
8205     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8206     etype = getSpec(operandType(result));
8207
8208     /* read the first byte  */
8209     switch (ptype) {
8210
8211     case POINTER:
8212     case IPOINTER:
8213         pic16_emitcode("mov","a,@%s",rname);
8214         break;
8215         
8216     case PPOINTER:
8217         pic16_emitcode("movx","a,@%s",rname);
8218         break;
8219         
8220     case FPOINTER:
8221         pic16_emitcode("movx","a,@dptr");
8222         break;
8223
8224     case CPOINTER:
8225         pic16_emitcode("clr","a");
8226         pic16_emitcode("movc","a","@a+dptr");
8227         break;
8228
8229     case GPOINTER:
8230         pic16_emitcode("lcall","__gptrget");
8231         break;
8232     }
8233
8234     /* if we have bitdisplacement then it fits   */
8235     /* into this byte completely or if length is */
8236     /* less than a byte                          */
8237     if ((shCnt = SPEC_BSTR(etype)) || 
8238         (SPEC_BLEN(etype) <= 8))  {
8239
8240         /* shift right acc */
8241         AccRsh(shCnt);
8242
8243         pic16_emitcode("anl","a,#0x%02x",
8244                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8245         pic16_aopPut(AOP(result),"a",offset);
8246         return ;
8247     }
8248
8249     /* bit field did not fit in a byte  */
8250     rlen = SPEC_BLEN(etype) - 8;
8251     pic16_aopPut(AOP(result),"a",offset++);
8252
8253     while (1)  {
8254
8255         switch (ptype) {
8256         case POINTER:
8257         case IPOINTER:
8258             pic16_emitcode("inc","%s",rname);
8259             pic16_emitcode("mov","a,@%s",rname);
8260             break;
8261             
8262         case PPOINTER:
8263             pic16_emitcode("inc","%s",rname);
8264             pic16_emitcode("movx","a,@%s",rname);
8265             break;
8266
8267         case FPOINTER:
8268             pic16_emitcode("inc","dptr");
8269             pic16_emitcode("movx","a,@dptr");
8270             break;
8271             
8272         case CPOINTER:
8273             pic16_emitcode("clr","a");
8274             pic16_emitcode("inc","dptr");
8275             pic16_emitcode("movc","a","@a+dptr");
8276             break;
8277             
8278         case GPOINTER:
8279             pic16_emitcode("inc","dptr");
8280             pic16_emitcode("lcall","__gptrget");
8281             break;
8282         }
8283
8284         rlen -= 8;            
8285         /* if we are done */
8286         if ( rlen <= 0 )
8287             break ;
8288         
8289         pic16_aopPut(AOP(result),"a",offset++);
8290                               
8291     }
8292     
8293     if (rlen) {
8294         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8295         pic16_aopPut(AOP(result),"a",offset);          
8296     }
8297     
8298     return ;
8299 }
8300
8301 #if 0
8302 /*-----------------------------------------------------------------*/
8303 /* genDataPointerGet - generates code when ptr offset is known     */
8304 /*-----------------------------------------------------------------*/
8305 static void genDataPointerGet (operand *left, 
8306                                operand *result, 
8307                                iCode *ic)
8308 {
8309   int size , offset = 0;
8310
8311
8312   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8313
8314
8315   /* optimization - most of the time, left and result are the same
8316    * address, but different types. for the pic code, we could omit
8317    * the following
8318    */
8319
8320   pic16_aopOp(result,ic,TRUE);
8321
8322   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8323
8324   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8325
8326   size = AOP_SIZE(result);
8327
8328   while (size--) {
8329     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8330     offset++;
8331   }
8332
8333   pic16_freeAsmop(left,NULL,ic,TRUE);
8334   pic16_freeAsmop(result,NULL,ic,TRUE);
8335 }
8336 #endif
8337 /*-----------------------------------------------------------------*/
8338 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8339 /*-----------------------------------------------------------------*/
8340 static void genNearPointerGet (operand *left, 
8341                                operand *result, 
8342                                iCode *ic)
8343 {
8344     asmop *aop = NULL;
8345     //regs *preg = NULL ;
8346     char *rname ;
8347     sym_link *rtype, *retype;
8348     sym_link *ltype = operandType(left);    
8349     //char buffer[80];
8350
8351     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8352
8353     rtype = operandType(result);
8354     retype= getSpec(rtype);
8355     
8356     pic16_aopOp(left,ic,FALSE);
8357     
8358     /* if left is rematerialisable and
8359        result is not bit variable type and
8360        the left is pointer to data space i.e
8361        lower 128 bytes of space */
8362     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8363         !IS_BITVAR(retype)         &&
8364         DCL_TYPE(ltype) == POINTER) {
8365       //genDataPointerGet (left,result,ic);
8366         return ;
8367     }
8368     
8369     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8370
8371         /* if the value is already in a pointer register
8372        then don't need anything more */
8373     if (!AOP_INPREG(AOP(left))) {
8374         /* otherwise get a free pointer register */
8375     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8376 /*
8377         aop = newAsmop(0);
8378         preg = getFreePtr(ic,&aop,FALSE);
8379         pic16_emitcode("mov","%s,%s",
8380                 preg->name,
8381                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8382         rname = preg->name ;
8383 */
8384     rname ="BAD";
8385     } else
8386         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8387     
8388     pic16_aopOp (result,ic,FALSE);
8389     
8390       /* if bitfield then unpack the bits */
8391     if (IS_BITFIELD(retype)) 
8392         genUnpackBits (result,rname,POINTER);
8393     else {
8394         /* we have can just get the values */
8395       int size = AOP_SIZE(result);
8396       int offset = 0 ;  
8397         
8398       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8399
8400       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8401       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8402       while(size--) {
8403         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8404         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8405         if(size)
8406           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8407       }
8408 /*
8409         while (size--) {
8410             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8411
8412                 pic16_emitcode("mov","a,@%s",rname);
8413                 pic16_aopPut(AOP(result),"a",offset);
8414             } else {
8415                 sprintf(buffer,"@%s",rname);
8416                 pic16_aopPut(AOP(result),buffer,offset);
8417             }
8418             offset++ ;
8419             if (size)
8420                 pic16_emitcode("inc","%s",rname);
8421         }
8422 */
8423     }
8424
8425     /* now some housekeeping stuff */
8426     if (aop) {
8427         /* we had to allocate for this iCode */
8428     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8429         pic16_freeAsmop(NULL,aop,ic,TRUE);
8430     } else { 
8431         /* we did not allocate which means left
8432            already in a pointer register, then
8433            if size > 0 && this could be used again
8434            we have to point it back to where it 
8435            belongs */
8436     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8437         if (AOP_SIZE(result) > 1 &&
8438             !OP_SYMBOL(left)->remat &&
8439             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8440               ic->depth )) {
8441             int size = AOP_SIZE(result) - 1;
8442             while (size--)
8443                 pic16_emitcode("dec","%s",rname);
8444         }
8445     }
8446
8447     /* done */
8448     pic16_freeAsmop(left,NULL,ic,TRUE);
8449     pic16_freeAsmop(result,NULL,ic,TRUE);
8450      
8451 }
8452
8453 /*-----------------------------------------------------------------*/
8454 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8455 /*-----------------------------------------------------------------*/
8456 static void genPagedPointerGet (operand *left, 
8457                                operand *result, 
8458                                iCode *ic)
8459 {
8460     asmop *aop = NULL;
8461     regs *preg = NULL ;
8462     char *rname ;
8463     sym_link *rtype, *retype;    
8464
8465     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8466
8467     rtype = operandType(result);
8468     retype= getSpec(rtype);
8469     
8470     pic16_aopOp(left,ic,FALSE);
8471
8472   /* if the value is already in a pointer register
8473        then don't need anything more */
8474     if (!AOP_INPREG(AOP(left))) {
8475         /* otherwise get a free pointer register */
8476         aop = newAsmop(0);
8477         preg = getFreePtr(ic,&aop,FALSE);
8478         pic16_emitcode("mov","%s,%s",
8479                 preg->name,
8480                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8481         rname = preg->name ;
8482     } else
8483         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8484     
8485     pic16_freeAsmop(left,NULL,ic,TRUE);
8486     pic16_aopOp (result,ic,FALSE);
8487
8488     /* if bitfield then unpack the bits */
8489     if (IS_BITFIELD(retype)) 
8490         genUnpackBits (result,rname,PPOINTER);
8491     else {
8492         /* we have can just get the values */
8493         int size = AOP_SIZE(result);
8494         int offset = 0 ;        
8495         
8496         while (size--) {
8497             
8498             pic16_emitcode("movx","a,@%s",rname);
8499             pic16_aopPut(AOP(result),"a",offset);
8500             
8501             offset++ ;
8502             
8503             if (size)
8504                 pic16_emitcode("inc","%s",rname);
8505         }
8506     }
8507
8508     /* now some housekeeping stuff */
8509     if (aop) {
8510         /* we had to allocate for this iCode */
8511         pic16_freeAsmop(NULL,aop,ic,TRUE);
8512     } else { 
8513         /* we did not allocate which means left
8514            already in a pointer register, then
8515            if size > 0 && this could be used again
8516            we have to point it back to where it 
8517            belongs */
8518         if (AOP_SIZE(result) > 1 &&
8519             !OP_SYMBOL(left)->remat &&
8520             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8521               ic->depth )) {
8522             int size = AOP_SIZE(result) - 1;
8523             while (size--)
8524                 pic16_emitcode("dec","%s",rname);
8525         }
8526     }
8527
8528     /* done */
8529     pic16_freeAsmop(result,NULL,ic,TRUE);
8530     
8531         
8532 }
8533
8534 /*-----------------------------------------------------------------*/
8535 /* genFarPointerGet - gget value from far space                    */
8536 /*-----------------------------------------------------------------*/
8537 static void genFarPointerGet (operand *left,
8538                               operand *result, iCode *ic)
8539 {
8540     int size, offset ;
8541     sym_link *retype = getSpec(operandType(result));
8542
8543     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8544
8545     pic16_aopOp(left,ic,FALSE);
8546
8547     /* if the operand is already in dptr 
8548     then we do nothing else we move the value to dptr */
8549     if (AOP_TYPE(left) != AOP_STR) {
8550         /* if this is remateriazable */
8551         if (AOP_TYPE(left) == AOP_IMMD)
8552             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8553         else { /* we need to get it byte by byte */
8554             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8555             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8556             if (options.model == MODEL_FLAT24)
8557             {
8558                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8559             }
8560         }
8561     }
8562     /* so dptr know contains the address */
8563     pic16_freeAsmop(left,NULL,ic,TRUE);
8564     pic16_aopOp(result,ic,FALSE);
8565
8566     /* if bit then unpack */
8567     if (IS_BITFIELD(retype)) 
8568         genUnpackBits(result,"dptr",FPOINTER);
8569     else {
8570         size = AOP_SIZE(result);
8571         offset = 0 ;
8572
8573         while (size--) {
8574             pic16_emitcode("movx","a,@dptr");
8575             pic16_aopPut(AOP(result),"a",offset++);
8576             if (size)
8577                 pic16_emitcode("inc","dptr");
8578         }
8579     }
8580
8581     pic16_freeAsmop(result,NULL,ic,TRUE);
8582 }
8583 #if 0
8584 /*-----------------------------------------------------------------*/
8585 /* genCodePointerGet - get value from code space                  */
8586 /*-----------------------------------------------------------------*/
8587 static void genCodePointerGet (operand *left,
8588                                 operand *result, iCode *ic)
8589 {
8590     int size, offset ;
8591     sym_link *retype = getSpec(operandType(result));
8592
8593     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8594
8595     pic16_aopOp(left,ic,FALSE);
8596
8597     /* if the operand is already in dptr 
8598     then we do nothing else we move the value to dptr */
8599     if (AOP_TYPE(left) != AOP_STR) {
8600         /* if this is remateriazable */
8601         if (AOP_TYPE(left) == AOP_IMMD)
8602             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8603         else { /* we need to get it byte by byte */
8604             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8605             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8606             if (options.model == MODEL_FLAT24)
8607             {
8608                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8609             }
8610         }
8611     }
8612     /* so dptr know contains the address */
8613     pic16_freeAsmop(left,NULL,ic,TRUE);
8614     pic16_aopOp(result,ic,FALSE);
8615
8616     /* if bit then unpack */
8617     if (IS_BITFIELD(retype)) 
8618         genUnpackBits(result,"dptr",CPOINTER);
8619     else {
8620         size = AOP_SIZE(result);
8621         offset = 0 ;
8622
8623         while (size--) {
8624             pic16_emitcode("clr","a");
8625             pic16_emitcode("movc","a,@a+dptr");
8626             pic16_aopPut(AOP(result),"a",offset++);
8627             if (size)
8628                 pic16_emitcode("inc","dptr");
8629         }
8630     }
8631
8632     pic16_freeAsmop(result,NULL,ic,TRUE);
8633 }
8634 #endif
8635 /*-----------------------------------------------------------------*/
8636 /* genGenPointerGet - gget value from generic pointer space        */
8637 /*-----------------------------------------------------------------*/
8638 static void genGenPointerGet (operand *left,
8639                               operand *result, iCode *ic)
8640 {
8641         int size, offset, lit;
8642         sym_link *retype = getSpec(operandType(result));
8643
8644         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8645         pic16_aopOp(left,ic,FALSE);
8646         pic16_aopOp(result,ic,FALSE);
8647         size = AOP_SIZE(result);
8648
8649         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8650
8651         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
8652
8653                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
8654                 // load FSR0 from immediate
8655                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
8656                 offset = 0;
8657                 while(size--) {
8658                         if(size) {
8659                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
8660                         } else {
8661                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
8662                         }
8663                         offset++;
8664                 }
8665                 goto release;
8666
8667         }
8668         else { /* we need to get it byte by byte */
8669                 // set up FSR0 with address from left
8670                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
8671                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
8672
8673                 offset = 0 ;
8674
8675                 while(size--) {
8676                         if(size) {
8677                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
8678                         } else {
8679                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
8680                         }
8681                         offset++;
8682                 }
8683                 goto release;
8684         }
8685
8686   /* if bit then unpack */
8687         if (IS_BITFIELD(retype)) 
8688                 genUnpackBits(result,"BAD",GPOINTER);
8689
8690         release:
8691         pic16_freeAsmop(left,NULL,ic,TRUE);
8692         pic16_freeAsmop(result,NULL,ic,TRUE);
8693
8694 }
8695
8696 /*-----------------------------------------------------------------*/
8697 /* genConstPointerGet - get value from const generic pointer space */
8698 /*-----------------------------------------------------------------*/
8699 static void genConstPointerGet (operand *left,
8700                                 operand *result, iCode *ic)
8701 {
8702   //sym_link *retype = getSpec(operandType(result));
8703   symbol *albl = newiTempLabel(NULL);
8704   symbol *blbl = newiTempLabel(NULL);
8705   PIC_OPCODE poc;
8706
8707   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8708   pic16_aopOp(left,ic,FALSE);
8709   pic16_aopOp(result,ic,FALSE);
8710
8711
8712   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8713
8714   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8715
8716   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
8717   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
8718   pic16_emitpLabel(albl->key);
8719
8720   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8721     
8722   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
8723   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
8724   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
8725   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
8726   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
8727
8728   pic16_emitpLabel(blbl->key);
8729
8730   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
8731
8732
8733   pic16_freeAsmop(left,NULL,ic,TRUE);
8734   pic16_freeAsmop(result,NULL,ic,TRUE);
8735
8736 }
8737 /*-----------------------------------------------------------------*/
8738 /* genPointerGet - generate code for pointer get                   */
8739 /*-----------------------------------------------------------------*/
8740 static void genPointerGet (iCode *ic)
8741 {
8742     operand *left, *result ;
8743     sym_link *type, *etype;
8744     int p_type;
8745
8746     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8747
8748     left = IC_LEFT(ic);
8749     result = IC_RESULT(ic) ;
8750
8751     /* depending on the type of pointer we need to
8752     move it to the correct pointer register */
8753     type = operandType(left);
8754     etype = getSpec(type);
8755
8756 #if 0
8757     if (IS_PTR_CONST(type))
8758 #else
8759     if (IS_CODEPTR(type))
8760 #endif
8761       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8762
8763     /* if left is of type of pointer then it is simple */
8764     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8765         p_type = DCL_TYPE(type);
8766     else {
8767         /* we have to go by the storage class */
8768         p_type = PTR_TYPE(SPEC_OCLS(etype));
8769
8770         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8771
8772         if (SPEC_OCLS(etype)->codesp ) {
8773           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8774           //p_type = CPOINTER ; 
8775         }
8776         else
8777             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8778               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8779                /*p_type = FPOINTER ;*/ 
8780             else
8781                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8782                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8783 /*                  p_type = PPOINTER; */
8784                 else
8785                     if (SPEC_OCLS(etype) == idata )
8786                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8787 /*                      p_type = IPOINTER; */
8788                     else
8789                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8790 /*                      p_type = POINTER ; */
8791     }
8792
8793     /* now that we have the pointer type we assign
8794     the pointer values */
8795     switch (p_type) {
8796
8797     case POINTER:       
8798     case IPOINTER:
8799         genNearPointerGet (left,result,ic);
8800         break;
8801
8802     case PPOINTER:
8803         genPagedPointerGet(left,result,ic);
8804         break;
8805
8806     case FPOINTER:
8807         genFarPointerGet (left,result,ic);
8808         break;
8809
8810     case CPOINTER:
8811         genConstPointerGet (left,result,ic);
8812         //pic16_emitcodePointerGet (left,result,ic);
8813         break;
8814
8815     case GPOINTER:
8816 #if 0
8817       if (IS_PTR_CONST(type))
8818         genConstPointerGet (left,result,ic);
8819       else
8820 #endif
8821         genGenPointerGet (left,result,ic);
8822       break;
8823     }
8824
8825 }
8826
8827 /*-----------------------------------------------------------------*/
8828 /* genPackBits - generates code for packed bit storage             */
8829 /*-----------------------------------------------------------------*/
8830 static void genPackBits (sym_link    *etype ,
8831                          operand *right ,
8832                          char *rname, int p_type)
8833 {
8834     int shCount = 0 ;
8835     int offset = 0  ;
8836     int rLen = 0 ;
8837     int blen, bstr ;   
8838     char *l ;
8839
8840     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8841     blen = SPEC_BLEN(etype);
8842     bstr = SPEC_BSTR(etype);
8843
8844     l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8845     MOVA(l);   
8846
8847     /* if the bit lenth is less than or    */
8848     /* it exactly fits a byte then         */
8849     if (SPEC_BLEN(etype) <= 8 )  {
8850         shCount = SPEC_BSTR(etype) ;
8851
8852         /* shift left acc */
8853         AccLsh(shCount);
8854
8855         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8856
8857
8858             switch (p_type) {
8859                 case POINTER:
8860                     pic16_emitcode ("mov","b,a");
8861                     pic16_emitcode("mov","a,@%s",rname);
8862                     break;
8863
8864                 case FPOINTER:
8865                     pic16_emitcode ("mov","b,a");
8866                     pic16_emitcode("movx","a,@dptr");
8867                     break;
8868
8869                 case GPOINTER:
8870                     pic16_emitcode ("push","b");
8871                     pic16_emitcode ("push","acc");
8872                     pic16_emitcode ("lcall","__gptrget");
8873                     pic16_emitcode ("pop","b");
8874                     break;
8875             }
8876
8877             pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
8878                       ((unsigned char)(0xFF << (blen+bstr)) | 
8879                        (unsigned char)(0xFF >> (8-bstr)) ) );
8880             pic16_emitcode ("orl","a,b");
8881             if (p_type == GPOINTER)
8882                 pic16_emitcode("pop","b");
8883         }
8884     }
8885
8886     switch (p_type) {
8887         case POINTER:
8888             pic16_emitcode("mov","@%s,a",rname);
8889             break;
8890
8891         case FPOINTER:
8892             pic16_emitcode("movx","@dptr,a");
8893             break;
8894
8895         case GPOINTER:
8896             DEBUGpic16_emitcode(";lcall","__gptrput");
8897             break;
8898     }
8899
8900     /* if we r done */
8901     if ( SPEC_BLEN(etype) <= 8 )
8902         return ;
8903
8904     pic16_emitcode("inc","%s",rname);
8905     rLen = SPEC_BLEN(etype) ;     
8906
8907     /* now generate for lengths greater than one byte */
8908     while (1) {
8909
8910         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
8911
8912         rLen -= 8 ;
8913         if (rLen <= 0 )
8914             break ;
8915
8916         switch (p_type) {
8917             case POINTER:
8918                 if (*l == '@') {
8919                     MOVA(l);
8920                     pic16_emitcode("mov","@%s,a",rname);
8921                 } else
8922                     pic16_emitcode("mov","@%s,%s",rname,l);
8923                 break;
8924
8925             case FPOINTER:
8926                 MOVA(l);
8927                 pic16_emitcode("movx","@dptr,a");
8928                 break;
8929
8930             case GPOINTER:
8931                 MOVA(l);
8932                 DEBUGpic16_emitcode(";lcall","__gptrput");
8933                 break;  
8934         }   
8935         pic16_emitcode ("inc","%s",rname);
8936     }
8937
8938     MOVA(l);
8939
8940     /* last last was not complete */
8941     if (rLen)   {
8942         /* save the byte & read byte */
8943         switch (p_type) {
8944             case POINTER:
8945                 pic16_emitcode ("mov","b,a");
8946                 pic16_emitcode("mov","a,@%s",rname);
8947                 break;
8948
8949             case FPOINTER:
8950                 pic16_emitcode ("mov","b,a");
8951                 pic16_emitcode("movx","a,@dptr");
8952                 break;
8953
8954             case GPOINTER:
8955                 pic16_emitcode ("push","b");
8956                 pic16_emitcode ("push","acc");
8957                 pic16_emitcode ("lcall","__gptrget");
8958                 pic16_emitcode ("pop","b");
8959                 break;
8960         }
8961
8962         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8963         pic16_emitcode ("orl","a,b");
8964     }
8965
8966     if (p_type == GPOINTER)
8967         pic16_emitcode("pop","b");
8968
8969     switch (p_type) {
8970
8971     case POINTER:
8972         pic16_emitcode("mov","@%s,a",rname);
8973         break;
8974         
8975     case FPOINTER:
8976         pic16_emitcode("movx","@dptr,a");
8977         break;
8978         
8979     case GPOINTER:
8980         DEBUGpic16_emitcode(";lcall","__gptrput");
8981         break;                  
8982     }
8983 }
8984 /*-----------------------------------------------------------------*/
8985 /* genDataPointerSet - remat pointer to data space                 */
8986 /*-----------------------------------------------------------------*/
8987 static void genDataPointerSet(operand *right,
8988                               operand *result,
8989                               iCode *ic)
8990 {
8991     int size, offset = 0 ;
8992     char *l, buffer[256];
8993
8994     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8995     pic16_aopOp(right,ic,FALSE);
8996     
8997     l = pic16_aopGet(AOP(result),0,FALSE,TRUE);
8998     size = AOP_SIZE(right);
8999 /*
9000     if ( AOP_TYPE(result) == AOP_PCODE) {
9001       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9002               AOP(result)->aopu.pcop->name,
9003               PCOI(AOP(result)->aopu.pcop)->offset);
9004     }
9005 */
9006
9007     // tsd, was l+1 - the underline `_' prefix was being stripped
9008     while (size--) {
9009       if (offset) {
9010         sprintf(buffer,"(%s + %d)",l,offset);
9011         fprintf(stderr,"%s:%d: oops  %s\n",__FILE__, __LINE__, buffer);
9012       } else
9013         sprintf(buffer,"%s",l);
9014
9015         if (AOP_TYPE(right) == AOP_LIT) {
9016           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9017           lit = lit >> (8*offset);
9018           if(lit&0xff) {
9019             pic16_emitcode("movlw","%d",lit);
9020             pic16_emitcode("movwf","%s",buffer);
9021
9022             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9023             //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
9024             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9025
9026           } else {
9027             pic16_emitcode("clrf","%s",buffer);
9028             //pic16_emitpcode(POC_CLRF, pic16_popRegFromString(buffer));
9029             pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
9030           }
9031         }else {
9032           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
9033           pic16_emitcode("movwf","%s",buffer);
9034
9035           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9036           //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
9037           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9038
9039         }
9040
9041         offset++;
9042     }
9043
9044     pic16_freeAsmop(right,NULL,ic,TRUE);
9045     pic16_freeAsmop(result,NULL,ic,TRUE);
9046 }
9047
9048 /*-----------------------------------------------------------------*/
9049 /* genNearPointerSet - pic16_emitcode for near pointer put                */
9050 /*-----------------------------------------------------------------*/
9051 static void genNearPointerSet (operand *right,
9052                                operand *result, 
9053                                iCode *ic)
9054 {
9055   asmop *aop = NULL;
9056   char *l;
9057   sym_link *retype;
9058   sym_link *ptype = operandType(result);
9059
9060     
9061   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9062   retype= getSpec(operandType(right));
9063
9064   pic16_aopOp(result,ic,FALSE);
9065
9066     
9067   /* if the result is rematerializable &
9068      in data space & not a bit variable */
9069   //if (AOP_TYPE(result) == AOP_IMMD &&
9070   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
9071       DCL_TYPE(ptype) == POINTER   &&
9072       !IS_BITVAR(retype)) {
9073     genDataPointerSet (right,result,ic);
9074     pic16_freeAsmop(result,NULL,ic,TRUE);
9075     return;
9076   }
9077
9078   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9079   pic16_aopOp(right,ic,FALSE);
9080   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9081
9082   /* if the value is already in a pointer register
9083      then don't need anything more */
9084   if (!AOP_INPREG(AOP(result))) {
9085     /* otherwise get a free pointer register */
9086     //aop = newAsmop(0);
9087     //preg = getFreePtr(ic,&aop,FALSE);
9088     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9089     //pic16_emitcode("mov","%s,%s",
9090     //         preg->name,
9091     //         pic16_aopGet(AOP(result),0,FALSE,TRUE));
9092     //rname = preg->name ;
9093     //pic16_emitcode("movwf","fsr0");
9094     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0));
9095     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_fsr0));
9096     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9097     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9098     goto release;
9099
9100   }// else
9101 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9102
9103   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9104
9105   /* if bitfield then unpack the bits */
9106   if (IS_BITFIELD(retype)) {
9107     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9108            "The programmer is obviously confused");
9109 //      genPackBits (retype,right,"BAD",POINTER);
9110     exit(1);
9111   }
9112   else {
9113     /* we have can just get the values */
9114     int size = AOP_SIZE(right);
9115     int offset = 0 ;    
9116
9117     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9118     while (size--) {
9119       l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9120       if (*l == '@' ) {
9121         //MOVA(l);
9122         //pic16_emitcode("mov","@%s,a",rname);
9123         pic16_emitcode("movf","indf0,w ;1");
9124       } else {
9125
9126         if (AOP_TYPE(right) == AOP_LIT) {
9127           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9128           if(lit) {
9129             pic16_emitcode("movlw","%s",l);
9130             pic16_emitcode("movwf","indf0 ;2");
9131           } else 
9132             pic16_emitcode("clrf","indf0");
9133         }else {
9134           pic16_emitcode("movf","%s,w",l);
9135           pic16_emitcode("movwf","indf0 ;2");
9136         }
9137         //pic16_emitcode("mov","@%s,%s",rname,l);
9138       }
9139       if (size)
9140         pic16_emitcode("incf","fsr0,f ;3");
9141       //pic16_emitcode("inc","%s",rname);
9142       offset++;
9143     }
9144   }
9145
9146   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9147   /* now some housekeeping stuff */
9148   if (aop) {
9149     /* we had to allocate for this iCode */
9150     pic16_freeAsmop(NULL,aop,ic,TRUE);
9151   } else { 
9152     /* we did not allocate which means left
9153        already in a pointer register, then
9154        if size > 0 && this could be used again
9155        we have to point it back to where it 
9156        belongs */
9157     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9158     if (AOP_SIZE(right) > 1 &&
9159         !OP_SYMBOL(result)->remat &&
9160         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9161           ic->depth )) {
9162       int size = AOP_SIZE(right) - 1;
9163       while (size--)
9164         pic16_emitcode("decf","fsr0,f");
9165       //pic16_emitcode("dec","%s",rname);
9166     }
9167   }
9168
9169   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9170   /* done */
9171  release:
9172   pic16_freeAsmop(right,NULL,ic,TRUE);
9173   pic16_freeAsmop(result,NULL,ic,TRUE);
9174 }
9175
9176 /*-----------------------------------------------------------------*/
9177 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
9178 /*-----------------------------------------------------------------*/
9179 static void genPagedPointerSet (operand *right,
9180                                operand *result, 
9181                                iCode *ic)
9182 {
9183     asmop *aop = NULL;
9184     regs *preg = NULL ;
9185     char *rname , *l;
9186     sym_link *retype;
9187        
9188     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9189
9190     retype= getSpec(operandType(right));
9191     
9192     pic16_aopOp(result,ic,FALSE);
9193     
9194     /* if the value is already in a pointer register
9195        then don't need anything more */
9196     if (!AOP_INPREG(AOP(result))) {
9197         /* otherwise get a free pointer register */
9198         aop = newAsmop(0);
9199         preg = getFreePtr(ic,&aop,FALSE);
9200         pic16_emitcode("mov","%s,%s",
9201                 preg->name,
9202                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9203         rname = preg->name ;
9204     } else
9205         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9206     
9207     pic16_freeAsmop(result,NULL,ic,TRUE);
9208     pic16_aopOp (right,ic,FALSE);
9209
9210     /* if bitfield then unpack the bits */
9211     if (IS_BITFIELD(retype)) 
9212         genPackBits (retype,right,rname,PPOINTER);
9213     else {
9214         /* we have can just get the values */
9215         int size = AOP_SIZE(right);
9216         int offset = 0 ;        
9217         
9218         while (size--) {
9219             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9220             
9221             MOVA(l);
9222             pic16_emitcode("movx","@%s,a",rname);
9223
9224             if (size)
9225                 pic16_emitcode("inc","%s",rname);
9226
9227             offset++;
9228         }
9229     }
9230     
9231     /* now some housekeeping stuff */
9232     if (aop) {
9233         /* we had to allocate for this iCode */
9234         pic16_freeAsmop(NULL,aop,ic,TRUE);
9235     } else { 
9236         /* we did not allocate which means left
9237            already in a pointer register, then
9238            if size > 0 && this could be used again
9239            we have to point it back to where it 
9240            belongs */
9241         if (AOP_SIZE(right) > 1 &&
9242             !OP_SYMBOL(result)->remat &&
9243             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9244               ic->depth )) {
9245             int size = AOP_SIZE(right) - 1;
9246             while (size--)
9247                 pic16_emitcode("dec","%s",rname);
9248         }
9249     }
9250
9251     /* done */
9252     pic16_freeAsmop(right,NULL,ic,TRUE);
9253     
9254         
9255 }
9256
9257 /*-----------------------------------------------------------------*/
9258 /* genFarPointerSet - set value from far space                     */
9259 /*-----------------------------------------------------------------*/
9260 static void genFarPointerSet (operand *right,
9261                               operand *result, iCode *ic)
9262 {
9263     int size, offset ;
9264     sym_link *retype = getSpec(operandType(right));
9265
9266     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9267     pic16_aopOp(result,ic,FALSE);
9268
9269     /* if the operand is already in dptr 
9270     then we do nothing else we move the value to dptr */
9271     if (AOP_TYPE(result) != AOP_STR) {
9272         /* if this is remateriazable */
9273         if (AOP_TYPE(result) == AOP_IMMD)
9274             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9275         else { /* we need to get it byte by byte */
9276             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9277             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9278             if (options.model == MODEL_FLAT24)
9279             {
9280                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9281             }
9282         }
9283     }
9284     /* so dptr know contains the address */
9285     pic16_freeAsmop(result,NULL,ic,TRUE);
9286     pic16_aopOp(right,ic,FALSE);
9287
9288     /* if bit then unpack */
9289     if (IS_BITFIELD(retype)) 
9290         genPackBits(retype,right,"dptr",FPOINTER);
9291     else {
9292         size = AOP_SIZE(right);
9293         offset = 0 ;
9294
9295         while (size--) {
9296             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9297             MOVA(l);
9298             pic16_emitcode("movx","@dptr,a");
9299             if (size)
9300                 pic16_emitcode("inc","dptr");
9301         }
9302     }
9303
9304     pic16_freeAsmop(right,NULL,ic,TRUE);
9305 }
9306
9307 /*-----------------------------------------------------------------*/
9308 /* genGenPointerSet - set value from generic pointer space         */
9309 /*-----------------------------------------------------------------*/
9310 static void genGenPointerSet (operand *right,
9311                               operand *result, iCode *ic)
9312 {
9313         int size, offset, lit;
9314         sym_link *retype = getSpec(operandType(right));
9315
9316         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9317
9318         pic16_aopOp(result,ic,FALSE);
9319         pic16_aopOp(right,ic,FALSE);
9320         size = AOP_SIZE(right);
9321         offset = 0;
9322
9323         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9324
9325
9326         /* if the operand is already in dptr 
9327                 then we do nothing else we move the value to dptr */
9328         if (AOP_TYPE(result) != AOP_STR) {
9329                 /* if this is remateriazable */
9330                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9331                 // WARNING: anythig until "else" is untested!
9332                 if (AOP_TYPE(result) == AOP_IMMD) {
9333                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9334                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
9335                         // load FSR0 from immediate
9336                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9337                         offset = 0;
9338                         while(size--) {
9339                                 if(size) {
9340                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9341                                 } else {
9342                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9343                                 }
9344                                 offset++;
9345                         }
9346                         goto release;
9347                 }
9348                 else { /* we need to get it byte by byte */
9349                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9350                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9351
9352                         // set up FSR0 with address of result
9353                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9354                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9355
9356                         /* hack hack! see if this the FSR. If so don't load W */
9357                         if(AOP_TYPE(right) != AOP_ACC) {
9358
9359                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9360
9361                                 while(size--) {
9362                                         if(size) {
9363                                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9364                                         } else {
9365                                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9366                                         }
9367                                         offset++;
9368                                 }
9369                                 goto release;
9370                         } 
9371                         // right = ACC
9372                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9373
9374                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9375                         goto release;
9376         } // if (AOP_TYPE(result) != AOP_IMMD)
9377
9378         } // if (AOP_TYPE(result) != AOP_STR)
9379         /* so dptr know contains the address */
9380
9381
9382         /* if bit then unpack */
9383         if (IS_BITFIELD(retype)) 
9384                 genPackBits(retype,right,"dptr",GPOINTER);
9385         else {
9386                 size = AOP_SIZE(right);
9387                 offset = 0 ;
9388
9389                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9390
9391                 // set up FSR0 with address of result
9392                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9393                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9394         
9395                 while (size--) {
9396                         if (AOP_TYPE(right) == AOP_LIT) {
9397                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9398                                 if (size) {
9399                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
9400                                 } else {
9401                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9402                                 }
9403                         } else { // no literal
9404                                 if(size) {
9405                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
9406                                 } else {
9407                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
9408                                 }
9409                         }
9410                         offset++;
9411         }
9412         }
9413
9414         release:
9415         pic16_freeAsmop(right,NULL,ic,TRUE);
9416         pic16_freeAsmop(result,NULL,ic,TRUE);
9417 }
9418
9419 /*-----------------------------------------------------------------*/
9420 /* genPointerSet - stores the value into a pointer location        */
9421 /*-----------------------------------------------------------------*/
9422 static void genPointerSet (iCode *ic)
9423 {    
9424     operand *right, *result ;
9425     sym_link *type, *etype;
9426     int p_type;
9427
9428     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9429
9430     right = IC_RIGHT(ic);
9431     result = IC_RESULT(ic) ;
9432
9433     /* depending on the type of pointer we need to
9434     move it to the correct pointer register */
9435     type = operandType(result);
9436     etype = getSpec(type);
9437     /* if left is of type of pointer then it is simple */
9438     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9439         p_type = DCL_TYPE(type);
9440     }
9441     else {
9442         /* we have to go by the storage class */
9443         p_type = PTR_TYPE(SPEC_OCLS(etype));
9444
9445 /*      if (SPEC_OCLS(etype)->codesp ) { */
9446 /*          p_type = CPOINTER ;  */
9447 /*      } */
9448 /*      else */
9449 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9450 /*              p_type = FPOINTER ; */
9451 /*          else */
9452 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9453 /*                  p_type = PPOINTER ; */
9454 /*              else */
9455 /*                  if (SPEC_OCLS(etype) == idata ) */
9456 /*                      p_type = IPOINTER ; */
9457 /*                  else */
9458 /*                      p_type = POINTER ; */
9459     }
9460
9461     /* now that we have the pointer type we assign
9462     the pointer values */
9463     switch (p_type) {
9464
9465     case POINTER:
9466     case IPOINTER:
9467         genNearPointerSet (right,result,ic);
9468         break;
9469
9470     case PPOINTER:
9471         genPagedPointerSet (right,result,ic);
9472         break;
9473
9474     case FPOINTER:
9475         genFarPointerSet (right,result,ic);
9476         break;
9477
9478     case GPOINTER:
9479         genGenPointerSet (right,result,ic);
9480         break;
9481
9482     default:
9483       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9484               "genPointerSet: illegal pointer type");
9485     }
9486 }
9487
9488 /*-----------------------------------------------------------------*/
9489 /* genIfx - generate code for Ifx statement                        */
9490 /*-----------------------------------------------------------------*/
9491 static void genIfx (iCode *ic, iCode *popIc)
9492 {
9493   operand *cond = IC_COND(ic);
9494   int isbit =0;
9495
9496   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9497
9498   pic16_aopOp(cond,ic,FALSE);
9499
9500   /* get the value into acc */
9501   if (AOP_TYPE(cond) != AOP_CRY)
9502     pic16_toBoolean(cond);
9503   else
9504     isbit = 1;
9505   /* the result is now in the accumulator */
9506   pic16_freeAsmop(cond,NULL,ic,TRUE);
9507
9508   /* if there was something to be popped then do it */
9509   if (popIc)
9510     genIpop(popIc);
9511
9512   /* if the condition is  a bit variable */
9513   if (isbit && IS_ITEMP(cond) && 
9514       SPIL_LOC(cond)) {
9515     genIfxJump(ic,SPIL_LOC(cond)->rname);
9516     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9517   }
9518   else {
9519     if (isbit && !IS_ITEMP(cond))
9520       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9521     else
9522       genIfxJump(ic,"a");
9523   }
9524   ic->generated = 1;
9525
9526 }
9527
9528 /*-----------------------------------------------------------------*/
9529 /* genAddrOf - generates code for address of                       */
9530 /*-----------------------------------------------------------------*/
9531 #if 0
9532 static void genAddrOf (iCode *ic)
9533 {
9534   operand *right, *result, *left;
9535   int size, offset ;
9536
9537   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9538
9539
9540   //pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9541
9542   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
9543   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9544   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9545
9546   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
9547
9548   size = AOP_SIZE(IC_RESULT(ic));
9549   offset = 0;
9550
9551
9552   while (size--) {
9553     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),offset));
9554     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9555     offset++;
9556   }
9557
9558
9559   pic16_freeAsmop(left,NULL,ic,FALSE);
9560   pic16_freeAsmop(result,NULL,ic,TRUE);
9561
9562 }
9563
9564 #else   /* new genAddrOf */
9565
9566 static void genAddrOf (iCode *ic)
9567 {
9568   operand *result, *left;
9569   int size;
9570   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
9571   pCodeOp *pcop0, *pcop1, *pcop2;
9572
9573         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9574
9575         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9576         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9577
9578         sym = OP_SYMBOL( left );
9579
9580         size = AOP_SIZE(IC_RESULT(ic));
9581
9582         if(pic16_debug_verbose) {
9583                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9584                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9585         }
9586         
9587         /* Assume that what we want the address of is in data space
9588          * since there is no stack on the PIC, yet! -- VR */
9589         /* low */
9590         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9591
9592         /* high */
9593         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9594         
9595         /* upper */
9596         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9597         
9598
9599         if (size == 3) {
9600                 pic16_emitpcode(POC_MOVLW, pcop0);
9601                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9602                 pic16_emitpcode(POC_MOVLW, pcop1);
9603                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9604                 pic16_emitpcode(POC_MOVLW, pcop2);
9605                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9606         } else
9607         if (size == 2) {
9608                 pic16_emitpcode(POC_MOVLW, pcop0);
9609                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9610                 pic16_emitpcode(POC_MOVLW, pcop1);
9611                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9612         } else {
9613                 pic16_emitpcode(POC_MOVLW, pcop0);
9614                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9615         }
9616
9617         pic16_freeAsmop(result,NULL,ic,TRUE);
9618         pic16_freeAsmop(left, NULL, ic, FALSE);
9619 }
9620
9621 #endif  /* new genAddrOf */
9622
9623 #if 0
9624 /*-----------------------------------------------------------------*/
9625 /* genFarFarAssign - assignment when both are in far space         */
9626 /*-----------------------------------------------------------------*/
9627 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9628 {
9629     int size = AOP_SIZE(right);
9630     int offset = 0;
9631     char *l ;
9632     /* first push the right side on to the stack */
9633     while (size--) {
9634         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9635         MOVA(l);
9636         pic16_emitcode ("push","acc");
9637     }
9638     
9639     pic16_freeAsmop(right,NULL,ic,FALSE);
9640     /* now assign DPTR to result */
9641     pic16_aopOp(result,ic,FALSE);
9642     size = AOP_SIZE(result);
9643     while (size--) {
9644         pic16_emitcode ("pop","acc");
9645         pic16_aopPut(AOP(result),"a",--offset);
9646     }
9647     pic16_freeAsmop(result,NULL,ic,FALSE);
9648         
9649 }
9650 #endif
9651
9652 /*-----------------------------------------------------------------*/
9653 /* genAssign - generate code for assignment                        */
9654 /*-----------------------------------------------------------------*/
9655 static void genAssign (iCode *ic)
9656 {
9657   operand *result, *right;
9658   int size, offset,know_W;
9659   unsigned long lit = 0L;
9660
9661   result = IC_RESULT(ic);
9662   right  = IC_RIGHT(ic) ;
9663
9664   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9665   
9666   /* if they are the same */
9667   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9668     return ;
9669
9670   pic16_aopOp(right,ic,FALSE);
9671   pic16_aopOp(result,ic,TRUE);
9672
9673   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9674
9675   /* if they are the same registers */
9676   if (pic16_sameRegs(AOP(right),AOP(result)))
9677     goto release;
9678
9679   /* if the result is a bit */
9680   if (AOP_TYPE(result) == AOP_CRY) {
9681     /* if the right size is a literal then
9682        we know what the value is */
9683     if (AOP_TYPE(right) == AOP_LIT) {
9684           
9685       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9686                   pic16_popGet(AOP(result),0));
9687
9688       if (((int) operandLitValue(right))) 
9689         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9690                        AOP(result)->aopu.aop_dir,
9691                        AOP(result)->aopu.aop_dir);
9692       else
9693         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9694                        AOP(result)->aopu.aop_dir,
9695                        AOP(result)->aopu.aop_dir);
9696       goto release;
9697     }
9698
9699     /* the right is also a bit variable */
9700     if (AOP_TYPE(right) == AOP_CRY) {
9701       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9702       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9703       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9704
9705       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9706                      AOP(result)->aopu.aop_dir,
9707                      AOP(result)->aopu.aop_dir);
9708       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
9709                      AOP(right)->aopu.aop_dir,
9710                      AOP(right)->aopu.aop_dir);
9711       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9712                      AOP(result)->aopu.aop_dir,
9713                      AOP(result)->aopu.aop_dir);
9714       goto release ;
9715     }
9716
9717     /* we need to or */
9718     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9719     pic16_toBoolean(right);
9720     emitSKPZ;
9721     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9722     //pic16_aopPut(AOP(result),"a",0);
9723     goto release ;
9724   }
9725
9726   /* bit variables done */
9727   /* general case */
9728   size = AOP_SIZE(result);
9729   offset = 0 ;
9730   if(AOP_TYPE(right) == AOP_LIT)
9731     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9732
9733 /* VR - What is this?! */
9734   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9735   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9736     if(aopIdx(AOP(result),0) == 4) {
9737   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9738       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9739       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9740       goto release;
9741     } else
9742       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9743   }
9744
9745   know_W=-1;
9746   while (size--) {
9747   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9748     if(AOP_TYPE(right) == AOP_LIT) {
9749       if(lit&0xff) {
9750         if(know_W != (lit&0xff))
9751           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9752         know_W = lit&0xff;
9753         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9754       } else
9755         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9756
9757       lit >>= 8;
9758
9759     } else if (AOP_TYPE(right) == AOP_CRY) {
9760       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9761       if(offset == 0) {
9762         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
9763         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9764       }
9765     } else {
9766   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9767
9768 #if 1
9769         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
9770            normally should work, but mind that the W register live range
9771            is not checked, so if the code generator assumes that the W
9772            is already loaded after such a pair, wrong code will be generated.
9773            
9774            Checking the live range is the next step.
9775            This is experimental code yet and has not been fully tested yet.
9776            USE WITH CARE. Revert to old code by setting 0 to the condition above.
9777            Vangelis Rokas 030603 (vrokas@otenet.gr) */
9778            
9779         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9780 #else   
9781         /* This is the old code, which is assumed(?!) that works fine(!?) */
9782
9783         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9784         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9785 #endif
9786     }
9787             
9788     offset++;
9789   }
9790
9791     
9792  release:
9793   pic16_freeAsmop (right,NULL,ic,FALSE);
9794   pic16_freeAsmop (result,NULL,ic,TRUE);
9795 }   
9796
9797 /*-----------------------------------------------------------------*/
9798 /* genJumpTab - generates code for jump table                       */
9799 /*-----------------------------------------------------------------*/
9800 static void genJumpTab (iCode *ic)
9801 {
9802     symbol *jtab;
9803     char *l;
9804
9805     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9806
9807     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9808     /* get the condition into accumulator */
9809     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9810     MOVA(l);
9811     /* multiply by three */
9812     pic16_emitcode("add","a,acc");
9813     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9814
9815     jtab = newiTempLabel(NULL);
9816     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9817     pic16_emitcode("jmp","@a+dptr");
9818     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9819
9820     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9821     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9822     emitSKPNC;
9823     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9824     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9825     pic16_emitpLabel(jtab->key);
9826
9827     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9828
9829     /* now generate the jump labels */
9830     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9831          jtab = setNextItem(IC_JTLABELS(ic))) {
9832         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9833         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9834         
9835     }
9836
9837 }
9838
9839 /*-----------------------------------------------------------------*/
9840 /* genMixedOperation - gen code for operators between mixed types  */
9841 /*-----------------------------------------------------------------*/
9842 /*
9843   TSD - Written for the PIC port - but this unfortunately is buggy.
9844   This routine is good in that it is able to efficiently promote 
9845   types to different (larger) sizes. Unfortunately, the temporary
9846   variables that are optimized out by this routine are sometimes
9847   used in other places. So until I know how to really parse the 
9848   iCode tree, I'm going to not be using this routine :(.
9849 */
9850 static int genMixedOperation (iCode *ic)
9851 {
9852 #if 0
9853   operand *result = IC_RESULT(ic);
9854   sym_link *ctype = operandType(IC_LEFT(ic));
9855   operand *right = IC_RIGHT(ic);
9856   int ret = 0;
9857   int big,small;
9858   int offset;
9859
9860   iCode *nextic;
9861   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9862
9863   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9864
9865   nextic = ic->next;
9866   if(!nextic)
9867     return 0;
9868
9869   nextright = IC_RIGHT(nextic);
9870   nextleft  = IC_LEFT(nextic);
9871   nextresult = IC_RESULT(nextic);
9872
9873   pic16_aopOp(right,ic,FALSE);
9874   pic16_aopOp(result,ic,FALSE);
9875   pic16_aopOp(nextright,  nextic, FALSE);
9876   pic16_aopOp(nextleft,   nextic, FALSE);
9877   pic16_aopOp(nextresult, nextic, FALSE);
9878
9879   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9880
9881     operand *t = right;
9882     right = nextright;
9883     nextright = t; 
9884
9885     pic16_emitcode(";remove right +","");
9886
9887   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9888 /*
9889     operand *t = right;
9890     right = nextleft;
9891     nextleft = t; 
9892 */
9893     pic16_emitcode(";remove left +","");
9894   } else
9895     return 0;
9896
9897   big = AOP_SIZE(nextleft);
9898   small = AOP_SIZE(nextright);
9899
9900   switch(nextic->op) {
9901
9902   case '+':
9903     pic16_emitcode(";optimize a +","");
9904     /* if unsigned or not an integral type */
9905     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9906       pic16_emitcode(";add a bit to something","");
9907     } else {
9908
9909       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9910
9911       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9912         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9913         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9914       } else
9915         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9916
9917       offset = 0;
9918       while(--big) {
9919
9920         offset++;
9921
9922         if(--small) {
9923           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9924             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9925             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9926           }
9927
9928           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9929           emitSKPNC;
9930           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9931                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9932                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9933           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9934           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9935
9936         } else {
9937           pic16_emitcode("rlf","known_zero,w");
9938
9939           /*
9940             if right is signed
9941               btfsc  right,7
9942                addlw ff
9943           */
9944           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9945             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9946             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9947           } else {
9948             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9949           }
9950         }
9951       }
9952       ret = 1;
9953     }
9954   }
9955   ret = 1;
9956
9957 release:
9958   pic16_freeAsmop(right,NULL,ic,TRUE);
9959   pic16_freeAsmop(result,NULL,ic,TRUE);
9960   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9961   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9962   if(ret)
9963     nextic->generated = 1;
9964
9965   return ret;
9966 #else
9967   return 0;
9968 #endif
9969 }
9970 /*-----------------------------------------------------------------*/
9971 /* genCast - gen code for casting                                  */
9972 /*-----------------------------------------------------------------*/
9973 static void genCast (iCode *ic)
9974 {
9975   operand *result = IC_RESULT(ic);
9976   sym_link *ctype = operandType(IC_LEFT(ic));
9977   sym_link *rtype = operandType(IC_RIGHT(ic));
9978   operand *right = IC_RIGHT(ic);
9979   int size, offset ;
9980
9981         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9982         /* if they are equivalent then do nothing */
9983         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9984                 return ;
9985
9986         pic16_aopOp(right,ic,FALSE) ;
9987         pic16_aopOp(result,ic,FALSE);
9988
9989         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9990
9991         /* if the result is a bit */
9992         if (AOP_TYPE(result) == AOP_CRY) {
9993         
9994                 /* if the right size is a literal then
9995                  * we know what the value is */
9996                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9997
9998                 if (AOP_TYPE(right) == AOP_LIT) {
9999                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10000                                 pic16_popGet(AOP(result),0));
10001
10002                         if (((int) operandLitValue(right))) 
10003                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10004                                         AOP(result)->aopu.aop_dir,
10005                                         AOP(result)->aopu.aop_dir);
10006                         else
10007                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10008                                         AOP(result)->aopu.aop_dir,
10009                                         AOP(result)->aopu.aop_dir);
10010                         goto release;
10011                 }
10012
10013                 /* the right is also a bit variable */
10014                 if (AOP_TYPE(right) == AOP_CRY) {
10015                         emitCLRC;
10016                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10017
10018                         pic16_emitcode("clrc","");
10019                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10020                                 AOP(right)->aopu.aop_dir,
10021                                 AOP(right)->aopu.aop_dir);
10022                         pic16_aopPut(AOP(result),"c",0);
10023                         goto release ;
10024                 }
10025
10026                 /* we need to or */
10027                 if (AOP_TYPE(right) == AOP_REG) {
10028                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10029                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10030                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10031                 }
10032                 pic16_toBoolean(right);
10033                 pic16_aopPut(AOP(result),"a",0);
10034                 goto release ;
10035         }
10036
10037         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10038           int offset = 1;
10039
10040                 size = AOP_SIZE(result);
10041
10042                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10043
10044                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10045                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10046                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10047
10048                 while (size--)
10049                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10050
10051                 goto release;
10052         }
10053
10054         /* if they are the same size : or less */
10055         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10056
10057                 /* if they are in the same place */
10058                 if (pic16_sameRegs(AOP(right),AOP(result)))
10059                         goto release;
10060
10061                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10062 #if 0
10063                 if (IS_PTR_CONST(rtype))
10064 #else
10065                 if (IS_CODEPTR(rtype))
10066 #endif
10067                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10068
10069 #if 0
10070                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10071 #else
10072                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10073 #endif
10074                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10075
10076 #if 0
10077                 if(AOP_TYPE(right) == AOP_IMMD) {
10078                   pCodeOp *pcop0, *pcop1, *pcop2;
10079                   symbol *sym = OP_SYMBOL( right );
10080
10081                         size = AOP_SIZE(result);
10082                         /* low */
10083                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10084                         /* high */
10085                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10086                         /* upper */
10087                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10088         
10089                         if (size == 3) {
10090                                 pic16_emitpcode(POC_MOVLW, pcop0);
10091                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10092                                 pic16_emitpcode(POC_MOVLW, pcop1);
10093                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10094                                 pic16_emitpcode(POC_MOVLW, pcop2);
10095                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10096                         } else
10097                         if (size == 2) {
10098                                 pic16_emitpcode(POC_MOVLW, pcop0);
10099                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10100                                 pic16_emitpcode(POC_MOVLW, pcop1);
10101                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10102                         } else {
10103                                 pic16_emitpcode(POC_MOVLW, pcop0);
10104                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10105                         }
10106                 } else
10107 #endif
10108                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10109                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10110                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10111                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10112                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10113                         if(AOP_SIZE(result) <2)
10114                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10115                 } else {
10116                         /* if they in different places then copy */
10117                         size = AOP_SIZE(result);
10118                         offset = 0 ;
10119                         while (size--) {
10120                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10121                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10122                                 offset++;
10123                         }
10124                 }
10125                 goto release;
10126         }
10127
10128         /* if the result is of type pointer */
10129         if (IS_PTR(ctype)) {
10130           int p_type;
10131           sym_link *type = operandType(right);
10132           sym_link *etype = getSpec(type);
10133
10134                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10135
10136                 /* pointer to generic pointer */
10137                 if (IS_GENPTR(ctype)) {
10138                   char *l = zero;
10139             
10140                         if (IS_PTR(type)) 
10141                                 p_type = DCL_TYPE(type);
10142                         else {
10143                 /* we have to go by the storage class */
10144                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10145
10146 /*              if (SPEC_OCLS(etype)->codesp )  */
10147 /*                  p_type = CPOINTER ;  */
10148 /*              else */
10149 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10150 /*                      p_type = FPOINTER ; */
10151 /*                  else */
10152 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10153 /*                          p_type = PPOINTER; */
10154 /*                      else */
10155 /*                          if (SPEC_OCLS(etype) == idata ) */
10156 /*                              p_type = IPOINTER ; */
10157 /*                          else */
10158 /*                              p_type = POINTER ; */
10159             }
10160                 
10161             /* the first two bytes are known */
10162       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10163             size = GPTRSIZE - 1; 
10164             offset = 0 ;
10165             while (size--) {
10166               if(offset < AOP_SIZE(right)) {
10167       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10168                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10169                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10170                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10171                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10172                 } else { 
10173                   pic16_aopPut(AOP(result),
10174                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10175                          offset);
10176                 }
10177               } else 
10178                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10179               offset++;
10180             }
10181             /* the last byte depending on type */
10182             switch (p_type) {
10183             case IPOINTER:
10184             case POINTER:
10185                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10186                 break;
10187             case FPOINTER:
10188               pic16_emitcode(";BUG!? ","%d",__LINE__);
10189                 l = one;
10190                 break;
10191             case CPOINTER:
10192               pic16_emitcode(";BUG!? ","%d",__LINE__);
10193                 l = "#0x02";
10194                 break;                          
10195             case PPOINTER:
10196               pic16_emitcode(";BUG!? ","%d",__LINE__);
10197                 l = "#0x03";
10198                 break;
10199                 
10200             default:
10201                 /* this should never happen */
10202                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10203                        "got unknown pointer type");
10204                 exit(1);
10205             }
10206             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
10207             goto release ;
10208         }
10209         
10210         /* just copy the pointers */
10211         size = AOP_SIZE(result);
10212         offset = 0 ;
10213         while (size--) {
10214             pic16_aopPut(AOP(result),
10215                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10216                    offset);
10217             offset++;
10218         }
10219         goto release ;
10220     }
10221     
10222
10223
10224     /* so we now know that the size of destination is greater
10225     than the size of the source.
10226     Now, if the next iCode is an operator then we might be
10227     able to optimize the operation without performing a cast.
10228     */
10229     if(genMixedOperation(ic))
10230       goto release;
10231
10232     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10233     
10234     /* we move to result for the size of source */
10235     size = AOP_SIZE(right);
10236     offset = 0 ;
10237     while (size--) {
10238       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
10239       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
10240       offset++;
10241     }
10242
10243     /* now depending on the sign of the destination */
10244     size = AOP_SIZE(result) - AOP_SIZE(right);
10245     /* if unsigned or not an integral type */
10246     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10247       while (size--)
10248         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10249     } else {
10250       /* we need to extend the sign :( */
10251
10252       if(size == 1) {
10253         /* Save one instruction of casting char to int */
10254         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
10255         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10256         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
10257       } else {
10258         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10259
10260         if(offset)
10261           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10262         else
10263           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10264         
10265         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
10266
10267         while (size--)
10268           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
10269       }
10270     }
10271
10272 release:
10273     pic16_freeAsmop(right,NULL,ic,TRUE);
10274     pic16_freeAsmop(result,NULL,ic,TRUE);
10275
10276 }
10277
10278 /*-----------------------------------------------------------------*/
10279 /* genDjnz - generate decrement & jump if not zero instrucion      */
10280 /*-----------------------------------------------------------------*/
10281 static int genDjnz (iCode *ic, iCode *ifx)
10282 {
10283     symbol *lbl, *lbl1;
10284     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10285
10286     if (!ifx)
10287         return 0;
10288     
10289     /* if the if condition has a false label
10290        then we cannot save */
10291     if (IC_FALSE(ifx))
10292         return 0;
10293
10294     /* if the minus is not of the form 
10295        a = a - 1 */
10296     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10297         !IS_OP_LITERAL(IC_RIGHT(ic)))
10298         return 0;
10299
10300     if (operandLitValue(IC_RIGHT(ic)) != 1)
10301         return 0;
10302
10303     /* if the size of this greater than one then no
10304        saving */
10305     if (getSize(operandType(IC_RESULT(ic))) > 1)
10306         return 0;
10307
10308     /* otherwise we can save BIG */
10309     lbl = newiTempLabel(NULL);
10310     lbl1= newiTempLabel(NULL);
10311
10312     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10313     
10314     if (IS_AOP_PREG(IC_RESULT(ic))) {
10315         pic16_emitcode("dec","%s",
10316                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10317         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10318         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10319     } else {    
10320
10321
10322       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10323       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10324
10325       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10326       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10327
10328     }
10329 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10330 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10331 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10332 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10333
10334     
10335     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10336     ifx->generated = 1;
10337     return 1;
10338 }
10339
10340 /*-----------------------------------------------------------------*/
10341 /* genReceive - generate code for a receive iCode                  */
10342 /*-----------------------------------------------------------------*/
10343 static void genReceive (iCode *ic)
10344 {    
10345         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10346
10347         if (isOperandInFarSpace(IC_RESULT(ic)) && 
10348                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10349                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10350
10351           int size = getSize(operandType(IC_RESULT(ic)));
10352           int offset =  pic16_fReturnSizePic - size;
10353
10354                 while (size--) {
10355                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10356                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10357                         offset++;
10358                 }
10359
10360                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10361
10362                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10363                 size = AOP_SIZE(IC_RESULT(ic));
10364                 offset = 0;
10365                 while (size--) {
10366                         pic16_emitcode ("pop","acc");
10367                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10368                 }
10369         } else {
10370                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
10371
10372                 _G.accInUse++;
10373                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10374                 _G.accInUse--;
10375                 assignResultValue(IC_RESULT(ic));       
10376         }
10377
10378         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10379 }
10380
10381 /*-----------------------------------------------------------------*/
10382 /* genDummyRead - generate code for dummy read of volatiles        */
10383 /*-----------------------------------------------------------------*/
10384 static void
10385 genDummyRead (iCode * ic)
10386 {
10387   pic16_emitcode ("; genDummyRead","");
10388   pic16_emitcode ("; not implemented","");
10389
10390   ic = ic;
10391 }
10392
10393 /*-----------------------------------------------------------------*/
10394 /* genpic16Code - generate code for pic16 based controllers        */
10395 /*-----------------------------------------------------------------*/
10396 /*
10397  * At this point, ralloc.c has gone through the iCode and attempted
10398  * to optimize in a way suitable for a PIC. Now we've got to generate
10399  * PIC instructions that correspond to the iCode.
10400  *
10401  * Once the instructions are generated, we'll pass through both the
10402  * peep hole optimizer and the pCode optimizer.
10403  *-----------------------------------------------------------------*/
10404
10405 void genpic16Code (iCode *lic)
10406 {
10407     iCode *ic;
10408     int cln = 0;
10409
10410     lineHead = lineCurr = NULL;
10411
10412     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10413     pic16_addpBlock(pb);
10414
10415 #if 0
10416     /* if debug information required */
10417     if (options.debug && currFunc) {
10418       if (currFunc) {
10419         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10420         _G.debugLine = 1;
10421         if (IS_STATIC(currFunc->etype)) {
10422           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
10423           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10424         } else {
10425           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
10426           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10427         }
10428         _G.debugLine = 0;
10429       }
10430     }
10431 #endif
10432
10433 //    dumpiCode(lic);
10434
10435     for (ic = lic ; ic ; ic = ic->next ) {
10436
10437 //      fprintf(stderr, "; VR = %c %x\n", ic->op, ic->op);
10438 //      DEBUGpic16_emitcode("; VR", "");
10439       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10440         if ( cln != ic->lineno ) {
10441             if ( options.debug ) {
10442                 _G.debugLine = 1;
10443                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10444                          FileBaseName(ic->filename),ic->lineno,
10445                          ic->level,ic->block);
10446                 _G.debugLine = 0;
10447             }
10448             
10449             if(!options.noCcodeInAsm) {
10450                 pic16_addpCode2pBlock(pb,
10451                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
10452                                 printCLine(ic->filename, ic->lineno)));
10453             }
10454
10455             cln = ic->lineno ;
10456         }
10457         
10458         if(options.iCodeInAsm) {
10459                 /* insert here code to print iCode as comment */
10460                 pic16_emitcomment("; ic:%d: %s", ic->seq, printILine(ic));
10461         }
10462         
10463         /* if the result is marked as
10464            spilt and rematerializable or code for
10465            this has already been generated then
10466            do nothing */
10467         if (resultRemat(ic) || ic->generated ) 
10468             continue ;
10469         
10470         /* depending on the operation */
10471         switch (ic->op) {
10472         case '!' :
10473             pic16_genNot(ic);
10474             break;
10475             
10476         case '~' :
10477             pic16_genCpl(ic);
10478             break;
10479             
10480         case UNARYMINUS:
10481             genUminus (ic);
10482             break;
10483             
10484         case IPUSH:
10485             genIpush (ic);
10486             break;
10487             
10488         case IPOP:
10489             /* IPOP happens only when trying to restore a 
10490                spilt live range, if there is an ifx statement
10491                following this pop then the if statement might
10492                be using some of the registers being popped which
10493                would destroy the contents of the register so
10494                we need to check for this condition and handle it */
10495             if (ic->next            && 
10496                 ic->next->op == IFX &&
10497                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10498                 genIfx (ic->next,ic);
10499             else
10500                 genIpop (ic);
10501             break; 
10502             
10503         case CALL:
10504             genCall (ic);
10505             break;
10506             
10507         case PCALL:
10508             genPcall (ic);
10509             break;
10510             
10511         case FUNCTION:
10512             genFunction (ic);
10513             break;
10514             
10515         case ENDFUNCTION:
10516             genEndFunction (ic);
10517             break;
10518             
10519         case RETURN:
10520             genRet (ic);
10521             break;
10522             
10523         case LABEL:
10524             genLabel (ic);
10525             break;
10526             
10527         case GOTO:
10528             genGoto (ic);
10529             break;
10530             
10531         case '+' :
10532             pic16_genPlus (ic) ;
10533             break;
10534             
10535         case '-' :
10536             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10537                 pic16_genMinus (ic);
10538             break;
10539             
10540         case '*' :
10541             genMult (ic);
10542             break;
10543             
10544         case '/' :
10545             genDiv (ic) ;
10546             break;
10547             
10548         case '%' :
10549             genMod (ic);
10550             break;
10551             
10552         case '>' :
10553             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10554             break;
10555             
10556         case '<' :
10557             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10558             break;
10559             
10560         case LE_OP:
10561         case GE_OP:
10562         case NE_OP:
10563             
10564             /* note these two are xlated by algebraic equivalence
10565                during parsing SDCC.y */
10566             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10567                    "got '>=' or '<=' shouldn't have come here");
10568             break;      
10569             
10570         case EQ_OP:
10571             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10572             break;          
10573             
10574         case AND_OP:
10575             genAndOp (ic);
10576             break;
10577             
10578         case OR_OP:
10579             genOrOp (ic);
10580             break;
10581             
10582         case '^' :
10583             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10584             break;
10585             
10586         case '|' :
10587                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10588             break;
10589             
10590         case BITWISEAND:
10591             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10592             break;
10593             
10594         case INLINEASM:
10595             genInline (ic);
10596             break;
10597             
10598         case RRC:
10599             genRRC (ic);
10600             break;
10601             
10602         case RLC:
10603             genRLC (ic);
10604             break;
10605             
10606         case GETHBIT:
10607             genGetHbit (ic);
10608             break;
10609             
10610         case LEFT_OP:
10611             genLeftShift (ic);
10612             break;
10613             
10614         case RIGHT_OP:
10615             genRightShift (ic);
10616             break;
10617             
10618         case GET_VALUE_AT_ADDRESS:
10619             genPointerGet(ic);
10620             break;
10621             
10622         case '=' :
10623             if (POINTER_SET(ic))
10624                 genPointerSet(ic);
10625             else
10626                 genAssign(ic);
10627             break;
10628             
10629         case IFX:
10630             genIfx (ic,NULL);
10631             break;
10632             
10633         case ADDRESS_OF:
10634             genAddrOf (ic);
10635             break;
10636             
10637         case JUMPTABLE:
10638             genJumpTab (ic);
10639             break;
10640             
10641         case CAST:
10642             genCast (ic);
10643             break;
10644             
10645         case RECEIVE:
10646             genReceive(ic);
10647             break;
10648             
10649         case SEND:
10650             addSet(&_G.sendSet,ic);
10651             break;
10652
10653         case DUMMY_READ_VOLATILE:
10654           genDummyRead (ic);
10655           break;
10656
10657         default :
10658             ic = ic;
10659         }
10660     }
10661
10662
10663     /* now we are ready to call the
10664        peep hole optimizer */
10665     if (!options.nopeep) {
10666       peepHole (&lineHead);
10667     }
10668     /* now do the actual printing */
10669     printLine (lineHead,codeOutFile);
10670
10671 #ifdef PCODE_DEBUG
10672     DFPRINTF((stderr,"printing pBlock\n\n"));
10673     pic16_printpBlock(stdout,pb);
10674 #endif
10675
10676     return;
10677 }
10678