* support/regression/tests/zeropad.c: added TEST_G macro for alpha build
[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 void pic16_genMult16X16_16(operand *, operand *, operand *);
53 void pic16_genMult32X32_32(operand *, operand *, operand *);
54 pCode *pic16_AssembleLine(char *line, int peeps);
55 extern void pic16_printpBlock(FILE *of, pBlock *pb);
56 static asmop *newAsmop (short type);
57 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset);
58 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
59 static void mov2w (asmop *aop, int offset);
60 static int aopIdx (asmop *aop, int offset);
61
62 static int labelOffset=0;
63 extern int pic16_debug_verbose;
64 static int optimized_for_speed = 0;
65 /*
66   hack hack
67
68 */
69
70 /* max_key keeps track of the largest label number used in 
71    a function. This is then used to adjust the label offset
72    for the next function.
73 */
74 static int max_key=0;
75 static int GpsuedoStkPtr=0;
76
77 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
78 unsigned int pic16aopLiteral (value *val, int offset);
79 const char *pic16_AopType(short type);
80 static iCode *ifxForOp ( operand *op, iCode *ic );
81
82 void pic16_pushpCodeOp(pCodeOp *pcop);
83 void pic16_poppCodeOp(pCodeOp *pcop);
84
85 static bool is_LitOp(operand *op);
86
87
88 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
89
90 /* this is the down and dirty file with all kinds of 
91    kludgy & hacky stuff. This is what it is all about
92    CODE GENERATION for a specific MCU . some of the
93    routines may be reusable, will have to see */
94
95 static char *zero = "#0x00";
96 static char *one  = "#0x01";
97 static char *spname = "sp";
98
99
100 /*
101  * Function return value policy (MSB-->LSB):
102  *  8 bits      -> WREG
103  * 16 bits      -> PRODL:WREG
104  * 24 bits      -> PRODH:PRODL:WREG
105  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
106  * >32 bits     -> on stack, and FSR0 points to the beginning
107  *
108  */
109  
110
111 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
112 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
113 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
114 static char **fReturn = fReturnpic16;
115
116 static char *accUse[] = {"WREG"};
117
118 //static short rbank = -1;
119
120 static struct {
121     short r0Pushed;
122     short r1Pushed;
123     short accInUse;
124     short inLine;
125     short debugLine;
126     short nRegsSaved;
127     set *sendSet;
128     int interruptvector;
129 } _G;
130
131 /* Resolved ifx structure. This structure stores information
132    about an iCode ifx that makes it easier to generate code.
133 */
134 typedef struct resolvedIfx {
135   symbol *lbl;     /* pointer to a label */
136   int condition;   /* true or false ifx */
137   int generated;   /* set true when the code associated with the ifx
138                     * is generated */
139 } resolvedIfx;
140
141 extern int pic16_ptrRegReq ;
142 extern int pic16_nRegs;
143 extern FILE *codeOutFile;
144 static void saverbank (int, iCode *,bool);
145
146 static lineNode *lineHead = NULL;
147 static lineNode *lineCurr = NULL;
148
149 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
150 0xE0, 0xC0, 0x80, 0x00};
151 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
152 0x07, 0x03, 0x01, 0x00};
153
154 static  pBlock *pb;
155
156 /*-----------------------------------------------------------------*/
157 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
158 /*                 exponent of 2 is returned, otherwise -1 is      */
159 /*                 returned.                                       */
160 /* note that this is similar to the function `powof2' in SDCCsymt  */
161 /* if(n == 2^y)                                                    */
162 /*   return y;                                                     */
163 /* return -1;                                                      */
164 /*-----------------------------------------------------------------*/
165 static int my_powof2 (unsigned long num)
166 {
167   if(num) {
168     if( (num & (num-1)) == 0) {
169       int nshifts = -1;
170       while(num) {
171         num>>=1;
172         nshifts++;
173       }
174       return nshifts;
175     }
176   }
177
178   return -1;
179 }
180
181 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
182 {
183   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
184                        line_no,
185                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
186                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
187                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
188                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
189                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
190                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
191                        ((result) ? AOP_SIZE(result) : 0));
192 }
193
194 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
195 {
196
197   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
198                        line_no,
199                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
200                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
201                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
202                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
203                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
204                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
205
206 }
207
208 void pic16_emitpcomment (char *fmt, ...)
209 {
210     va_list ap;
211     char lb[INITIAL_INLINEASM];  
212     char *lbp = lb;
213
214     va_start(ap,fmt);   
215
216     lb[0] = ';';
217     vsprintf(lb+1,fmt,ap);
218
219     while (isspace(*lbp)) lbp++;
220
221     if (lbp && *lbp) 
222         lineCurr = (lineCurr ?
223                     connectLine(lineCurr,newLineNode(lb)) :
224                     (lineHead = newLineNode(lb)));
225     lineCurr->isInline = _G.inLine;
226     lineCurr->isDebug  = _G.debugLine;
227
228     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
229     va_end(ap);
230
231 //      fprintf(stderr, "%s\n", lb);
232 }
233
234 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
235 {
236     va_list ap;
237     char lb[INITIAL_INLINEASM];  
238     char *lbp = lb;
239
240     if(!pic16_debug_verbose)
241       return;
242
243     va_start(ap,fmt);   
244
245     if (inst && *inst) {
246         if (fmt && *fmt)
247             sprintf(lb,"%s\t",inst);
248         else
249             sprintf(lb,"%s",inst);
250         vsprintf(lb+(strlen(lb)),fmt,ap);
251     }  else
252         vsprintf(lb,fmt,ap);
253
254     while (isspace(*lbp)) lbp++;
255
256     if (lbp && *lbp) 
257         lineCurr = (lineCurr ?
258                     connectLine(lineCurr,newLineNode(lb)) :
259                     (lineHead = newLineNode(lb)));
260     lineCurr->isInline = _G.inLine;
261     lineCurr->isDebug  = _G.debugLine;
262
263     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
264     va_end(ap);
265
266 //      fprintf(stderr, "%s\n", lb);
267 }
268
269 void pic16_emitpLabel(int key)
270 {
271   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
272 }
273
274 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
275 {
276
277   if(pcop)
278     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
279   else
280     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
281     
282 //    fprintf(stderr, "%s\n", pcop->name);
283 }
284
285 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
286 {
287
288   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
289
290 }
291
292
293 #if 1
294 #define pic16_emitcode  DEBUGpic16_emitcode
295 #else
296 /*-----------------------------------------------------------------*/
297 /* pic16_emitcode - writes the code into a file : for now it is simple    */
298 /*-----------------------------------------------------------------*/
299 void pic16_emitcode (char *inst,char *fmt, ...)
300 {
301     va_list ap;
302     char lb[INITIAL_INLINEASM];  
303     char *lbp = lb;
304
305     va_start(ap,fmt);   
306
307     if (inst && *inst) {
308         if (fmt && *fmt)
309             sprintf(lb,"%s\t",inst);
310         else
311             sprintf(lb,"%s",inst);
312         vsprintf(lb+(strlen(lb)),fmt,ap);
313     }  else
314         vsprintf(lb,fmt,ap);
315
316     while (isspace(*lbp)) lbp++;
317
318     if (lbp && *lbp) 
319         lineCurr = (lineCurr ?
320                     connectLine(lineCurr,newLineNode(lb)) :
321                     (lineHead = newLineNode(lb)));
322     lineCurr->isInline = _G.inLine;
323     lineCurr->isDebug  = _G.debugLine;
324
325 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
326
327 //    if(pic16_debug_verbose)
328 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
329
330     va_end(ap);
331 }
332 #endif
333
334
335 /*-----------------------------------------------------------------*/
336 /* pic16_emitDebuggerSymbol - associate the current code location  */
337 /*   with a debugger symbol                                        */
338 /*-----------------------------------------------------------------*/
339 void
340 pic16_emitDebuggerSymbol (char * debugSym)
341 {
342   _G.debugLine = 1;
343   pic16_emitcode (";", "%s ==.", debugSym);
344   _G.debugLine = 0;
345 }
346
347
348 /*-----------------------------------------------------------------*/
349 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
350 /*-----------------------------------------------------------------*/
351 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
352 {
353     bool r0iu = FALSE , r1iu = FALSE;
354     bool r0ou = FALSE , r1ou = FALSE;
355
356         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
357
358     /* the logic: if r0 & r1 used in the instruction
359     then we are in trouble otherwise */
360
361     /* first check if r0 & r1 are used by this
362     instruction, in which case we are in trouble */
363     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
364         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
365     {
366         goto endOfWorld;      
367     }
368
369     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
370     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
371
372     /* if no usage of r0 then return it */
373     if (!r0iu && !r0ou) {
374         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
375         (*aopp)->type = AOP_R0;
376         
377         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
378     }
379
380     /* if no usage of r1 then return it */
381     if (!r1iu && !r1ou) {
382         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
383         (*aopp)->type = AOP_R1;
384
385         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
386     }    
387
388     /* now we know they both have usage */
389     /* if r0 not used in this instruction */
390     if (!r0iu) {
391         /* push it if not already pushed */
392         if (!_G.r0Pushed) {
393           //pic16_emitcode ("push","%s",
394           //          pic16_regWithIdx(R0_IDX)->dname);
395             _G.r0Pushed++ ;
396         }
397         
398         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
399         (*aopp)->type = AOP_R0;
400
401         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
402     }
403
404     /* if r1 not used then */
405
406     if (!r1iu) {
407         /* push it if not already pushed */
408         if (!_G.r1Pushed) {
409           //pic16_emitcode ("push","%s",
410           //          pic16_regWithIdx(R1_IDX)->dname);
411             _G.r1Pushed++ ;
412         }
413         
414         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
415         (*aopp)->type = AOP_R1;
416         return pic16_regWithIdx(R1_IDX);
417     }
418
419 endOfWorld :
420     /* I said end of world but not quite end of world yet */
421     /* if this is a result then we can push it on the stack*/
422     if (result) {
423         (*aopp)->type = AOP_STK;    
424         return NULL;
425     }
426
427     /* other wise this is true end of the world */
428     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
429            "getFreePtr should never reach here");
430     exit(0);
431 }
432
433 /*-----------------------------------------------------------------*/
434 /* newAsmop - creates a new asmOp                                  */
435 /*-----------------------------------------------------------------*/
436 static asmop *newAsmop (short type)
437 {
438     asmop *aop;
439
440     aop = Safe_calloc(1,sizeof(asmop));
441     aop->type = type;
442     return aop;
443 }
444
445 static void genSetDPTR(int n)
446 {
447     if (!n)
448     {
449         pic16_emitcode(";", "Select standard DPTR");
450         pic16_emitcode("mov", "dps, #0x00");
451     }
452     else
453     {
454         pic16_emitcode(";", "Select alternate DPTR");
455         pic16_emitcode("mov", "dps, #0x01");
456     }
457 }
458
459 /*-----------------------------------------------------------------*/
460 /* resolveIfx - converts an iCode ifx into a form more useful for  */
461 /*              generating code                                    */
462 /*-----------------------------------------------------------------*/
463 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
464 {
465
466   DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
467
468   if(!resIfx) 
469     return;
470
471
472   resIfx->condition = 1;    /* assume that the ifx is true */
473   resIfx->generated = 0;    /* indicate that the ifx has not been used */
474
475   if(!ifx) {
476     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
477
478 #if 1
479     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
480                         __FUNCTION__,__LINE__,resIfx->lbl->key);
481 #endif
482
483   } else {
484     if(IC_TRUE(ifx)) {
485       resIfx->lbl = IC_TRUE(ifx);
486     } else {
487       resIfx->lbl = IC_FALSE(ifx);
488       resIfx->condition = 0;
489     }
490
491 #if 1
492     if(IC_TRUE(ifx)) 
493       DEBUGpic16_emitcode("; ***","ifx true is non-null");
494     if(IC_FALSE(ifx)) 
495       DEBUGpic16_emitcode("; ***","ifx false is non-null");
496 #endif
497   }
498
499   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
500
501 }
502 #if 0
503 /*-----------------------------------------------------------------*/
504 /* pointerCode - returns the code for a pointer type               */
505 /*-----------------------------------------------------------------*/
506 static int pointerCode (sym_link *etype)
507 {
508
509     return PTR_TYPE(SPEC_OCLS(etype));
510
511 }
512 #endif
513 /*-----------------------------------------------------------------*/
514 /* aopForSym - for a true symbol                                   */
515 /*-----------------------------------------------------------------*/
516 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
517 {
518     asmop *aop;
519     memmap *space= SPEC_OCLS(sym->etype);
520
521     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
522     /* if already has one */
523     if (sym->aop) {
524             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
525         return sym->aop;
526     }
527
528     /* if symbol was initially placed onStack then we must re-place it
529      * to direct memory, since pic16 does not have a specific stack */
530     if(sym->onStack) {
531         sym->onStack = 0;
532         SPEC_OCLS( sym->etype ) = data;
533         space = data;
534     }
535     
536
537 #if 1
538     /* assign depending on the storage class */
539     /* if it is on the stack or indirectly addressable */
540     /* space we need to assign either r0 or r1 to it   */    
541     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
542
543         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
544                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
545         
546         sym->aop = aop = newAsmop(0);
547         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
548         aop->size = getSize(sym->type);
549
550         /* now assign the address of the variable to 
551         the pointer register */
552         if (aop->type != AOP_STK) {
553
554             if (sym->onStack) {
555                     if ( _G.accInUse )
556                         pic16_emitcode("push","acc");
557
558                     pic16_emitcode("mov","a,_bp");
559                     pic16_emitcode("add","a,#0x%02x",
560                              ((sym->stack < 0) ?
561                               ((char)(sym->stack - _G.nRegsSaved )) :
562                               ((char)sym->stack)) & 0xff);
563                     pic16_emitcode("mov","%s,a",
564                              aop->aopu.aop_ptr->name);
565
566                     if ( _G.accInUse )
567                         pic16_emitcode("pop","acc");
568             } else
569                 pic16_emitcode("mov","%s,#%s",
570                          aop->aopu.aop_ptr->name,
571                          sym->rname);
572             aop->paged = space->paged;
573         } else
574             aop->aopu.aop_stk = sym->stack;
575         return aop;
576     }
577 #endif
578
579     if (sym->onStack && options.stack10bit)
580     {
581         /* It's on the 10 bit stack, which is located in
582          * far data space.
583          */
584          
585       //DEBUGpic16_emitcode(";","%d",__LINE__);
586
587         if ( _G.accInUse )
588                 pic16_emitcode("push","acc");
589
590         pic16_emitcode("mov","a,_bp");
591         pic16_emitcode("add","a,#0x%02x",
592                  ((sym->stack < 0) ?
593                    ((char)(sym->stack - _G.nRegsSaved )) :
594                    ((char)sym->stack)) & 0xff);
595         
596         genSetDPTR(1);
597         pic16_emitcode ("mov","dpx1,#0x40");
598         pic16_emitcode ("mov","dph1,#0x00");
599         pic16_emitcode ("mov","dpl1, a");
600         genSetDPTR(0);
601         
602         if ( _G.accInUse )
603             pic16_emitcode("pop","acc");
604             
605         sym->aop = aop = newAsmop(AOP_DPTR2);
606         aop->size = getSize(sym->type); 
607         return aop;
608     }
609
610     //DEBUGpic16_emitcode(";","%d",__LINE__);
611     /* if in bit space */
612     if (IN_BITSPACE(space)) {
613         sym->aop = aop = newAsmop (AOP_CRY);
614         aop->aopu.aop_dir = sym->rname ;
615         aop->size = getSize(sym->type);
616         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
617         return aop;
618     }
619     /* if it is in direct space */
620     if (IN_DIRSPACE(space)) {
621         sym->aop = aop = newAsmop (AOP_DIR);
622         aop->aopu.aop_dir = sym->rname ;
623         aop->size = getSize(sym->type);
624         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
625         pic16_allocDirReg( IC_LEFT(ic) );
626         return aop;
627     }
628
629 #if 0                                                                                           // patch 14
630     /* special case for a function */
631     if (IS_FUNC(sym->type)) {   
632         sym->aop = aop = newAsmop(AOP_IMMD);    
633         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
634         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
635         strcpy(aop->aopu.aop_immd,sym->rname);
636         aop->size = FPTRSIZE; 
637         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
638         return aop;
639     }
640 #endif                                                                                          // patch 14
641
642
643     /* only remaining is far space */
644     /* in which case DPTR gets the address */
645     sym->aop = aop = newAsmop(AOP_PCODE);
646
647 /* change the next if to 1 to revert to good old immediate code */
648         if(IN_CODESPACE(space)) {
649                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
650                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
651                 PCOI(aop->aopu.pcop)->index = 0;
652         } else {
653                 /* try to allocate via direct register */
654                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset); // Patch 8
655 //              aop->size = getSize( sym->type );
656         }
657
658         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
659                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
660
661 #if 0
662         if(!pic16_allocDirReg (IC_LEFT(ic)))
663                 return NULL;
664 #endif
665
666         if(IN_DIRSPACE( space ))
667                 aop->size = PTRSIZE;
668         else if(IN_CODESPACE( space ))
669                 aop->size = FPTRSIZE;
670         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
671         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
672         else {
673                 assert( 0 );
674         }
675
676     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
677
678     /* if it is in code space */
679     if (IN_CODESPACE(space))
680         aop->code = 1;
681
682     return aop;     
683 }
684
685 /*-----------------------------------------------------------------*/
686 /* aopForRemat - rematerialzes an object                           */
687 /*-----------------------------------------------------------------*/
688 static asmop *aopForRemat (operand *op) // x symbol *sym)
689 {
690   symbol *sym = OP_SYMBOL(op);
691   iCode *ic = NULL, *oldic;
692   asmop *aop = newAsmop(AOP_PCODE);
693   int val = 0;
694   int offset = 0;
695   int viaimmd=0;
696
697
698         ic = sym->rematiCode;
699
700         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
701         
702         if(IS_OP_POINTER(op)) {
703                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
704         }
705
706         for (;;) {
707                 oldic = ic;
708
709 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
710         
711                 if (ic->op == '+') {
712                         val += (int) operandLitValue(IC_RIGHT(ic));
713                 } else if (ic->op == '-') {
714                         val -= (int) operandLitValue(IC_RIGHT(ic));
715                 } else
716                         break;
717                 
718                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
719         }
720
721         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
722
723         if(!op->isaddr)viaimmd++; else viaimmd=0;
724                 
725 /* set the following if to 1 to revert to good old immediate code */
726         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
727                 || viaimmd) {
728
729                 DEBUGpic16_emitcode("%s:%d immediate", __FILE__, __LINE__);
730
731                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
732
733 #if 0
734                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
735 #else
736                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
737 #endif
738
739                 PCOI(aop->aopu.pcop)->index = val;
740         } else {
741                 DEBUGpic16_emitcode("%s:%d dir", __FILE__, __LINE__);
742
743                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname, getSize( OP_SYMBOL( IC_LEFT(ic))->type), val);
744 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
745         }
746
747
748         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
749                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
750 #if 0
751                 val, IS_PTR_CONST(operandType(op)));
752 #else
753                 val, IS_CODEPTR(operandType(op)));
754 #endif
755
756 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
757
758         pic16_allocDirReg (IC_LEFT(ic));
759
760         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
761                 aop->code = 1;
762
763   return aop;        
764 }
765
766 static int aopIdx (asmop *aop, int offset)
767 {
768   if(!aop)
769     return -1;
770
771   if(aop->type !=  AOP_REG)
772     return -2;
773         
774   return aop->aopu.aop_reg[offset]->rIdx;
775
776 }
777 /*-----------------------------------------------------------------*/
778 /* regsInCommon - two operands have some registers in common       */
779 /*-----------------------------------------------------------------*/
780 static bool regsInCommon (operand *op1, operand *op2)
781 {
782     symbol *sym1, *sym2;
783     int i;
784
785     /* if they have registers in common */
786     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
787         return FALSE ;
788
789     sym1 = OP_SYMBOL(op1);
790     sym2 = OP_SYMBOL(op2);
791
792     if (sym1->nRegs == 0 || sym2->nRegs == 0)
793         return FALSE ;
794
795     for (i = 0 ; i < sym1->nRegs ; i++) {
796         int j;
797         if (!sym1->regs[i])
798             continue ;
799
800         for (j = 0 ; j < sym2->nRegs ;j++ ) {
801             if (!sym2->regs[j])
802                 continue ;
803
804             if (sym2->regs[j] == sym1->regs[i])
805                 return TRUE ;
806         }
807     }
808
809     return FALSE ;
810 }
811
812 /*-----------------------------------------------------------------*/
813 /* operandsEqu - equivalent                                        */
814 /*-----------------------------------------------------------------*/
815 static bool operandsEqu ( operand *op1, operand *op2)
816 {
817     symbol *sym1, *sym2;
818
819     /* if they not symbols */
820     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
821         return FALSE;
822
823     sym1 = OP_SYMBOL(op1);
824     sym2 = OP_SYMBOL(op2);
825
826     /* if both are itemps & one is spilt
827        and the other is not then false */
828     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
829         sym1->isspilt != sym2->isspilt )
830         return FALSE ;
831
832     /* if they are the same */
833     if (sym1 == sym2)
834         return TRUE ;
835
836     if (strcmp(sym1->rname,sym2->rname) == 0)
837         return TRUE;
838
839
840     /* if left is a tmp & right is not */
841     if (IS_ITEMP(op1)  && 
842         !IS_ITEMP(op2) &&
843         sym1->isspilt  &&
844         (sym1->usl.spillLoc == sym2))
845         return TRUE;
846
847     if (IS_ITEMP(op2)  && 
848         !IS_ITEMP(op1) &&
849         sym2->isspilt  &&
850         sym1->level > 0 &&
851         (sym2->usl.spillLoc == sym1))
852         return TRUE ;
853
854     return FALSE ;
855 }
856
857 /*-----------------------------------------------------------------*/
858 /* pic16_sameRegs - two asmops have the same registers                   */
859 /*-----------------------------------------------------------------*/
860 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
861 {
862     int i;
863
864     if (aop1 == aop2)
865         return TRUE ;
866
867     if (aop1->type != AOP_REG ||
868         aop2->type != AOP_REG )
869         return FALSE ;
870
871     if (aop1->size != aop2->size )
872         return FALSE ;
873
874     for (i = 0 ; i < aop1->size ; i++ )
875         if (aop1->aopu.aop_reg[i] !=
876             aop2->aopu.aop_reg[i] )
877             return FALSE ;
878
879     return TRUE ;
880 }
881
882 /*-----------------------------------------------------------------*/
883 /* pic16_aopOp - allocates an asmop for an operand  :                    */
884 /*-----------------------------------------------------------------*/
885 void pic16_aopOp (operand *op, iCode *ic, bool result)
886 {
887     asmop *aop;
888     symbol *sym;
889     int i;
890
891     if (!op)
892         return ;
893
894 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
895
896     /* if this a literal */
897     if (IS_OP_LITERAL(op)) {
898         op->aop = aop = newAsmop(AOP_LIT);
899         aop->aopu.aop_lit = op->operand.valOperand;
900         aop->size = getSize(operandType(op));
901         return;
902     }
903
904     {
905       sym_link *type = operandType(op);
906 #if 0
907       if(IS_PTR_CONST(type))
908 #else
909       if(IS_CODEPTR(type))
910 #endif
911         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
912     }
913
914     /* if already has a asmop then continue */
915     if (op->aop)
916         return ;
917
918     /* if the underlying symbol has a aop */
919     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
920       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
921         op->aop = OP_SYMBOL(op)->aop;
922         return;
923     }
924
925     /* if this is a true symbol */
926     if (IS_TRUE_SYMOP(op)) {    
927         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
928       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
929       return ;
930     }
931
932     /* this is a temporary : this has
933     only four choices :
934     a) register
935     b) spillocation
936     c) rematerialize 
937     d) conditional   
938     e) can be a return use only */
939
940     sym = OP_SYMBOL(op);
941
942         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
943     /* if the type is a conditional */
944     if (sym->regType == REG_CND) {
945         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
946         aop->size = 0;
947         return;
948     }
949
950     /* if it is spilt then two situations
951     a) is rematerialize 
952     b) has a spill location */
953     if (sym->isspilt || sym->nRegs == 0) {
954
955       DEBUGpic16_emitcode(";","%d",__LINE__);
956         /* rematerialize it NOW */
957         if (sym->remat) {
958
959             sym->aop = op->aop = aop =
960                                       aopForRemat (op);
961             aop->size = getSize(sym->type);
962             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
963             return;
964         }
965
966 #if 1
967         if (sym->accuse) {
968             int i;
969             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
970             aop->size = getSize(sym->type);
971             for ( i = 0 ; i < 1 ; i++ ) {
972                 aop->aopu.aop_str[i] = accUse[i];
973 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
974             }
975             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
976             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
977             return;  
978         }
979 #endif
980
981 #if 1
982         if (sym->ruonly ) {
983           /*
984           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
985           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
986           //pic16_allocDirReg (IC_LEFT(ic));
987           aop->size = getSize(sym->type);
988           */
989
990           unsigned i;
991
992           aop = op->aop = sym->aop = newAsmop(AOP_STR);
993           aop->size = getSize(sym->type);
994           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
995             aop->aopu.aop_str[i] = fReturn[i];
996
997           DEBUGpic16_emitcode(";","%d",__LINE__);
998           return;
999         }
1000 #endif
1001         /* else spill location  */
1002         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1003             /* force a new aop if sizes differ */
1004             sym->usl.spillLoc->aop = NULL;
1005         }
1006         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1007                             __FUNCTION__,__LINE__,
1008                             sym->usl.spillLoc->rname,
1009                             sym->rname, sym->usl.spillLoc->offset);
1010
1011         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1012         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1013         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1014                                           getSize(sym->type), 
1015                                           sym->usl.spillLoc->offset);
1016         aop->size = getSize(sym->type);
1017
1018         return;
1019     }
1020
1021     {
1022       sym_link *type = operandType(op);
1023 #if 0
1024       if(IS_PTR_CONST(type)) 
1025 #else
1026       if(IS_CODEPTR(type)) 
1027 #endif
1028         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1029     }
1030
1031     /* must be in a register */
1032     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1033     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1034     aop->size = sym->nRegs;
1035     for ( i = 0 ; i < sym->nRegs ;i++)
1036         aop->aopu.aop_reg[i] = sym->regs[i];
1037 }
1038
1039 /*-----------------------------------------------------------------*/
1040 /* pic16_freeAsmop - free up the asmop given to an operand               */
1041 /*----------------------------------------------------------------*/
1042 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1043 {   
1044     asmop *aop ;
1045
1046     if (!op)
1047         aop = aaop;
1048     else 
1049         aop = op->aop;
1050
1051     if (!aop)
1052         return ;
1053
1054     if (aop->freed)
1055         goto dealloc; 
1056
1057     aop->freed = 1;
1058
1059     /* depending on the asmop type only three cases need work AOP_RO
1060        , AOP_R1 && AOP_STK */
1061 #if 0
1062     switch (aop->type) {
1063         case AOP_R0 :
1064             if (_G.r0Pushed ) {
1065                 if (pop) {
1066                     pic16_emitcode ("pop","ar0");     
1067                     _G.r0Pushed--;
1068                 }
1069             }
1070             bitVectUnSetBit(ic->rUsed,R0_IDX);
1071             break;
1072
1073         case AOP_R1 :
1074             if (_G.r1Pushed ) {
1075                 if (pop) {
1076                     pic16_emitcode ("pop","ar1");
1077                     _G.r1Pushed--;
1078                 }
1079             }
1080             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1081             break;
1082
1083         case AOP_STK :
1084         {
1085             int sz = aop->size;    
1086             int stk = aop->aopu.aop_stk + aop->size;
1087             bitVectUnSetBit(ic->rUsed,R0_IDX);
1088             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1089
1090             getFreePtr(ic,&aop,FALSE);
1091             
1092             if (options.stack10bit)
1093             {
1094                 /* I'm not sure what to do here yet... */
1095                 /* #STUB */
1096                 fprintf(stderr, 
1097                         "*** Warning: probably generating bad code for "
1098                         "10 bit stack mode.\n");
1099             }
1100             
1101             if (stk) {
1102                 pic16_emitcode ("mov","a,_bp");
1103                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1104                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1105             } else {
1106                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1107             }
1108
1109             while (sz--) {
1110                 pic16_emitcode("pop","acc");
1111                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1112                 if (!sz) break;
1113                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1114             }
1115             op->aop = aop;
1116             pic16_freeAsmop(op,NULL,ic,TRUE);
1117             if (_G.r0Pushed) {
1118                 pic16_emitcode("pop","ar0");
1119                 _G.r0Pushed--;
1120             }
1121
1122             if (_G.r1Pushed) {
1123                 pic16_emitcode("pop","ar1");
1124                 _G.r1Pushed--;
1125             }       
1126         }
1127     }
1128 #endif
1129
1130 dealloc:
1131     /* all other cases just dealloc */
1132     if (op ) {
1133         op->aop = NULL;
1134         if (IS_SYMOP(op)) {
1135             OP_SYMBOL(op)->aop = NULL;    
1136             /* if the symbol has a spill */
1137             if (SPIL_LOC(op))
1138                 SPIL_LOC(op)->aop = NULL;
1139         }
1140     }
1141 }
1142
1143 /*-----------------------------------------------------------------*/
1144 /* pic16_aopGet - for fetching value of the aop                          */
1145 /*-----------------------------------------------------------------*/
1146 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1147 {
1148     char *s = buffer ;
1149     char *rs;
1150
1151     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1152
1153     /* offset is greater than size then zero */
1154     if (offset > (aop->size - 1) &&
1155         aop->type != AOP_LIT)
1156         return zero;
1157
1158     /* depending on type */
1159     switch (aop->type) {
1160         
1161     case AOP_R0:
1162     case AOP_R1:
1163         DEBUGpic16_emitcode(";","%d",__LINE__);
1164         /* if we need to increment it */       
1165         while (offset > aop->coff) {        
1166             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1167             aop->coff++;
1168         }
1169         
1170         while (offset < aop->coff) {
1171             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1172             aop->coff--;
1173         }
1174         
1175         aop->coff = offset ;
1176         if (aop->paged) {
1177             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1178             return (dname ? "acc" : "a");
1179         }       
1180         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1181         rs = Safe_calloc(1,strlen(s)+1);
1182         strcpy(rs,s);   
1183         return rs;
1184         
1185     case AOP_DPTR:
1186     case AOP_DPTR2:
1187         DEBUGpic16_emitcode(";","%d",__LINE__);
1188     if (aop->type == AOP_DPTR2)
1189     {
1190         genSetDPTR(1);
1191     }
1192     
1193         while (offset > aop->coff) {
1194             pic16_emitcode ("inc","dptr");
1195             aop->coff++;
1196         }
1197         
1198         while (offset < aop->coff) {        
1199             pic16_emitcode("lcall","__decdptr");
1200             aop->coff--;
1201         }
1202         
1203         aop->coff = offset;
1204         if (aop->code) {
1205             pic16_emitcode("clr","a");
1206             pic16_emitcode("movc","a,@a+dptr");
1207         }
1208     else {
1209             pic16_emitcode("movx","a,@dptr");
1210     }
1211             
1212     if (aop->type == AOP_DPTR2)
1213     {
1214         genSetDPTR(0);
1215     }
1216             
1217     return (dname ? "acc" : "a");
1218         
1219         
1220     case AOP_IMMD:
1221         if (bit16) 
1222             sprintf (s,"%s",aop->aopu.aop_immd);
1223         else
1224             if (offset) 
1225                 sprintf(s,"(%s >> %d)",
1226                         aop->aopu.aop_immd,
1227                         offset*8);
1228             else
1229                 sprintf(s,"%s",
1230                         aop->aopu.aop_immd);
1231         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1232         rs = Safe_calloc(1,strlen(s)+1);
1233         strcpy(rs,s);   
1234         return rs;
1235         
1236     case AOP_DIR:
1237       if (offset) {
1238         sprintf(s,"(%s + %d)",
1239                 aop->aopu.aop_dir,
1240                 offset);
1241         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1242       } else
1243             sprintf(s,"%s",aop->aopu.aop_dir);
1244         rs = Safe_calloc(1,strlen(s)+1);
1245         strcpy(rs,s);   
1246         return rs;
1247         
1248     case AOP_REG:
1249       //if (dname) 
1250       //    return aop->aopu.aop_reg[offset]->dname;
1251       //else
1252             return aop->aopu.aop_reg[offset]->name;
1253         
1254     case AOP_CRY:
1255       //pic16_emitcode(";","%d",__LINE__);
1256       return aop->aopu.aop_dir;
1257         
1258     case AOP_ACC:
1259         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1260 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1261 //        assert( 0 );
1262         return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1263
1264     case AOP_LIT:
1265         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1266         rs = Safe_calloc(1,strlen(s)+1);
1267         strcpy(rs,s);   
1268         return rs;
1269         
1270     case AOP_STR:
1271         aop->coff = offset ;
1272         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1273             dname)
1274             return "acc";
1275         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1276         
1277         return aop->aopu.aop_str[offset];
1278         
1279     case AOP_PCODE:
1280       {
1281         pCodeOp *pcop = aop->aopu.pcop;
1282         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1283         if(pcop->name) {
1284           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1285           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1286           sprintf(s,"%s", pcop->name);
1287         } else
1288           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1289
1290       }
1291       rs = Safe_calloc(1,strlen(s)+1);
1292       strcpy(rs,s);   
1293       return rs;
1294
1295     }
1296
1297     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1298            "aopget got unsupported aop->type");
1299     exit(0);
1300 }
1301
1302
1303 /*-----------------------------------------------------------------*/
1304 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1305 /*-----------------------------------------------------------------*/
1306 pCodeOp *pic16_popGetTempReg(void)
1307 {
1308   pCodeOp *pcop;
1309   symbol *cfunc;
1310
1311 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1312
1313         cfunc = currFunc;
1314         currFunc = NULL;
1315
1316         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1317         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1318                 PCOR(pcop)->r->wasUsed=1;
1319                 PCOR(pcop)->r->isFree=0;
1320
1321                 /* push value on stack */
1322                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1323         }
1324
1325         currFunc = cfunc;
1326
1327   return pcop;
1328 }
1329
1330 /*-----------------------------------------------------------------*/
1331 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1332 /*-----------------------------------------------------------------*/
1333 void pic16_popReleaseTempReg(pCodeOp *pcop)
1334 {
1335         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1336
1337         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1338                 PCOR(pcop)->r->isFree = 1;
1339                 
1340                 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1341         }
1342 }
1343 /*-----------------------------------------------------------------*/
1344 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1345 /*-----------------------------------------------------------------*/
1346 pCodeOp *pic16_popGetLabel(unsigned int key)
1347 {
1348
1349   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1350
1351   if(key>max_key)
1352     max_key = key;
1353
1354   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1355 }
1356
1357 /*-----------------------------------------------------------------*/
1358 /* pic16_popCopyReg - copy a pcode operator                              */
1359 /*-----------------------------------------------------------------*/
1360 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1361 {
1362   pCodeOpReg *pcor;
1363
1364   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1365   pcor->pcop.type = pc->pcop.type;
1366   if(pc->pcop.name) {
1367     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1368       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1369   } else
1370     pcor->pcop.name = NULL;
1371
1372   pcor->r = pc->r;
1373   pcor->rIdx = pc->rIdx;
1374   pcor->r->wasUsed=1;
1375
1376 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1377
1378   return PCOP(pcor);
1379 }
1380
1381 /*-----------------------------------------------------------------*/
1382 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1383 /*-----------------------------------------------------------------*/
1384 pCodeOp *pic16_popGetLit(unsigned int lit)
1385 {
1386   return pic16_newpCodeOpLit(lit);
1387 }
1388
1389 /*-----------------------------------------------------------------*/
1390 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1391 /*-----------------------------------------------------------------*/
1392 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1393 {
1394   return pic16_newpCodeOpLit2(lit, arg2);
1395 }
1396
1397
1398 /*-----------------------------------------------------------------*/
1399 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1400 /*-----------------------------------------------------------------*/
1401 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1402 {
1403   return pic16_newpCodeOpImmd(name, offset,index, 0);
1404 }
1405
1406
1407 /*-----------------------------------------------------------------*/
1408 /* pic16_popGet - asm operator to pcode operator conversion              */
1409 /*-----------------------------------------------------------------*/
1410 pCodeOp *pic16_popGetWithString(char *str)
1411 {
1412   pCodeOp *pcop;
1413
1414
1415   if(!str) {
1416     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1417     exit (1);
1418   }
1419
1420   pcop = pic16_newpCodeOp(str,PO_STR);
1421
1422   return pcop;
1423 }
1424
1425 /*-----------------------------------------------------------------*/
1426 /* pic16_popRegFromString -                                        */
1427 /*-----------------------------------------------------------------*/
1428 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1429 {
1430
1431   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1432   pcop->type = PO_DIR;
1433
1434   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1435   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1436
1437   if(!str)
1438     str = "BAD_STRING";
1439
1440   pcop->name = Safe_calloc(1,strlen(str)+1);
1441   strcpy(pcop->name,str);
1442
1443   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1444
1445   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1446   if(PCOR(pcop)->r == NULL) {
1447 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1448 //              __FUNCTION__, __LINE__, str, size, offset);
1449     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1450
1451         //fprintf(stderr, "allocating new register -> %s\n", str);
1452
1453 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1454   } else {
1455 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1456   }
1457   PCOR(pcop)->instance = offset;
1458
1459   return pcop;
1460 }
1461
1462 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1463 {
1464   pCodeOp *pcop;
1465
1466 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1467
1468         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1469         PCOR(pcop)->rIdx = rIdx;
1470         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1471         PCOR(pcop)->r->isFree = 0;
1472         PCOR(pcop)->r->wasUsed = 1;
1473
1474         pcop->type = PCOR(pcop)->r->pc_type;
1475
1476   return pcop;
1477 }
1478
1479 /*---------------------------------------------------------------------------------*/
1480 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1481 /*                 VR 030601                                                       */
1482 /*---------------------------------------------------------------------------------*/
1483 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1484 {
1485   pCodeOpReg2 *pcop2;
1486   pCodeOp *temp;
1487   
1488         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1489
1490         /* comment the following check, so errors to throw up */
1491 //      if(!pcop2)return NULL;
1492
1493         temp = pic16_popGet(aop_dst, offset);
1494         pcop2->pcop2 = temp;
1495         
1496   return PCOP(pcop2);
1497 }
1498
1499
1500
1501 /*--------------------------------------------------------------------------------.-*/
1502 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1503 /*                  VR 030601 , adapted by Hans Dorn                                */
1504 /*--------------------------------------------------------------------------------.-*/
1505 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1506 {
1507   pCodeOpReg2 *pcop2;
1508  
1509         pcop2 = (pCodeOpReg2 *)src;
1510         pcop2->pcop2 = dst;
1511         
1512         return PCOP(pcop2);
1513 }
1514
1515
1516
1517 /*---------------------------------------------------------------------------------*/
1518 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1519 /*                     movff instruction                                           */
1520 /*---------------------------------------------------------------------------------*/
1521 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1522 {
1523   pCodeOpReg2 *pcop2;
1524
1525         if(!noalloc) {
1526                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1527                 pcop2->pcop2 = pic16_popCopyReg(dst);
1528         } else {
1529                 /* the pCodeOp may be already allocated */
1530                 pcop2 = (pCodeOpReg2 *)(src);
1531                 pcop2->pcop2 = (pCodeOp *)(dst);
1532         }
1533
1534   return PCOP(pcop2);
1535 }
1536
1537
1538 /*-----------------------------------------------------------------*/
1539 /* pic16_popGet - asm operator to pcode operator conversion              */
1540 /*-----------------------------------------------------------------*/
1541 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1542 {
1543   //char *s = buffer ;
1544   char *rs;
1545   pCodeOp *pcop;
1546
1547     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1548     /* offset is greater than
1549     size then zero */
1550
1551 //    if (offset > (aop->size - 1) &&
1552 //        aop->type != AOP_LIT)
1553 //      return NULL;  //zero;
1554
1555     /* depending on type */
1556     switch (aop->type) {
1557         
1558     case AOP_R0:
1559     case AOP_R1:
1560     case AOP_DPTR:
1561     case AOP_DPTR2:
1562         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1563         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1564         assert( 0 );
1565         return NULL;
1566
1567
1568
1569     case AOP_IMMD:
1570       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1571       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1572
1573     case AOP_ACC:
1574       {
1575         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1576
1577         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1578
1579         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1580         
1581         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1582         PCOR(pcop)->rIdx = rIdx;
1583         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1584         PCOR(pcop)->r->wasUsed=1;
1585         PCOR(pcop)->r->isFree=0;
1586
1587         PCOR(pcop)->instance = offset;
1588         pcop->type = PCOR(pcop)->r->pc_type;
1589 //      rs = aop->aopu.aop_reg[offset]->name;
1590 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1591         return pcop;
1592
1593
1594 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1595 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1596
1597 //      assert( 0 );
1598       }
1599         
1600     case AOP_DIR:
1601       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1602       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1603         
1604     case AOP_REG:
1605       {
1606         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1607
1608         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1609         
1610         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1611         PCOR(pcop)->rIdx = rIdx;
1612         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1613         PCOR(pcop)->r->wasUsed=1;
1614         PCOR(pcop)->r->isFree=0;
1615
1616         PCOR(pcop)->instance = offset;
1617         pcop->type = PCOR(pcop)->r->pc_type;
1618         rs = aop->aopu.aop_reg[offset]->name;
1619         DEBUGpic16_emitcode(";","%d regiser idx = %d name = %s",__LINE__,rIdx,rs);
1620         return pcop;
1621       }
1622
1623     case AOP_CRY:
1624         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1625
1626       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1627       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1628       //if(PCOR(pcop)->r == NULL)
1629       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1630       return pcop;
1631         
1632     case AOP_LIT:
1633         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1634       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1635
1636     case AOP_STR:
1637       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1638       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1639
1640       /*
1641       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1642       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1643       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1644       pcop->type = PCOR(pcop)->r->pc_type;
1645       pcop->name = PCOR(pcop)->r->name;
1646
1647       return pcop;
1648       */
1649
1650     case AOP_PCODE:
1651       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1652                           __LINE__, 
1653                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1654       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1655 #if 1
1656         switch( aop->aopu.pcop->type ) {
1657                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1658                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1659                 default:
1660                         assert( 0 );    /* should never reach here */;
1661         }
1662 #else
1663       PCOI(pcop)->offset = offset;
1664 #endif
1665       return pcop;
1666     }
1667
1668     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1669            "pic16_popGet got unsupported aop->type");
1670     exit(0);
1671 }
1672 /*-----------------------------------------------------------------*/
1673 /* pic16_aopPut - puts a string for a aop                                */
1674 /*-----------------------------------------------------------------*/
1675 void pic16_aopPut (asmop *aop, char *s, int offset)
1676 {
1677     char *d = buffer ;
1678     symbol *lbl ;
1679
1680     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1681
1682     if (aop->size && offset > ( aop->size - 1)) {
1683         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1684                "pic16_aopPut got offset > aop->size");
1685         exit(0);
1686     }
1687
1688     /* will assign value to value */
1689     /* depending on where it is ofcourse */
1690     switch (aop->type) {
1691     case AOP_DIR:
1692       if (offset) {
1693         sprintf(d,"(%s + %d)",
1694                 aop->aopu.aop_dir,offset);
1695         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1696
1697       } else
1698             sprintf(d,"%s",aop->aopu.aop_dir);
1699         
1700         if (strcmp(d,s)) {
1701           DEBUGpic16_emitcode(";","%d",__LINE__);
1702           if(strcmp(s,"W"))
1703             pic16_emitcode("movf","%s,w",s);
1704           pic16_emitcode("movwf","%s",d);
1705
1706           if(strcmp(s,"W")) {
1707             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1708             if(offset >= aop->size) {
1709               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1710               break;
1711             } else
1712               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1713           }
1714
1715           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1716
1717
1718         }
1719         break;
1720         
1721     case AOP_REG:
1722       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1723         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1724           /*
1725             if (*s == '@'           ||
1726                 strcmp(s,"r0") == 0 ||
1727                 strcmp(s,"r1") == 0 ||
1728                 strcmp(s,"r2") == 0 ||
1729                 strcmp(s,"r3") == 0 ||
1730                 strcmp(s,"r4") == 0 ||
1731                 strcmp(s,"r5") == 0 ||
1732                 strcmp(s,"r6") == 0 || 
1733                 strcmp(s,"r7") == 0 )
1734                 pic16_emitcode("mov","%s,%s  ; %d",
1735                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1736             else
1737           */
1738
1739           if(strcmp(s,"W")==0 )
1740             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1741
1742           pic16_emitcode("movwf","%s",
1743                    aop->aopu.aop_reg[offset]->name);
1744
1745           if(strcmp(s,zero)==0) {
1746             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1747
1748           } else if(strcmp(s,"W")==0) {
1749             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1750             pcop->type = PO_GPR_REGISTER;
1751
1752             PCOR(pcop)->rIdx = -1;
1753             PCOR(pcop)->r = NULL;
1754
1755             DEBUGpic16_emitcode(";","%d",__LINE__);
1756             pcop->name = Safe_strdup(s);
1757             pic16_emitpcode(POC_MOVFW,pcop);
1758             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1759           } else if(strcmp(s,one)==0) {
1760             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1761             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1762           } else {
1763             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1764           }
1765         }
1766         break;
1767         
1768     case AOP_DPTR:
1769     case AOP_DPTR2:
1770     
1771     if (aop->type == AOP_DPTR2)
1772     {
1773         genSetDPTR(1);
1774     }
1775     
1776         if (aop->code) {
1777             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1778                    "pic16_aopPut writting to code space");
1779             exit(0);
1780         }
1781         
1782         while (offset > aop->coff) {
1783             aop->coff++;
1784             pic16_emitcode ("inc","dptr");
1785         }
1786         
1787         while (offset < aop->coff) {
1788             aop->coff-- ;
1789             pic16_emitcode("lcall","__decdptr");
1790         }
1791         
1792         aop->coff = offset;
1793         
1794         /* if not in accumulater */
1795         MOVA(s);        
1796         
1797         pic16_emitcode ("movx","@dptr,a");
1798         
1799     if (aop->type == AOP_DPTR2)
1800     {
1801         genSetDPTR(0);
1802     }
1803         break;
1804         
1805     case AOP_R0:
1806     case AOP_R1:
1807         while (offset > aop->coff) {
1808             aop->coff++;
1809             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1810         }
1811         while (offset < aop->coff) {
1812             aop->coff-- ;
1813             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1814         }
1815         aop->coff = offset;
1816         
1817         if (aop->paged) {
1818             MOVA(s);           
1819             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1820             
1821         } else
1822             if (*s == '@') {
1823                 MOVA(s);
1824                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1825             } else
1826                 if (strcmp(s,"r0") == 0 ||
1827                     strcmp(s,"r1") == 0 ||
1828                     strcmp(s,"r2") == 0 ||
1829                     strcmp(s,"r3") == 0 ||
1830                     strcmp(s,"r4") == 0 ||
1831                     strcmp(s,"r5") == 0 ||
1832                     strcmp(s,"r6") == 0 || 
1833                     strcmp(s,"r7") == 0 ) {
1834                     char buffer[10];
1835                     sprintf(buffer,"a%s",s);
1836                     pic16_emitcode("mov","@%s,%s",
1837                              aop->aopu.aop_ptr->name,buffer);
1838                 } else
1839                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1840         
1841         break;
1842         
1843     case AOP_STK:
1844         if (strcmp(s,"a") == 0)
1845             pic16_emitcode("push","acc");
1846         else
1847             pic16_emitcode("push","%s",s);
1848         
1849         break;
1850         
1851     case AOP_CRY:
1852         /* if bit variable */
1853         if (!aop->aopu.aop_dir) {
1854             pic16_emitcode("clr","a");
1855             pic16_emitcode("rlc","a");
1856         } else {
1857             if (s == zero) 
1858                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1859             else
1860                 if (s == one)
1861                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1862                 else
1863                     if (!strcmp(s,"c"))
1864                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1865                     else {
1866                         lbl = newiTempLabel(NULL);
1867                         
1868                         if (strcmp(s,"a")) {
1869                             MOVA(s);
1870                         }
1871                         pic16_emitcode("clr","c");
1872                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1873                         pic16_emitcode("cpl","c");
1874                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1875                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1876                     }
1877         }
1878         break;
1879         
1880     case AOP_STR:
1881         aop->coff = offset;
1882         if (strcmp(aop->aopu.aop_str[offset],s))
1883             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1884         break;
1885         
1886     case AOP_ACC:
1887         aop->coff = offset;
1888         if (!offset && (strcmp(s,"acc") == 0))
1889             break;
1890         
1891         if (strcmp(aop->aopu.aop_str[offset],s))
1892             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1893         break;
1894
1895     default :
1896         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1897                "pic16_aopPut got unsupported aop->type");
1898         exit(0);    
1899     }    
1900
1901 }
1902
1903 /*-----------------------------------------------------------------*/
1904 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1905 /*-----------------------------------------------------------------*/
1906 static void mov2w (asmop *aop, int offset)
1907 {
1908
1909   if(!aop)
1910     return;
1911
1912   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1913
1914   if ( aop->type == AOP_PCODE ||
1915        aop->type == AOP_LIT )
1916     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1917   else
1918     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1919
1920 }
1921
1922
1923 /* push pcop into stack */
1924 void pic16_pushpCodeOp(pCodeOp *pcop)
1925 {
1926 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1927         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1928 }
1929
1930 /* pop pcop from stack */
1931 void pic16_poppCodeOp(pCodeOp *pcop)
1932 {
1933         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1934 }
1935
1936
1937 /*-----------------------------------------------------------------*/
1938 /* pushw - pushes wreg to stack                                    */
1939 /*-----------------------------------------------------------------*/
1940 void pushw(void)
1941 {
1942         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1943         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1944 }
1945
1946                 
1947 /*-----------------------------------------------------------------*/
1948 /* pushaop - pushes aop to stack                                   */
1949 /*-----------------------------------------------------------------*/
1950 void pushaop(asmop *aop, int offset)
1951 {
1952         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1953         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1954 }
1955
1956 /*-----------------------------------------------------------------*/
1957 /* popaop - pops aop from stack                                    */
1958 /*-----------------------------------------------------------------*/
1959 void popaop(asmop *aop, int offset)
1960 {
1961         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1962         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1963 }
1964
1965 void popaopidx(asmop *aop, int offset, int index)
1966 {
1967   int ofs=1;
1968
1969         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1970
1971         if(STACK_MODEL_LARGE)ofs++;
1972
1973         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1974         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1975 }
1976
1977 /*-----------------------------------------------------------------*/
1978 /* reAdjustPreg - points a register back to where it should        */
1979 /*-----------------------------------------------------------------*/
1980 static void reAdjustPreg (asmop *aop)
1981 {
1982     int size ;
1983
1984     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1985     aop->coff = 0;
1986     if ((size = aop->size) <= 1)
1987         return ;
1988     size-- ;
1989     switch (aop->type) {
1990         case AOP_R0 :
1991         case AOP_R1 :
1992             while (size--)
1993                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1994             break;          
1995         case AOP_DPTR :
1996         case AOP_DPTR2:
1997             if (aop->type == AOP_DPTR2)
1998             {
1999                 genSetDPTR(1);
2000             } 
2001             while (size--)
2002             {
2003                 pic16_emitcode("lcall","__decdptr");
2004             }
2005                 
2006             if (aop->type == AOP_DPTR2)
2007             {
2008                 genSetDPTR(0);
2009             }                
2010             break;  
2011
2012     }   
2013
2014 }
2015
2016
2017 #if 0
2018 /*-----------------------------------------------------------------*/
2019 /* opIsGptr: returns non-zero if the passed operand is             */   
2020 /* a generic pointer type.                                         */
2021 /*-----------------------------------------------------------------*/ 
2022 static int opIsGptr(operand *op)
2023 {
2024     sym_link *type = operandType(op);
2025     
2026     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2027     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2028     {
2029         return 1;
2030     }
2031     return 0;        
2032 }
2033 #endif
2034
2035 /*-----------------------------------------------------------------*/
2036 /* pic16_getDataSize - get the operand data size                         */
2037 /*-----------------------------------------------------------------*/
2038 int pic16_getDataSize(operand *op)
2039 {
2040     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2041
2042
2043     return AOP_SIZE(op);
2044
2045     // tsd- in the pic port, the genptr size is 1, so this code here
2046     // fails. ( in the 8051 port, the size was 4).
2047 #if 0
2048     int size;
2049     size = AOP_SIZE(op);
2050     if (size == GPTRSIZE)
2051     {
2052         sym_link *type = operandType(op);
2053         if (IS_GENPTR(type))
2054         {
2055             /* generic pointer; arithmetic operations
2056              * should ignore the high byte (pointer type).
2057              */
2058             size--;
2059     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2060         }
2061     }
2062     return size;
2063 #endif
2064 }
2065
2066 /*-----------------------------------------------------------------*/
2067 /* pic16_outAcc - output Acc                                             */
2068 /*-----------------------------------------------------------------*/
2069 void pic16_outAcc(operand *result)
2070 {
2071   int size,offset;
2072   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2073   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2074
2075
2076   size = pic16_getDataSize(result);
2077   if(size){
2078     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2079     size--;
2080     offset = 1;
2081     /* unsigned or positive */
2082     while(size--)
2083       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2084   }
2085
2086 }
2087
2088 /*-----------------------------------------------------------------*/
2089 /* pic16_outBitC - output a bit C                                  */
2090 /*                 Move to result the value of Carry flag -- VR    */
2091 /*-----------------------------------------------------------------*/
2092 void pic16_outBitC(operand *result)
2093 {
2094   int i;
2095
2096     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2097     /* if the result is bit */
2098     if (AOP_TYPE(result) == AOP_CRY) {
2099         fprintf(stderr, "%s:%d: pic16 port warning: unsupported case\n", __FILE__, __LINE__);
2100         pic16_aopPut(AOP(result),"c",0);
2101     } else {
2102
2103         i = AOP_SIZE(result);
2104         while(i--) {
2105                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
2106         }
2107         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result), 0));
2108         
2109 /*
2110         pic16_emitcode("clr","a  ; %d", __LINE__);
2111         pic16_emitcode("rlc","a");
2112         pic16_outAcc(result);
2113 */
2114     }
2115 }
2116
2117 /*-----------------------------------------------------------------*/
2118 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2119 /*-----------------------------------------------------------------*/
2120 void pic16_toBoolean(operand *oper)
2121 {
2122     int size = AOP_SIZE(oper) - 1;
2123     int offset = 1;
2124
2125     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2126
2127     if ( AOP_TYPE(oper) != AOP_ACC) {
2128       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2129     }
2130     while (size--) {
2131       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2132     }
2133 }
2134
2135
2136 #if !defined(GEN_Not)
2137 /*-----------------------------------------------------------------*/
2138 /* genNot - generate code for ! operation                          */
2139 /*-----------------------------------------------------------------*/
2140 static void pic16_genNot (iCode *ic)
2141 {
2142   symbol *tlbl;
2143   int size;
2144
2145   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2146   /* assign asmOps to operand & result */
2147   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2148   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2149
2150   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2151   /* if in bit space then a special case */
2152   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2153     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2154       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2155       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2156     } else {
2157       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2158       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2159       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2160     }
2161     goto release;
2162   }
2163
2164   size = AOP_SIZE(IC_LEFT(ic));
2165   if(size == 1) {
2166     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2167     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2168     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2169     goto release;
2170   }
2171   pic16_toBoolean(IC_LEFT(ic));
2172
2173   tlbl = newiTempLabel(NULL);
2174   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2175   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2176   pic16_outBitC(IC_RESULT(ic));
2177
2178  release:    
2179   /* release the aops */
2180   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2181   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2182 }
2183 #endif
2184
2185
2186 #if !defined(GEN_Cpl)
2187 /*-----------------------------------------------------------------*/
2188 /* genCpl - generate code for complement                           */
2189 /*-----------------------------------------------------------------*/
2190 static void pic16_genCpl (iCode *ic)
2191 {
2192     int offset = 0;
2193     int size ;
2194
2195
2196     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2197     /* assign asmOps to operand & result */
2198     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2199     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2200
2201     /* if both are in bit space then 
2202     a special case */
2203     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2204         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2205
2206         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2207         pic16_emitcode("cpl","c"); 
2208         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2209         goto release; 
2210     } 
2211
2212     size = AOP_SIZE(IC_RESULT(ic));
2213     while (size--) {
2214 /*
2215         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2216         MOVA(l);       
2217         pic16_emitcode("cpl","a");
2218         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2219 */
2220         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2221               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2222         } else {
2223                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2224                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2225         }
2226         offset++;
2227
2228     }
2229
2230
2231 release:
2232     /* release the aops */
2233     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2234     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2235 }
2236 #endif
2237
2238 /*-----------------------------------------------------------------*/
2239 /* genUminusFloat - unary minus for floating points                */
2240 /*-----------------------------------------------------------------*/
2241 static void genUminusFloat(operand *op,operand *result)
2242 {
2243     int size ,offset =0 ;
2244     char *l;
2245
2246     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2247     /* for this we just need to flip the 
2248     first it then copy the rest in place */
2249     size = AOP_SIZE(op) - 1;
2250     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2251
2252     MOVA(l);    
2253
2254     pic16_emitcode("cpl","acc.7");
2255     pic16_aopPut(AOP(result),"a",3);    
2256
2257     while(size--) {
2258         pic16_aopPut(AOP(result),
2259                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2260                offset);
2261         offset++;
2262     }          
2263 }
2264
2265 /*-----------------------------------------------------------------*/
2266 /* genUminus - unary minus code generation                         */
2267 /*-----------------------------------------------------------------*/
2268 static void genUminus (iCode *ic)
2269 {
2270   int size, i;
2271   sym_link *optype, *rtype;
2272
2273         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2274         
2275         /* assign asmops */
2276         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2277         pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2278
2279         /* if both in bit space then special case */
2280         if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY
2281                 && AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2282
2283                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2284                 pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2285                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2286                 
2287                 goto release; 
2288         } 
2289
2290         optype = operandType(IC_LEFT(ic));
2291         rtype = operandType(IC_RESULT(ic));
2292
2293         /* if float then do float stuff */
2294         if (IS_FLOAT(optype)) {
2295                 genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2296                 goto release;
2297         }
2298
2299         /* otherwise subtract from zero by taking the 2's complement */
2300         size = AOP_SIZE(IC_LEFT(ic));
2301
2302         for(i=0; i<size; i++) {
2303                 if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2304                         pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2305                 else {
2306                         pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2307                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2308                 }
2309         }
2310
2311         pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2312         for(i=1; i<size; i++) {
2313                 emitSKPNZ;
2314                 pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2315         }
2316
2317 release:
2318         /* release the aops */
2319         pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2320         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2321 }
2322
2323 /*-----------------------------------------------------------------*/
2324 /* saveRegisters - will look for a call and save the registers     */
2325 /*-----------------------------------------------------------------*/
2326 static void saveRegisters(iCode *lic) 
2327 {
2328     int i;
2329     iCode *ic;
2330     bitVect *rsave;
2331     sym_link *dtype;
2332
2333     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2334     /* look for call */
2335     for (ic = lic ; ic ; ic = ic->next) 
2336         if (ic->op == CALL || ic->op == PCALL)
2337             break;
2338
2339     if (!ic) {
2340         fprintf(stderr,"found parameter push with no function call\n");
2341         return ;
2342     }
2343
2344     /* if the registers have been saved already then
2345     do nothing */
2346     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2347         return ;
2348
2349     /* find the registers in use at this time 
2350     and push them away to safety */
2351     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2352                           ic->rUsed);
2353
2354     ic->regsSaved = 1;
2355     if (options.useXstack) {
2356         if (bitVectBitValue(rsave,R0_IDX))
2357             pic16_emitcode("mov","b,r0");
2358         pic16_emitcode("mov","r0,%s",spname);
2359         for (i = 0 ; i < pic16_nRegs ; i++) {
2360             if (bitVectBitValue(rsave,i)) {
2361                 if (i == R0_IDX)
2362                     pic16_emitcode("mov","a,b");
2363                 else
2364                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2365                 pic16_emitcode("movx","@r0,a");
2366                 pic16_emitcode("inc","r0");
2367             }
2368         }
2369         pic16_emitcode("mov","%s,r0",spname);
2370         if (bitVectBitValue(rsave,R0_IDX))
2371             pic16_emitcode("mov","r0,b");           
2372     }// else
2373     //for (i = 0 ; i < pic16_nRegs ; i++) {
2374     //    if (bitVectBitValue(rsave,i))
2375     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2376     //}
2377
2378     dtype = operandType(IC_LEFT(ic));
2379     if (currFunc && dtype && 
2380         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2381         IFFUNC_ISISR(currFunc->type) &&
2382         !ic->bankSaved) 
2383
2384         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2385
2386 }
2387 /*-----------------------------------------------------------------*/
2388 /* unsaveRegisters - pop the pushed registers                      */
2389 /*-----------------------------------------------------------------*/
2390 static void unsaveRegisters (iCode *ic)
2391 {
2392     int i;
2393     bitVect *rsave;
2394
2395     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2396     /* find the registers in use at this time 
2397     and push them away to safety */
2398     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2399                           ic->rUsed);
2400     
2401     if (options.useXstack) {
2402         pic16_emitcode("mov","r0,%s",spname);   
2403         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2404             if (bitVectBitValue(rsave,i)) {
2405                 pic16_emitcode("dec","r0");
2406                 pic16_emitcode("movx","a,@r0");
2407                 if (i == R0_IDX)
2408                     pic16_emitcode("mov","b,a");
2409                 else
2410                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2411             }       
2412
2413         }
2414         pic16_emitcode("mov","%s,r0",spname);
2415         if (bitVectBitValue(rsave,R0_IDX))
2416             pic16_emitcode("mov","r0,b");
2417     } //else
2418     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2419     //    if (bitVectBitValue(rsave,i))
2420     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2421     //}
2422
2423 }  
2424
2425 #if 0  // patch 14
2426 /*-----------------------------------------------------------------*/
2427 /* pushSide -                                                      */
2428 /*-----------------------------------------------------------------*/
2429 static void pushSide(operand * oper, int size)
2430 {
2431         int offset = 0;
2432     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2433         while (size--) {
2434                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2435                 if (AOP_TYPE(oper) != AOP_REG &&
2436                     AOP_TYPE(oper) != AOP_DIR &&
2437                     strcmp(l,"a") ) {
2438                         pic16_emitcode("mov","a,%s",l);
2439                         pic16_emitcode("push","acc");
2440                 } else
2441                         pic16_emitcode("push","%s",l);
2442         }
2443 }
2444 #endif // patch 14
2445
2446 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2447 {
2448 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2449
2450         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2451                 pic16_emitpcode(POC_MOVFW, src);
2452                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2453         } else {
2454                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2455                         src, pic16_popGet(AOP(op), offset)));
2456         }
2457 }
2458
2459
2460 /*-----------------------------------------------------------------*/
2461 /* assignResultValue - assign results to oper, rescall==1 is       */
2462 /*                     called from genCall() or genPCall()         */
2463 /*-----------------------------------------------------------------*/
2464 static void assignResultValue(operand * oper, int rescall)
2465 {
2466   int size = AOP_SIZE(oper);
2467
2468         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2469         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2470
2471         if(rescall) {
2472                 /* assign result from a call/pcall function() */
2473                 
2474                 /* function results are stored in a special order,
2475                  * see top of file with Function return policy, or manual */
2476
2477                 if(size <= 4) {
2478                         /* 8-bits, result in WREG */
2479                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2480                         
2481                         if(size>1) {
2482                                 /* 16-bits, result in PRODL:WREG */
2483                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2484                         }
2485                         
2486                         if(size>2) {
2487                                 /* 24-bits, result in PRODH:PRODL:WREG */
2488                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2489                         }
2490                         
2491                         if(size>3) {
2492                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2493                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2494                         }
2495                 } else {
2496                         /* >32-bits, result on stack, and FSR0 points to beginning.
2497                          * Fix stack when done */
2498                          
2499                         while (size--) {
2500 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2501 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2502                 
2503                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2504                                 GpsuedoStkPtr++;
2505                         }
2506                         
2507                         /* fix stack */
2508                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2509                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2510                         if(STACK_MODEL_LARGE) {
2511                                 emitSKPNC;
2512                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2513                         }
2514                 }                       
2515         } else {        
2516                 if(!GpsuedoStkPtr) {
2517 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2518                         /* The last byte in the assignment is in W */
2519                         size--;
2520                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2521                         GpsuedoStkPtr++;
2522                 }
2523
2524                 while (size--) {
2525 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2526 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2527                 
2528                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2529                         GpsuedoStkPtr++;
2530
2531 #if 0
2532 #if STACK_SUPPORT
2533                 if(!USE_STACK)
2534                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2535 #else
2536                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2537 #endif
2538 #endif
2539
2540                 }
2541         }
2542                 
2543 }
2544
2545
2546 /*-----------------------------------------------------------------*/
2547 /* genIpush - genrate code for pushing this gets a little complex  */
2548 /*-----------------------------------------------------------------*/
2549 static void genIpush (iCode *ic)
2550 {
2551
2552   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2553 #if 0
2554     int size, offset = 0 ;
2555     char *l;
2556
2557
2558     /* if this is not a parm push : ie. it is spill push 
2559     and spill push is always done on the local stack */
2560     if (!ic->parmPush) {
2561
2562         /* and the item is spilt then do nothing */
2563         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2564             return ;
2565
2566         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2567         size = AOP_SIZE(IC_LEFT(ic));
2568         /* push it on the stack */
2569         while(size--) {
2570             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2571             if (*l == '#') {
2572                 MOVA(l);
2573                 l = "acc";
2574             }
2575             pic16_emitcode("push","%s",l);
2576         }
2577         return ;        
2578     }
2579
2580     /* this is a paramter push: in this case we call
2581     the routine to find the call and save those
2582     registers that need to be saved */   
2583     saveRegisters(ic);
2584
2585     /* then do the push */
2586     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2587
2588
2589         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2590     size = AOP_SIZE(IC_LEFT(ic));
2591
2592     while (size--) {
2593         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2594         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2595             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2596             strcmp(l,"a") ) {
2597             pic16_emitcode("mov","a,%s",l);
2598             pic16_emitcode("push","acc");
2599         } else
2600             pic16_emitcode("push","%s",l);
2601     }       
2602
2603     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2604 #endif
2605 }
2606
2607 /*-----------------------------------------------------------------*/
2608 /* genIpop - recover the registers: can happen only for spilling   */
2609 /*-----------------------------------------------------------------*/
2610 static void genIpop (iCode *ic)
2611 {
2612   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2613 #if 0
2614     int size,offset ;
2615
2616
2617     /* if the temp was not pushed then */
2618     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2619         return ;
2620
2621     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2622     size = AOP_SIZE(IC_LEFT(ic));
2623     offset = (size-1);
2624     while (size--) 
2625         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2626                                    FALSE,TRUE));
2627
2628     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2629 #endif
2630 }
2631
2632 /*-----------------------------------------------------------------*/
2633 /* unsaverbank - restores the resgister bank from stack            */
2634 /*-----------------------------------------------------------------*/
2635 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2636 {
2637   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2638 #if 0
2639     int i;
2640     asmop *aop ;
2641     regs *r = NULL;
2642
2643     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2644     if (popPsw) {
2645         if (options.useXstack) {
2646             aop = newAsmop(0);
2647             r = getFreePtr(ic,&aop,FALSE);
2648             
2649             
2650             pic16_emitcode("mov","%s,_spx",r->name);
2651             pic16_emitcode("movx","a,@%s",r->name);
2652             pic16_emitcode("mov","psw,a");
2653             pic16_emitcode("dec","%s",r->name);
2654             
2655         }else
2656             pic16_emitcode ("pop","psw");
2657     }
2658
2659     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2660         if (options.useXstack) {       
2661             pic16_emitcode("movx","a,@%s",r->name);
2662             //pic16_emitcode("mov","(%s+%d),a",
2663             //       regspic16[i].base,8*bank+regspic16[i].offset);
2664             pic16_emitcode("dec","%s",r->name);
2665
2666         } else 
2667           pic16_emitcode("pop",""); //"(%s+%d)",
2668         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2669     }
2670
2671     if (options.useXstack) {
2672
2673         pic16_emitcode("mov","_spx,%s",r->name);
2674         pic16_freeAsmop(NULL,aop,ic,TRUE);
2675
2676     }
2677 #endif 
2678 }
2679
2680 /*-----------------------------------------------------------------*/
2681 /* saverbank - saves an entire register bank on the stack          */
2682 /*-----------------------------------------------------------------*/
2683 static void saverbank (int bank, iCode *ic, bool pushPsw)
2684 {
2685   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2686 #if 0
2687     int i;
2688     asmop *aop ;
2689     regs *r = NULL;
2690
2691     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2692     if (options.useXstack) {
2693
2694         aop = newAsmop(0);
2695         r = getFreePtr(ic,&aop,FALSE);  
2696         pic16_emitcode("mov","%s,_spx",r->name);
2697
2698     }
2699
2700     for (i = 0 ; i < pic16_nRegs ;i++) {
2701         if (options.useXstack) {
2702             pic16_emitcode("inc","%s",r->name);
2703             //pic16_emitcode("mov","a,(%s+%d)",
2704             //         regspic16[i].base,8*bank+regspic16[i].offset);
2705             pic16_emitcode("movx","@%s,a",r->name);           
2706         } else 
2707           pic16_emitcode("push","");// "(%s+%d)",
2708                      //regspic16[i].base,8*bank+regspic16[i].offset);
2709     }
2710     
2711     if (pushPsw) {
2712         if (options.useXstack) {
2713             pic16_emitcode("mov","a,psw");
2714             pic16_emitcode("movx","@%s,a",r->name);     
2715             pic16_emitcode("inc","%s",r->name);
2716             pic16_emitcode("mov","_spx,%s",r->name);       
2717             pic16_freeAsmop (NULL,aop,ic,TRUE);
2718             
2719         } else
2720             pic16_emitcode("push","psw");
2721         
2722         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2723     }
2724     ic->bankSaved = 1;
2725 #endif
2726 }
2727
2728
2729
2730 /*-----------------------------------------------------------------*/
2731 /* genCall - generates a call statement                            */
2732 /*-----------------------------------------------------------------*/
2733 static void genCall (iCode *ic)
2734 {
2735   sym_link *dtype;   
2736   int stackParms=0;
2737   
2738         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2739
2740         /* if caller saves & we have not saved then */
2741         if (!ic->regsSaved)
2742                 saveRegisters(ic);
2743
2744         /* if we are calling a function that is not using
2745          * the same register bank then we need to save the
2746          * destination registers on the stack */
2747         dtype = operandType(IC_LEFT(ic));
2748         if (currFunc && dtype && 
2749                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2750                 IFFUNC_ISISR(currFunc->type) &&
2751                 !ic->bankSaved) 
2752
2753                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2754
2755         /* if send set is not empty the assign */
2756         if (_G.sendSet) {
2757           iCode *sic;
2758
2759                 /* For the Pic port, there is no data stack.
2760                  * So parameters passed to functions are stored
2761                  * in registers. (The pCode optimizer will get
2762                  * rid of most of these :). */
2763
2764           int psuedoStkPtr=-1; 
2765           int firstTimeThruLoop = 1;
2766
2767                 _G.sendSet = reverseSet(_G.sendSet);
2768
2769                 /* First figure how many parameters are getting passed */
2770                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2771                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2772                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2773                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2774                 }
2775
2776                 stackParms = psuedoStkPtr;
2777
2778                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2779                   int size, offset = 0;
2780
2781                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2782                         size = AOP_SIZE(IC_LEFT(sic));
2783
2784                         while (size--) {
2785                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2786                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2787                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2788
2789                                 if(!firstTimeThruLoop) {
2790                                         /* If this is not the first time we've been through the loop
2791                                          * then we need to save the parameter in a temporary
2792                                          * register. The last byte of the last parameter is
2793                                          * passed in W. */
2794
2795                                         pushw();
2796                                         --psuedoStkPtr;         // sanity check
2797                                 }
2798                         
2799                                 firstTimeThruLoop=0;
2800
2801                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2802                                 offset++;
2803                         }
2804                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2805                 }
2806                 _G.sendSet = NULL;
2807         }
2808
2809         /* make the call */
2810         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2811                         OP_SYMBOL(IC_LEFT(ic))->rname :
2812                         OP_SYMBOL(IC_LEFT(ic))->name));
2813
2814         GpsuedoStkPtr=0;
2815         /* if we need assign a result value */
2816         if ((IS_ITEMP(IC_RESULT(ic)) && 
2817                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2818                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2819                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2820
2821                 _G.accInUse++;
2822                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2823                 _G.accInUse--;
2824
2825                 assignResultValue(IC_RESULT(ic), 1);
2826
2827                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2828                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2829                 
2830                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2831         }
2832
2833         if(stackParms>0) {
2834                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2835                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2836                 if(STACK_MODEL_LARGE) {
2837                         emitSKPNC;
2838                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2839                 }
2840         }
2841
2842         /* adjust the stack for parameters if required */
2843 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2844
2845         if (ic->parmBytes) {
2846           int i;
2847
2848                 if (ic->parmBytes > 3) {
2849                         pic16_emitcode("mov","a,%s",spname);
2850                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2851                         pic16_emitcode("mov","%s,a",spname);
2852                 } else 
2853                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2854                                 pic16_emitcode("dec","%s",spname);
2855         }
2856
2857 #if 0
2858         /* if register bank was saved then pop them */
2859         if (ic->bankSaved)
2860                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2861
2862         /* if we hade saved some registers then unsave them */
2863         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2864                 unsaveRegisters (ic);
2865 #endif
2866 }
2867
2868
2869
2870 /*-----------------------------------------------------------------*/   // patch 14
2871 /* genPcall - generates a call by pointer statement                */
2872 /*-----------------------------------------------------------------*/
2873
2874 // new version, created from genCall
2875
2876 static void genPcall (iCode *ic)
2877 {
2878   sym_link *dtype;   
2879   int stackParms=0;
2880   symbol *retlbl = newiTempLabel(NULL);
2881   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2882   
2883         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2884
2885         /* if caller saves & we have not saved then */
2886         if (!ic->regsSaved)
2887                 saveRegisters(ic);
2888
2889         /* if we are calling a function that is not using
2890          * the same register bank then we need to save the
2891          * destination registers on the stack */
2892         dtype = operandType(IC_LEFT(ic));
2893         if (currFunc && dtype && 
2894                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2895                 IFFUNC_ISISR(currFunc->type) &&
2896                 !ic->bankSaved) 
2897
2898                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2899
2900         /* if send set is not empty the assign */
2901         if (_G.sendSet) {
2902           iCode *sic;
2903
2904                 /* For the Pic port, there is no data stack.
2905                  * So parameters passed to functions are stored
2906                  * in registers. (The pCode optimizer will get
2907                  * rid of most of these :). */
2908
2909           int psuedoStkPtr=-1; 
2910           int firstTimeThruLoop = 1;
2911
2912                 _G.sendSet = reverseSet(_G.sendSet);
2913
2914                 /* First figure how many parameters are getting passed */
2915                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2916                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2917                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2918                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2919                 }
2920
2921                 stackParms = psuedoStkPtr;
2922
2923                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2924                   int size, offset = 0;
2925
2926                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2927                         size = AOP_SIZE(IC_LEFT(sic));
2928
2929                         while (size--) {
2930                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2931                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2932                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2933
2934                                 if(!firstTimeThruLoop) {
2935                                         /* If this is not the first time we've been through the loop
2936                                          * then we need to save the parameter in a temporary
2937                                          * register. The last byte of the last parameter is
2938                                          * passed in W. */
2939
2940                                         pushw();
2941                                         --psuedoStkPtr;         // sanity check
2942                                 }
2943                         
2944                                 firstTimeThruLoop=0;
2945
2946                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2947                                 offset++;
2948                         }
2949                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2950                 }
2951                 _G.sendSet = NULL;
2952         }
2953
2954         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2955
2956         // push return address
2957         // push $ on return stack, then replace with retlbl
2958
2959         // Note: retlbl is supplied as dummy operand to PUSH
2960         // This has the nice side effect of keeping the label from being optimized out :o)
2961         pic16_emitpcode(POC_PUSH, pic16_popGetLabel(retlbl->key));      
2962
2963         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2964         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2965         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2966         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2967         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2968         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2969
2970         /* make the call by writing the pointer into pc */
2971 // FIXME Disabled writes to PCLATU because of gpsim problems
2972 #if 1
2973         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2974 #else
2975         fprintf(stderr,
2976 "WARNING: (%s:%d) PCLATU is not written because of gpsim problems\n\
2977 Correct this as soon as gpsim bug is fixed\n", __FILE__, __LINE__);
2978 #endif
2979  
2980         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2981         // note: MOVFF to PCL not allowed
2982         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2983         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2984
2985         /* return address is here: (X) */
2986         pic16_emitpLabel(retlbl->key);
2987
2988         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2989
2990         GpsuedoStkPtr=0;
2991         /* if we need assign a result value */
2992         if ((IS_ITEMP(IC_RESULT(ic)) && 
2993                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2994                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2995                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2996
2997                 _G.accInUse++;
2998                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2999                 _G.accInUse--;
3000
3001                 assignResultValue(IC_RESULT(ic), 1);
3002
3003                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
3004                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
3005                 
3006                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
3007         }
3008
3009         if(stackParms>0) {
3010                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
3011                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
3012                 if(STACK_MODEL_LARGE) {
3013                         emitSKPNC;
3014                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3015                 }
3016         }
3017
3018         /* adjust the stack for parameters if required */
3019 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3020
3021         if (ic->parmBytes) {
3022           int i;
3023
3024                 if (ic->parmBytes > 3) {
3025                         pic16_emitcode("mov","a,%s",spname);
3026                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3027                         pic16_emitcode("mov","%s,a",spname);
3028                 } else 
3029                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3030                                 pic16_emitcode("dec","%s",spname);
3031         }
3032
3033         /* if register bank was saved then pop them */
3034         if (ic->bankSaved)
3035                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3036
3037         /* if we hade saved some registers then unsave them */
3038         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3039                 unsaveRegisters (ic);
3040 }
3041
3042
3043 #if 0                                                                           // patch 14
3044 // old version, kept for reference
3045
3046 /*-----------------------------------------------------------------*/
3047 /* genPcall - generates a call by pointer statement                */
3048 /*-----------------------------------------------------------------*/
3049 static void genPcall (iCode *ic)
3050 {
3051     sym_link *dtype;
3052     symbol *rlbl = newiTempLabel(NULL);
3053
3054
3055     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3056     /* if caller saves & we have not saved then */
3057     if (!ic->regsSaved)
3058         saveRegisters(ic);
3059
3060     /* if we are calling a function that is not using
3061     the same register bank then we need to save the
3062     destination registers on the stack */
3063     dtype = operandType(IC_LEFT(ic));
3064     if (currFunc && dtype && 
3065         IFFUNC_ISISR(currFunc->type) &&
3066         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3067         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3068
3069
3070     /* push the return address on to the stack */
3071     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3072     pic16_emitcode("push","acc");    
3073     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3074     pic16_emitcode("push","acc");
3075     
3076     if (options.model == MODEL_FLAT24)
3077     {
3078         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3079         pic16_emitcode("push","acc");    
3080     }
3081
3082     /* now push the calling address */
3083     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3084
3085     pushSide(IC_LEFT(ic), FPTRSIZE);
3086
3087     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3088
3089     /* if send set is not empty the assign */
3090     if (_G.sendSet) {
3091         iCode *sic ;
3092
3093         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3094              sic = setNextItem(_G.sendSet)) {
3095             int size, offset = 0;
3096             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3097             size = AOP_SIZE(IC_LEFT(sic));
3098             while (size--) {
3099                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3100                                 FALSE,FALSE);
3101                 if (strcmp(l,fReturn[offset]))
3102                     pic16_emitcode("mov","%s,%s",
3103                              fReturn[offset],
3104                              l);
3105                 offset++;
3106             }
3107             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3108         }
3109         _G.sendSet = NULL;
3110     }
3111
3112     pic16_emitcode("ret","");
3113     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3114
3115
3116     /* if we need assign a result value */
3117     if ((IS_ITEMP(IC_RESULT(ic)) &&
3118          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3119           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3120         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3121
3122         _G.accInUse++;
3123         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3124         _G.accInUse--;
3125         
3126         assignResultValue(IC_RESULT(ic), 1);
3127
3128         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3129     }
3130
3131     /* adjust the stack for parameters if 
3132     required */
3133     if (ic->parmBytes) {
3134         int i;
3135         if (ic->parmBytes > 3) {
3136             pic16_emitcode("mov","a,%s",spname);
3137             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3138             pic16_emitcode("mov","%s,a",spname);
3139         } else 
3140             for ( i = 0 ; i <  ic->parmBytes ;i++)
3141                 pic16_emitcode("dec","%s",spname);
3142
3143     }
3144
3145     /* if register bank was saved then unsave them */
3146     if (currFunc && dtype && 
3147         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3148         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3149
3150     /* if we hade saved some registers then
3151     unsave them */
3152     if (ic->regsSaved)
3153         unsaveRegisters (ic);
3154
3155 }
3156 #endif                                                                          // patch 14
3157
3158
3159 /*-----------------------------------------------------------------*/
3160 /* resultRemat - result  is rematerializable                       */
3161 /*-----------------------------------------------------------------*/
3162 static int resultRemat (iCode *ic)
3163 {
3164   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3165   if (SKIP_IC(ic) || ic->op == IFX)
3166     return 0;
3167
3168   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3169     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3170     if (sym->remat && !POINTER_SET(ic)) 
3171       return 1;
3172   }
3173
3174   return 0;
3175 }
3176
3177 #if defined(__BORLANDC__) || defined(_MSC_VER)
3178 #define STRCASECMP stricmp
3179 #else
3180 #define STRCASECMP strcasecmp
3181 #endif
3182
3183 #if 0
3184 /*-----------------------------------------------------------------*/
3185 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3186 /*-----------------------------------------------------------------*/
3187 static bool inExcludeList(char *s)
3188 {
3189   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3190     int i =0;
3191     
3192     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3193     if (options.excludeRegs[i] &&
3194     STRCASECMP(options.excludeRegs[i],"none") == 0)
3195         return FALSE ;
3196
3197     for ( i = 0 ; options.excludeRegs[i]; i++) {
3198         if (options.excludeRegs[i] &&
3199         STRCASECMP(s,options.excludeRegs[i]) == 0)
3200             return TRUE;
3201     }
3202     return FALSE ;
3203 }
3204 #endif
3205
3206 /*-----------------------------------------------------------------*/
3207 /* genFunction - generated code for function entry                 */
3208 /*-----------------------------------------------------------------*/
3209 static void genFunction (iCode *ic)
3210 {
3211   symbol *sym;
3212   sym_link *ftype;
3213   
3214         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
3215
3216         labelOffset += (max_key+4);
3217         max_key=0;
3218         GpsuedoStkPtr=0;
3219         _G.nRegsSaved = 0;
3220
3221         ftype = operandType(IC_LEFT(ic));
3222         sym = OP_SYMBOL(IC_LEFT(ic));
3223
3224         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3225                 /* create an absolute section at the interrupt vector:
3226                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3227           symbol *asym;
3228           char asymname[128];
3229           pBlock *apb;
3230
3231                 {
3232                   int i, found=-1;
3233
3234                         sym = OP_SYMBOL( IC_LEFT(ic));
3235                         for(i=0;i<=2;i++) {
3236                                 if(interrupts[i]->name
3237                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3238                                         found = i;
3239                                         break;
3240                                 }
3241                         }
3242                         
3243                         if(found == -1) {
3244                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3245                                         __FILE__, __LINE__, sym->name);
3246                                 assert( 0 );
3247                         }
3248                         _G.interruptvector = found;
3249                 }
3250
3251                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3252                 asym = newSymbol(asymname, 0);
3253
3254                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3255                 pic16_addpBlock( apb );
3256
3257                 pic16_addpCode2pBlock(apb,
3258                         pic16_newpCodeCharP(";-----------------------------------------"));
3259
3260
3261                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3262
3263                 pic16_addpCode2pBlock(apb,
3264                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3265                 
3266                 /* mark the end of this tiny function */
3267                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3268
3269                 {
3270                   absSym *abSym;
3271
3272                         abSym = Safe_calloc(1, sizeof(absSym));
3273                         abSym->name = Safe_strdup( asymname );
3274
3275                         switch( _G.interruptvector ) {
3276                                 case 0: abSym->address = 0x000000; break;
3277                                 case 1: abSym->address = 0x000008; break;
3278                                 case 2: abSym->address = 0x000018; break;
3279                         }
3280
3281                         addSet(&absSymSet, abSym);
3282                 }
3283         }
3284
3285
3286         /* create the function header */
3287         pic16_emitcode(";","-----------------------------------------");
3288         pic16_emitcode(";"," function %s",sym->name);
3289         pic16_emitcode(";","-----------------------------------------");
3290
3291         pic16_emitcode("","%s:",sym->rname);
3292         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3293
3294
3295         {
3296           absSym *ab;
3297
3298                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3299                         if(!strcmp(ab->name, sym->name)) {
3300                                 pic16_pBlockConvert2Absolute(pb);
3301                                 break;
3302                         }
3303
3304         }
3305
3306
3307         if(IFFUNC_ISNAKED(ftype)) {
3308                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3309                 return;
3310         }
3311         
3312         /* if critical function then turn interrupts off */
3313         if (IFFUNC_ISCRITICAL(ftype))
3314                 pic16_emitcode("clr","ea");
3315
3316         /* if this is an interrupt service routine then
3317          * save acc, b, dpl, dph  */
3318         if (IFFUNC_ISISR(sym->type)) {
3319           int i;
3320                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3321                 if(!(_G.interruptvector == 1)) {
3322
3323                         /* do not save WREG,STATUS,BSR for high priority interrupts
3324                          * because they are stored in the hardware shadow registers already */
3325                          
3326                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3327                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3328                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3329                 }
3330
3331                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3332                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3333                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3334                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3335
3336 //                pic16_pBlockConvert2ISR(pb);
3337                 
3338                 /* if any registers used */
3339                 if (sym->regsUsed) {
3340                         /* save the registers used */
3341                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3342                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3343                                 if (bitVectBitValue(sym->regsUsed,i)) {
3344 //                                      fprintf(stderr, "%s:%d function %s uses register %s\n",
3345 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3346 //                                                      pic16_regWithIdx(i)->name);
3347
3348                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3349                                         _G.nRegsSaved++;
3350                                 }
3351                         }
3352                 }
3353         } else {
3354                 /* emit code to setup stack frame if user enabled,
3355                  * and function is not main() */
3356          
3357 //              fprintf(stderr, "function name: %s\n", sym->name);
3358                 if(strcmp(sym->name, "main")) {
3359                         if(/*!options.ommitFramePtr || */sym->regsUsed) {
3360                         /* setup the stack frame */
3361                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3362                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3363                                 if(STACK_MODEL_LARGE)
3364                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3365                         }
3366                 }
3367
3368                 /* if callee-save to be used for this function
3369                 * then save the registers being used in this function */
3370 //              if (IFFUNC_CALLEESAVES(sym->type))
3371                 {
3372                   int i;
3373
3374 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3375
3376 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3377
3378                         /* if any registers used */
3379                         if (sym->regsUsed) {
3380                                 /* save the registers used */
3381                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3382                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3383                                         if (bitVectBitValue(sym->regsUsed,i)) {
3384
3385 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3386 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3387 //                                                              pic16_regWithIdx(i)->name);
3388
3389                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3390
3391 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3392 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3393 //                                                      &pic16_pc_postdec1, 0));
3394
3395                                                 _G.nRegsSaved++;
3396                                         }
3397                                 }
3398                         }
3399                 }
3400         }
3401
3402
3403         
3404 #if 0
3405         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3406
3407                 if (options.useXstack) {
3408                         pic16_emitcode("mov","r0,%s",spname);
3409                         pic16_emitcode("mov","a,_bp");
3410                         pic16_emitcode("movx","@r0,a");
3411                         pic16_emitcode("inc","%s",spname);
3412                 } else {
3413                         /* set up the stack */
3414                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3415                 }
3416                 pic16_emitcode ("mov","_bp,%s",spname);
3417         }
3418 #endif
3419         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3420
3421         /* adjust the stack for the function */
3422         if (sym->stack) {
3423           int i = sym->stack;
3424
3425                 if (i > 127 ) 
3426                         werror(W_STACK_OVERFLOW,sym->name);
3427
3428                 if (i > 3 && sym->recvSize < 4) {              
3429                         pic16_emitcode ("mov","a,sp");
3430                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3431                         pic16_emitcode ("mov","sp,a");
3432                 } else
3433                         while(i--)
3434                                 pic16_emitcode("inc","sp");
3435         }
3436
3437         if (sym->xstack) {
3438                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3439
3440                 pic16_emitcode ("mov","a,_spx");
3441                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3442                 pic16_emitcode ("mov","_spx,a");
3443         }
3444     
3445 }
3446
3447 /*-----------------------------------------------------------------*/
3448 /* genEndFunction - generates epilogue for functions               */
3449 /*-----------------------------------------------------------------*/
3450 static void genEndFunction (iCode *ic)
3451 {
3452     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3453
3454     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3455
3456     if(IFFUNC_ISNAKED(sym->type)) {
3457         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3458         return;
3459     }
3460
3461 #if 0
3462     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3463     {
3464         pic16_emitcode ("mov","%s,_bp",spname);
3465     }
3466 #endif
3467
3468     /* if use external stack but some variables were
3469     added to the local stack then decrement the
3470     local stack */
3471     if (options.useXstack && sym->stack) {      
3472         pic16_emitcode("mov","a,sp");
3473         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3474         pic16_emitcode("mov","sp,a");
3475     }
3476
3477
3478 #if 0
3479     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3480         if (options.useXstack) {
3481             pic16_emitcode("mov","r0,%s",spname);
3482             pic16_emitcode("movx","a,@r0");
3483             pic16_emitcode("mov","_bp,a");
3484             pic16_emitcode("dec","%s",spname);
3485         }
3486         else
3487         {
3488             pic16_emitcode ("pop","_bp");
3489         }
3490     }
3491 #endif
3492
3493         if (IFFUNC_ISISR(sym->type)) {
3494                 /* now we need to restore the registers */
3495                 /* if any registers used */
3496                 if (sym->regsUsed) {
3497                   int i;
3498
3499                         /* restore registers used */
3500                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3501                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3502                                 if (bitVectBitValue(sym->regsUsed,i)) {
3503
3504 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3505 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3506 //                                                      pic16_regWithIdx(i)->name);
3507
3508                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3509
3510 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3511 //                                                      &pic16_pc_preinc1,
3512 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3513
3514                                 }
3515                         }
3516                 }
3517         
3518                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3519                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3520                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3521                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3522
3523                 if(!(_G.interruptvector == 1)) {
3524                         /* do not restore interrupt vector for WREG,STATUS,BSR
3525                          * for high priority interrupt, see genFunction */
3526                          
3527                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3528                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3529                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3530                 }
3531         
3532                 _G.interruptvector = 0;         /* sanity check */
3533
3534 //              pic16_pBlockConvert2ISR(pb);
3535
3536
3537                 /* if debug then send end of function */
3538 /*      if (options.debug && currFunc)  */
3539                 if (currFunc) {
3540                         debugFile->writeEndFunction (currFunc, ic, 1);
3541                 }
3542         
3543                 pic16_emitpcodeNULLop(POC_RETFIE);
3544         } else {
3545                 if (IFFUNC_ISCRITICAL(sym->type))
3546                         pic16_emitcode("setb","ea");
3547         
3548
3549 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3550
3551                 /* if any registers used */
3552                 if (sym->regsUsed) {
3553                   int i;
3554                         /* save the registers used */
3555                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3556                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3557                                 if (bitVectBitValue(sym->regsUsed,i)) {
3558         
3559 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3560 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3561 //                                                      pic16_regWithIdx(i)->name);
3562         
3563                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3564                                         
3565 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3566 //                                              &pic16_pc_preinc1,
3567 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3568
3569                                         _G.nRegsSaved--;
3570                                 }
3571                         }
3572                 }
3573         
3574                 pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3575                 /* if debug then send end of function */
3576                 if (currFunc) {
3577                         debugFile->writeEndFunction (currFunc, ic, 1);
3578                 }
3579
3580                 /* insert code to restore stack frame, if user enabled it
3581                  * and function is not main() */
3582          
3583
3584                 if(strcmp(sym->name, "main")) {
3585                         if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3586                                 /* restore stack frame */
3587                                 if(STACK_MODEL_LARGE)
3588                                         pic16_emitpcode(POC_MOVFF,
3589                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3590                                 pic16_emitpcode(POC_MOVFF,
3591                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3592                         }
3593                 }
3594
3595                 pic16_emitcode ("return","");
3596                 pic16_emitpcodeNULLop(POC_RETURN);
3597
3598                 /* Mark the end of a function */
3599                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3600         }
3601
3602 }
3603
3604
3605 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3606 {
3607
3608         if(is_LitOp(op))
3609 //      if((AOP(op)->aopu.pcop->type == PO_IMMEDIATE)
3610 //              || (AOP(op)->aopu.pcop->type == PO_LITERAL))
3611         {
3612                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3613
3614                 if(dest->type != PO_WREG)
3615                         pic16_emitpcode(POC_MOVWF, dest);
3616         } else {
3617                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3618                         pic16_popGet(AOP(op), offset), dest));
3619         }
3620 }
3621
3622 /*-----------------------------------------------------------------*/
3623 /* genRet - generate code for return statement                     */
3624 /*-----------------------------------------------------------------*/
3625 static void genRet (iCode *ic)
3626 {
3627   int size;
3628   operand *left;
3629
3630         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3631         /* if we have no return value then
3632          * just generate the "ret" */
3633         
3634         if (!IC_LEFT(ic)) 
3635                 goto jumpret;       
3636     
3637         /* we have something to return then
3638          * move the return value into place */
3639         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3640         size = AOP_SIZE(IC_LEFT(ic));
3641
3642         if(size <= 4) {
3643                 if(size>3) {
3644                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3645 //                      pic16_emitpcode(POC_MOVFF,
3646 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3647                 }
3648                 if(size>2) {
3649                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3650 //                      pic16_emitpcode(POC_MOVFF,
3651 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3652                 }
3653                 if(size>1) {
3654                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3655 //                      pic16_emitpcode(POC_MOVFF,
3656 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3657                 }
3658
3659 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3660
3661                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3662 //              pic16_emitpcode(POC_MOVFF,
3663 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3664
3665         } else {
3666                 /* >32-bits, setup stack and FSR0 */
3667                 while (size--) {
3668 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3669 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3670
3671                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3672
3673 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3674                         GpsuedoStkPtr++;
3675                 }
3676                         
3677                 /* setup FSR0 */
3678                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3679                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3680
3681                 if(STACK_MODEL_LARGE) {
3682                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3683                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3684                 } else {
3685                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3686                 }
3687         }
3688                                 
3689 #if 0
3690         /* old code, left here for reference -- VR */    
3691         while (size--) {
3692           char *l ;
3693
3694                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3695                         /* #NOCHANGE */
3696                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3697                         pic16_emitpcomment("push %s",l);
3698                         pushed++;
3699                 } else {
3700                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3701                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3702                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3703                         
3704                         if (strcmp(fReturn[offset],l)) {
3705                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3706                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3707                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3708                                 } else {
3709                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3710                                 }
3711                                 
3712                                 if(size) {
3713                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3714                                 }
3715                                 offset++;
3716                         }
3717                 }
3718         }    
3719
3720         if (pushed) {
3721                 while(pushed) {
3722                         pushed--;
3723                         if (strcmp(fReturn[pushed],"a"))
3724                                 pic16_emitcode("pop",fReturn[pushed]);
3725                         else
3726                                 pic16_emitcode("pop","acc");
3727                 }
3728         }
3729 #endif
3730
3731
3732         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3733     
3734 jumpret:
3735         /* generate a jump to the return label
3736          * if the next is not the return statement */
3737         if (!(ic->next && ic->next->op == LABEL
3738                 && IC_LABEL(ic->next) == returnLabel)) {
3739         
3740                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3741                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3742         }
3743 }
3744
3745 /*-----------------------------------------------------------------*/
3746 /* genLabel - generates a label                                    */
3747 /*-----------------------------------------------------------------*/
3748 static void genLabel (iCode *ic)
3749 {
3750
3751
3752     /* special case never generate */
3753     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3754     if (IC_LABEL(ic) == entryLabel)
3755         return ;
3756
3757     pic16_emitpLabel(IC_LABEL(ic)->key);
3758     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3759 }
3760
3761 /*-----------------------------------------------------------------*/
3762 /* genGoto - generates a goto                                      */
3763 /*-----------------------------------------------------------------*/
3764 //tsd
3765 static void genGoto (iCode *ic)
3766 {
3767   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3768   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3769 }
3770
3771
3772 /*-----------------------------------------------------------------*/
3773 /* genMultbits :- multiplication of bits                           */
3774 /*-----------------------------------------------------------------*/
3775 static void genMultbits (operand *left, 
3776                          operand *right, 
3777                          operand *result)
3778 {
3779   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3780
3781   if(!pic16_sameRegs(AOP(result),AOP(right)))
3782     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3783
3784   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3785   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3786   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3787
3788 }
3789
3790
3791 /*-----------------------------------------------------------------*/
3792 /* genMultOneByte : 8 bit multiplication & division                */
3793 /*-----------------------------------------------------------------*/
3794 static void genMultOneByte (operand *left,
3795                             operand *right,
3796                             operand *result)
3797 {
3798
3799   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3800   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3801   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3802
3803   /* (if two literals, the value is computed before) */
3804   /* if one literal, literal on the right */
3805   if (AOP_TYPE(left) == AOP_LIT){
3806     operand *t = right;
3807     right = left;
3808     left = t;
3809   }
3810
3811         /* size is already checked in genMult == 1 */
3812 //      size = AOP_SIZE(result);
3813
3814         if (AOP_TYPE(right) == AOP_LIT){
3815                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3816                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3817                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3818                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3819         } else {
3820                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3821                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3822                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3823                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3824         }
3825         
3826         pic16_genMult8X8_8 (left, right,result);
3827 }
3828
3829 /*-----------------------------------------------------------------*/
3830 /* genMultOneWord : 16 bit multiplication                          */
3831 /*-----------------------------------------------------------------*/
3832 static void genMultOneWord (operand *left,
3833                             operand *right,
3834                             operand *result)
3835 {
3836
3837         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3838         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3839         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3840
3841         /* (if two literals, the value is computed before)
3842          * if one literal, literal on the right */
3843         if (AOP_TYPE(left) == AOP_LIT){
3844           operand *t = right;
3845                 right = left;
3846                 left = t;
3847         }
3848
3849         /* size is checked already == 2 */
3850 //      size = AOP_SIZE(result);
3851
3852         if (AOP_TYPE(right) == AOP_LIT) {
3853                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3854                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3855                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3856                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3857         } else {
3858                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3859                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3860                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3861                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3862         }
3863         
3864         pic16_genMult16X16_16(left, right,result);
3865 }
3866
3867 /*-----------------------------------------------------------------*/
3868 /* genMultOneLong : 32 bit multiplication                          */
3869 /*-----------------------------------------------------------------*/
3870 static void genMultOneLong (operand *left,
3871                             operand *right,
3872                             operand *result)
3873 {
3874
3875         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3876         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3877         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3878
3879         /* (if two literals, the value is computed before)
3880          * if one literal, literal on the right */
3881         if (AOP_TYPE(left) == AOP_LIT){
3882           operand *t = right;
3883                 right = left;
3884                 left = t;
3885         }
3886
3887         /* size is checked already == 4 */
3888 //      size = AOP_SIZE(result);
3889
3890         if (AOP_TYPE(right) == AOP_LIT) {
3891                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3892                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3893                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3894                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3895         } else {
3896                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3897                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3898                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3899                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3900         }
3901         
3902         pic16_genMult32X32_32(left, right,result);
3903 }
3904
3905
3906
3907 /*-----------------------------------------------------------------*/
3908 /* genMult - generates code for multiplication                     */
3909 /*-----------------------------------------------------------------*/
3910 static void genMult (iCode *ic)
3911 {
3912   operand *left = IC_LEFT(ic);
3913   operand *right = IC_RIGHT(ic);
3914   operand *result= IC_RESULT(ic);   
3915
3916         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3917         /* assign the amsops */
3918         pic16_aopOp (left,ic,FALSE);
3919         pic16_aopOp (right,ic,FALSE);
3920         pic16_aopOp (result,ic,TRUE);
3921
3922         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3923
3924         /* special cases first *
3925         * both are bits */
3926         if (AOP_TYPE(left) == AOP_CRY
3927                 && AOP_TYPE(right)== AOP_CRY) {
3928                 genMultbits(left,right,result);
3929           goto release ;
3930         }
3931
3932         /* if both are of size == 1 */
3933         if(AOP_SIZE(left) == 1
3934                 && AOP_SIZE(right) == 1) {
3935                 genMultOneByte(left,right,result);
3936           goto release ;
3937         }
3938
3939         /* if both are of size == 2 */
3940         if(AOP_SIZE(left) == 2
3941                 && AOP_SIZE(right) == 2) {
3942                 genMultOneWord(left, right, result);
3943           goto release;
3944         }
3945         
3946         /* if both are of size == 4 */
3947         if(AOP_SIZE(left) == 4
3948                 && AOP_SIZE(right) == 4) {
3949                 genMultOneLong(left, right, result);
3950           goto release;
3951         }
3952         
3953         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3954
3955
3956         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3957         /* should have been converted to function call */
3958         assert(0) ;
3959
3960 release :
3961         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3962         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3963         pic16_freeAsmop(result,NULL,ic,TRUE); 
3964 }
3965
3966 /*-----------------------------------------------------------------*/
3967 /* genDivbits :- division of bits                                  */
3968 /*-----------------------------------------------------------------*/
3969 static void genDivbits (operand *left, 
3970                         operand *right, 
3971                         operand *result)
3972 {
3973
3974     char *l;
3975
3976     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3977     /* the result must be bit */    
3978     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3979     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3980
3981     MOVA(l);    
3982
3983     pic16_emitcode("div","ab");
3984     pic16_emitcode("rrc","a");
3985     pic16_aopPut(AOP(result),"c",0);
3986 }
3987
3988 /*-----------------------------------------------------------------*/
3989 /* genDivOneByte : 8 bit division                                  */
3990 /*-----------------------------------------------------------------*/
3991 static void genDivOneByte (operand *left,
3992                            operand *right,
3993                            operand *result)
3994 {
3995     sym_link *opetype = operandType(result);
3996     char *l ;
3997     symbol *lbl ;
3998     int size,offset;
3999
4000         /* result = divident / divisor
4001          * - divident may be a register or a literal,
4002          * - divisor may be a register or a literal,
4003          * so there are 3 cases (literal / literal is optimized
4004          * by the front-end) to handle.
4005          * In addition we must handle signed and unsigned, which
4006          * result in 6 final different cases -- VR */
4007
4008     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4009     size = AOP_SIZE(result) - 1;
4010     offset = 1;
4011     /* signed or unsigned */
4012     if (SPEC_USIGN(opetype)) {
4013       pCodeOp *pct1,    /* count */
4014                 *pct2,  /* reste */
4015                 *pct3;  /* temp */
4016       symbol *label1, *label2, *label3;;
4017
4018
4019         /* unsigned is easy */
4020
4021         pct1 = pic16_popGetTempReg();
4022         pct2 = pic16_popGetTempReg();
4023         pct3 = pic16_popGetTempReg();
4024         
4025         label1 = newiTempLabel(NULL);
4026         label2 = newiTempLabel(NULL);
4027         label3 = newiTempLabel(NULL);
4028
4029         /* the following algorithm is extracted from divuint.c */
4030
4031         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( 8 ));
4032         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct1 ));
4033         
4034         pic16_emitpcode(POC_CLRF, pic16_pCodeOpCopy( pct2 ));
4035
4036         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
4037         
4038         pic16_emitpLabel(label1->key);
4039         
4040         emitCLRC;
4041         pic16_emitpcode(POC_RLCF, pic16_pCodeOpCopy( pct2 ));
4042
4043
4044         emitCLRC;
4045         pic16_emitpcode(POC_RLCF, pic16_popCopyReg( &pic16_pc_wreg ));
4046         
4047
4048         emitSKPNC;
4049         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy( pct2 ));
4050         
4051         pic16_emitpcode(POC_MOVWF, pic16_pCodeOpCopy( pct3 ));
4052         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), 0));
4053         
4054         pic16_emitpcode(POC_CPFSLT, pic16_pCodeOpCopy(pct2));
4055         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label3->key));
4056         pic16_emitpcode(POC_BRA, pic16_popGetLabel(label2->key));
4057         
4058         pic16_emitpLabel( label3->key );
4059         pic16_emitpcode(POC_SUBWF, pic16_pCodeOpCopy(pct2));
4060         pic16_emitpcode(POC_INCF, pic16_pCodeOpCopy(pct3));
4061         
4062         
4063
4064         pic16_emitpLabel(label2->key);
4065         pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct3));
4066         pic16_emitpcode(POC_DECFSZ, pic16_pCodeOpCopy(pct1));
4067         pic16_emitpcode(POC_BRA, pic16_popGetLabel( label1->key ));
4068         
4069         /* result is in wreg */
4070         if(AOP_TYPE(result) != AOP_ACC)
4071                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
4072
4073         pic16_popReleaseTempReg( pct3 );
4074         pic16_popReleaseTempReg( pct2 );
4075         pic16_popReleaseTempReg( pct1 );
4076
4077         return ;
4078     }
4079
4080     /* signed is a little bit more difficult */
4081
4082     /* save the signs of the operands */
4083     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4084     MOVA(l);    
4085     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4086     pic16_emitcode("push","acc"); /* save it on the stack */
4087
4088     /* now sign adjust for both left & right */
4089     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4090     MOVA(l);       
4091     lbl = newiTempLabel(NULL);
4092     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4093     pic16_emitcode("cpl","a");   
4094     pic16_emitcode("inc","a");
4095     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4096     pic16_emitcode("mov","b,a");
4097
4098     /* sign adjust left side */
4099     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4100     MOVA(l);
4101
4102     lbl = newiTempLabel(NULL);
4103     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4104     pic16_emitcode("cpl","a");
4105     pic16_emitcode("inc","a");
4106     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4107
4108     /* now the division */
4109     pic16_emitcode("div","ab");
4110     /* we are interested in the lower order
4111     only */
4112     pic16_emitcode("mov","b,a");
4113     lbl = newiTempLabel(NULL);
4114     pic16_emitcode("pop","acc");   
4115     /* if there was an over flow we don't 
4116     adjust the sign of the result */
4117     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4118     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4119     CLRC;
4120     pic16_emitcode("clr","a");
4121     pic16_emitcode("subb","a,b");
4122     pic16_emitcode("mov","b,a");
4123     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4124
4125     /* now we are done */
4126     pic16_aopPut(AOP(result),"b",0);
4127     if(size > 0){
4128         pic16_emitcode("mov","c,b.7");
4129         pic16_emitcode("subb","a,acc");   
4130     }
4131     while (size--)
4132         pic16_aopPut(AOP(result),"a",offset++);
4133
4134 }
4135
4136 /*-----------------------------------------------------------------*/
4137 /* genDiv - generates code for division                            */
4138 /*-----------------------------------------------------------------*/
4139 static void genDiv (iCode *ic)
4140 {
4141     operand *left = IC_LEFT(ic);
4142     operand *right = IC_RIGHT(ic);
4143     operand *result= IC_RESULT(ic);   
4144
4145
4146         /* Division is a very lengthy algorithm, so it is better
4147          * to call support routines than inlining algorithm.
4148          * Division functions written here just in case someone
4149          * wants to inline and not use the support libraries -- VR */
4150
4151     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4152     /* assign the amsops */
4153     pic16_aopOp (left,ic,FALSE);
4154     pic16_aopOp (right,ic,FALSE);
4155     pic16_aopOp (result,ic,TRUE);
4156
4157     /* special cases first */
4158     /* both are bits */
4159     if (AOP_TYPE(left) == AOP_CRY &&
4160         AOP_TYPE(right)== AOP_CRY) {
4161         genDivbits(left,right,result);
4162         goto release ;
4163     }
4164
4165     /* if both are of size == 1 */
4166     if (AOP_SIZE(left) == 1 &&
4167         AOP_SIZE(right) == 1 ) {
4168         genDivOneByte(left,right,result);
4169         goto release ;
4170     }
4171
4172     /* should have been converted to function call */
4173     assert(0);
4174 release :
4175     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4176     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4177     pic16_freeAsmop(result,NULL,ic,TRUE); 
4178 }
4179
4180 /*-----------------------------------------------------------------*/
4181 /* genModbits :- modulus of bits                                   */
4182 /*-----------------------------------------------------------------*/
4183 static void genModbits (operand *left, 
4184                         operand *right, 
4185                         operand *result)
4186 {
4187
4188     char *l;
4189
4190     /* the result must be bit */    
4191     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4192     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4193
4194     MOVA(l);       
4195
4196     pic16_emitcode("div","ab");
4197     pic16_emitcode("mov","a,b");
4198     pic16_emitcode("rrc","a");
4199     pic16_aopPut(AOP(result),"c",0);
4200 }
4201
4202 /*-----------------------------------------------------------------*/
4203 /* genModOneByte : 8 bit modulus                                   */
4204 /*-----------------------------------------------------------------*/
4205 static void genModOneByte (operand *left,
4206                            operand *right,
4207                            operand *result)
4208 {
4209     sym_link *opetype = operandType(result);
4210     char *l ;
4211     symbol *lbl ;
4212
4213     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4214     /* signed or unsigned */
4215     if (SPEC_USIGN(opetype)) {
4216         /* unsigned is easy */
4217         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4218         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4219         MOVA(l);    
4220         pic16_emitcode("div","ab");
4221         pic16_aopPut(AOP(result),"b",0);
4222         return ;
4223     }
4224
4225     /* signed is a little bit more difficult */
4226
4227     /* save the signs of the operands */
4228     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4229     MOVA(l);
4230
4231     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4232     pic16_emitcode("push","acc"); /* save it on the stack */
4233
4234     /* now sign adjust for both left & right */
4235     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4236     MOVA(l);
4237
4238     lbl = newiTempLabel(NULL);
4239     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4240     pic16_emitcode("cpl","a");   
4241     pic16_emitcode("inc","a");
4242     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4243     pic16_emitcode("mov","b,a"); 
4244
4245     /* sign adjust left side */
4246     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4247     MOVA(l);
4248
4249     lbl = newiTempLabel(NULL);
4250     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4251     pic16_emitcode("cpl","a");   
4252     pic16_emitcode("inc","a");
4253     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4254
4255     /* now the multiplication */
4256     pic16_emitcode("div","ab");
4257     /* we are interested in the lower order
4258     only */
4259     lbl = newiTempLabel(NULL);
4260     pic16_emitcode("pop","acc");   
4261     /* if there was an over flow we don't 
4262     adjust the sign of the result */
4263     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4264     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4265     CLRC ;
4266     pic16_emitcode("clr","a");
4267     pic16_emitcode("subb","a,b");
4268     pic16_emitcode("mov","b,a");
4269     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4270
4271     /* now we are done */
4272     pic16_aopPut(AOP(result),"b",0);
4273
4274 }
4275
4276 /*-----------------------------------------------------------------*/
4277 /* genMod - generates code for division                            */
4278 /*-----------------------------------------------------------------*/
4279 static void genMod (iCode *ic)
4280 {
4281     operand *left = IC_LEFT(ic);
4282     operand *right = IC_RIGHT(ic);
4283     operand *result= IC_RESULT(ic);  
4284
4285     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4286     /* assign the amsops */
4287     pic16_aopOp (left,ic,FALSE);
4288     pic16_aopOp (right,ic,FALSE);
4289     pic16_aopOp (result,ic,TRUE);
4290
4291     /* special cases first */
4292     /* both are bits */
4293     if (AOP_TYPE(left) == AOP_CRY &&
4294         AOP_TYPE(right)== AOP_CRY) {
4295         genModbits(left,right,result);
4296         goto release ;
4297     }
4298
4299     /* if both are of size == 1 */
4300     if (AOP_SIZE(left) == 1 &&
4301         AOP_SIZE(right) == 1 ) {
4302         genModOneByte(left,right,result);
4303         goto release ;
4304     }
4305
4306     /* should have been converted to function call */
4307     assert(0);
4308
4309 release :
4310     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4311     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4312     pic16_freeAsmop(result,NULL,ic,TRUE); 
4313 }
4314
4315 /*-----------------------------------------------------------------*/
4316 /* genIfxJump :- will create a jump depending on the ifx           */
4317 /*-----------------------------------------------------------------*/
4318 /*
4319   note: May need to add parameter to indicate when a variable is in bit space.
4320 */
4321 static void genIfxJump (iCode *ic, char *jval)
4322 {
4323
4324     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4325     /* if true label then we jump if condition
4326     supplied is true */
4327     if ( IC_TRUE(ic) ) {
4328
4329         if(strcmp(jval,"a") == 0)
4330           emitSKPZ;
4331         else if (strcmp(jval,"c") == 0)
4332           emitSKPC;
4333         else {
4334           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4335           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
4336         }
4337
4338         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4339         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4340
4341     }
4342     else {
4343         /* false label is present */
4344         if(strcmp(jval,"a") == 0)
4345           emitSKPNZ;
4346         else if (strcmp(jval,"c") == 0)
4347           emitSKPNC;
4348         else {
4349           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4350           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
4351         }
4352
4353         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4354         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4355
4356     }
4357
4358
4359     /* mark the icode as generated */
4360     ic->generated = 1;
4361 }
4362
4363 #if 0
4364 // not needed ATM
4365
4366 /*-----------------------------------------------------------------*/
4367 /* genSkip                                                         */
4368 /*-----------------------------------------------------------------*/
4369 static void genSkip(iCode *ifx,int status_bit)
4370 {
4371   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4372   if(!ifx)
4373     return;
4374
4375   if ( IC_TRUE(ifx) ) {
4376     switch(status_bit) {
4377     case 'z':
4378       emitSKPNZ;
4379       break;
4380
4381     case 'c':
4382       emitSKPNC;
4383       break;
4384
4385     case 'd':
4386       emitSKPDC;
4387       break;
4388
4389     }
4390
4391     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4392     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4393
4394   } else {
4395
4396     switch(status_bit) {
4397
4398     case 'z':
4399       emitSKPZ;
4400       break;
4401
4402     case 'c':
4403       emitSKPC;
4404       break;
4405
4406     case 'd':
4407       emitSKPDC;
4408       break;
4409     }
4410     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4411     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4412
4413   }
4414
4415 }
4416 #endif
4417
4418 /*-----------------------------------------------------------------*/
4419 /* genSkipc                                                        */
4420 /*-----------------------------------------------------------------*/
4421 static void genSkipc(resolvedIfx *rifx)
4422 {
4423   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4424   
4425   if(!rifx)
4426     return;
4427
4428   if(rifx->condition)
4429     emitSKPC;
4430   else
4431     emitSKPNC;
4432
4433   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4434   rifx->generated = 1;
4435 }
4436
4437 /*-----------------------------------------------------------------*/
4438 /* genSkipz2                                                       */
4439 /*-----------------------------------------------------------------*/
4440 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4441 {
4442   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4443   
4444   if(!rifx)
4445     return;
4446
4447   if( (rifx->condition ^ invert_condition) & 1)
4448     emitSKPZ;
4449   else
4450     emitSKPNZ;
4451
4452   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4453   rifx->generated = 1;
4454 }
4455
4456 #if 0
4457 /*-----------------------------------------------------------------*/
4458 /* genSkipz                                                        */
4459 /*-----------------------------------------------------------------*/
4460 static void genSkipz(iCode *ifx, int condition)
4461 {
4462   if(!ifx)
4463     return;
4464
4465   if(condition)
4466     emitSKPNZ;
4467   else
4468     emitSKPZ;
4469
4470   if ( IC_TRUE(ifx) )
4471     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4472   else
4473     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4474
4475   if ( IC_TRUE(ifx) )
4476     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4477   else
4478     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4479
4480 }
4481 #endif
4482
4483 /*-----------------------------------------------------------------*/
4484 /* genSkipCond                                                     */
4485 /*-----------------------------------------------------------------*/
4486 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4487 {
4488   if(!rifx)
4489     return;
4490
4491   if(rifx->condition)
4492     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4493   else
4494     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4495
4496
4497   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4498   rifx->generated = 1;
4499 }
4500
4501 #if 0
4502 /*-----------------------------------------------------------------*/
4503 /* genChkZeroes :- greater or less than comparison                 */
4504 /*     For each byte in a literal that is zero, inclusive or the   */
4505 /*     the corresponding byte in the operand with W                */
4506 /*     returns true if any of the bytes are zero                   */
4507 /*-----------------------------------------------------------------*/
4508 static int genChkZeroes(operand *op, int lit,  int size)
4509 {
4510
4511   int i;
4512   int flag =1;
4513
4514   while(size--) {
4515     i = (lit >> (size*8)) & 0xff;
4516
4517     if(i==0) {
4518       if(flag) 
4519         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4520       else
4521         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4522       flag = 0;
4523     }
4524   }
4525
4526   return (flag==0);
4527 }
4528 #endif
4529
4530 /*-----------------------------------------------------------------*/
4531 /* genCmp :- greater or less than comparison                       */
4532 /*-----------------------------------------------------------------*/
4533 static void genCmp (operand *left,operand *right,
4534                     operand *result, iCode *ifx, int sign)
4535 {
4536   int size; //, offset = 0 ;
4537   unsigned long lit = 0L,i = 0;
4538   resolvedIfx rFalseIfx;
4539   //  resolvedIfx rTrueIfx;
4540   symbol *truelbl;
4541   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4542 /*
4543   if(ifx) {
4544     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4545     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4546   }
4547 */
4548
4549   resolveIfx(&rFalseIfx,ifx);
4550   truelbl  = newiTempLabel(NULL);
4551   size = max(AOP_SIZE(left),AOP_SIZE(right));
4552
4553   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4554
4555 #define _swapp
4556
4557   /* if literal is on the right then swap with left */
4558   if ((AOP_TYPE(right) == AOP_LIT)) {
4559     operand *tmp = right ;
4560     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4561     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4562 #ifdef _swapp
4563
4564     lit = (lit - 1) & mask;
4565     right = left;
4566     left = tmp;
4567     rFalseIfx.condition ^= 1;
4568 #endif
4569
4570   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4571     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4572   }
4573
4574
4575   //if(IC_TRUE(ifx) == NULL)
4576   /* if left & right are bit variables */
4577   if (AOP_TYPE(left) == AOP_CRY &&
4578       AOP_TYPE(right) == AOP_CRY ) {
4579     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4580     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4581   } else {
4582     /* subtract right from left if at the
4583        end the carry flag is set then we know that
4584        left is greater than right */
4585
4586     symbol *lbl  = newiTempLabel(NULL);
4587
4588 #if 0
4589         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4590                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+labelOffset, lbl->key+100+labelOffset);
4591 #endif
4592
4593 #ifndef _swapp
4594     if(AOP_TYPE(right) == AOP_LIT) {
4595
4596       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4597
4598       DEBUGpic16_emitcode(";right lit","%d lit = 0x%x,sign=%d",__LINE__, lit,sign);
4599
4600       /* special cases */
4601
4602       if(lit == 0) {
4603
4604         if(sign != 0) 
4605           genSkipCond(&rFalseIfx,left,size-1,7);
4606         else 
4607           /* no need to compare to 0...*/
4608           /* NOTE: this is a de-generate compare that most certainly 
4609            *       creates some dead code. */
4610           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4611
4612         if(ifx) ifx->generated = 1;
4613         return;
4614
4615       }
4616       size--;
4617
4618       if(size == 0) {
4619         //i = (lit >> (size*8)) & 0xff;
4620         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4621         
4622         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4623
4624         i = ((0-lit) & 0xff);
4625         if(sign) {
4626           if( i == 0x81) { 
4627             /* lit is 0x7f, all signed chars are less than
4628              * this except for 0x7f itself */
4629             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4630             genSkipz2(&rFalseIfx,0);
4631           } else {
4632             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4633             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4634             genSkipc(&rFalseIfx);
4635           }
4636
4637         } else {
4638           if(lit == 1) {
4639             genSkipz2(&rFalseIfx,1);
4640           } else {
4641             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4642             genSkipc(&rFalseIfx);
4643           }
4644         }
4645
4646         if(ifx) ifx->generated = 1;
4647         return;
4648       }
4649
4650       /* chars are out of the way. now do ints and longs */
4651
4652
4653       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4654         
4655       /* special cases */
4656
4657       if(sign) {
4658
4659         if(lit == 0) {
4660           genSkipCond(&rFalseIfx,left,size,7);
4661           if(ifx) ifx->generated = 1;
4662           return;
4663         }
4664
4665         if(lit <0x100) {
4666           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4667
4668           //rFalseIfx.condition ^= 1;
4669           //genSkipCond(&rFalseIfx,left,size,7);
4670           //rFalseIfx.condition ^= 1;
4671
4672           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4673           if(rFalseIfx.condition)
4674             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4675           else
4676             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4677
4678           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4679           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4680           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4681
4682           while(size > 1)
4683             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4684
4685           if(rFalseIfx.condition) {
4686             emitSKPZ;
4687             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4688
4689           } else {
4690             emitSKPNZ;
4691           }
4692
4693           genSkipc(&rFalseIfx);
4694           pic16_emitpLabel(truelbl->key);
4695           if(ifx) ifx->generated = 1;
4696           return;
4697
4698         }
4699
4700         if(size == 1) {
4701
4702           if( (lit & 0xff) == 0) {
4703             /* lower byte is zero */
4704             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4705             i = ((lit >> 8) & 0xff) ^0x80;
4706             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4707             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4708             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4709             genSkipc(&rFalseIfx);
4710
4711
4712             if(ifx) ifx->generated = 1;
4713             return;
4714
4715           }
4716         } else {
4717           /* Special cases for signed longs */
4718           if( (lit & 0xffffff) == 0) {
4719             /* lower byte is zero */
4720             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4721             i = ((lit >> 8*3) & 0xff) ^0x80;
4722             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4723             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4724             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4725             genSkipc(&rFalseIfx);
4726
4727
4728             if(ifx) ifx->generated = 1;
4729             return;
4730
4731           }
4732
4733         }
4734
4735
4736         if(lit & (0x80 << (size*8))) {
4737           /* lit is negative */
4738           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4739
4740           //genSkipCond(&rFalseIfx,left,size,7);
4741
4742           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4743
4744           if(rFalseIfx.condition)
4745             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4746           else
4747             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4748
4749
4750         } else {
4751           /* lit is positive */
4752           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4753           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4754           if(rFalseIfx.condition)
4755             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4756           else
4757             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4758
4759         }
4760
4761         /*
4762           This works, but is only good for ints.
4763           It also requires a "known zero" register.
4764           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4765           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4766           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4767           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4768           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4769           genSkipc(&rFalseIfx);
4770
4771           pic16_emitpLabel(truelbl->key);
4772           if(ifx) ifx->generated = 1;
4773           return;
4774         **/
4775           
4776         /* There are no more special cases, so perform a general compare */
4777   
4778         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4779         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4780
4781         while(size--) {
4782
4783           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4784           emitSKPNZ;
4785           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4786         }
4787         //rFalseIfx.condition ^= 1;
4788         genSkipc(&rFalseIfx);
4789
4790         pic16_emitpLabel(truelbl->key);
4791
4792         if(ifx) ifx->generated = 1;
4793         return;
4794
4795
4796       }
4797
4798
4799       /* sign is out of the way. So now do an unsigned compare */
4800       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4801
4802
4803       /* General case - compare to an unsigned literal on the right.*/
4804
4805       i = (lit >> (size*8)) & 0xff;
4806       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4807       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4808       while(size--) {
4809         i = (lit >> (size*8)) & 0xff;
4810
4811         if(i) {
4812           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4813           emitSKPNZ;
4814           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4815         } else {
4816           /* this byte of the lit is zero, 
4817            *if it's not the last then OR in the variable */
4818           if(size)
4819             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4820         }
4821       }
4822
4823
4824       pic16_emitpLabel(lbl->key);
4825 //      pic16_emitpLabel(truelbl->key);
4826       //if(emitFinalCheck)
4827       genSkipc(&rFalseIfx);
4828       if(sign)
4829         pic16_emitpLabel(truelbl->key);
4830
4831       if(ifx) ifx->generated = 1;
4832       return;
4833
4834
4835     }
4836 #endif  // _swapp
4837
4838     if(AOP_TYPE(left) == AOP_LIT) {
4839       //symbol *lbl = newiTempLabel(NULL);
4840
4841       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4842
4843
4844       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4845
4846       /* Special cases */
4847       if((lit == 0) && (sign == 0)){
4848
4849         size--;
4850         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4851         while(size) 
4852           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4853
4854         genSkipz2(&rFalseIfx,0);
4855         if(ifx) ifx->generated = 1;
4856         return;
4857       }
4858
4859       if(size==1) {
4860         /* Special cases */
4861         lit &= 0xff;
4862         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4863           /* degenerate compare can never be true */
4864           if(rFalseIfx.condition == 0)
4865             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4866
4867           if(ifx) ifx->generated = 1;
4868           return;
4869         }
4870
4871         if(sign) {
4872           /* signed comparisons to a literal byte */
4873
4874           int lp1 = (lit+1) & 0xff;
4875
4876           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4877           switch (lp1) {
4878           case 0:
4879             rFalseIfx.condition ^= 1;
4880             genSkipCond(&rFalseIfx,right,0,7);
4881             break;
4882           case 0x7f:
4883             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4884             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4885             genSkipz2(&rFalseIfx,1);
4886             break;
4887           default:
4888             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4889             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4890             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4891             rFalseIfx.condition ^= 1;
4892             genSkipc(&rFalseIfx);
4893             break;
4894           }
4895         } else {
4896           /* unsigned comparisons to a literal byte */
4897
4898           switch(lit & 0xff ) {
4899           case 0:
4900             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4901             genSkipz2(&rFalseIfx,0);
4902             break;
4903           case 0x7f:
4904             rFalseIfx.condition ^= 1;
4905             genSkipCond(&rFalseIfx,right,0,7);
4906             break;
4907
4908           default:
4909             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4910             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4911             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4912             rFalseIfx.condition ^= 1;
4913             if (AOP_TYPE(result) == AOP_CRY)
4914               genSkipc(&rFalseIfx);
4915             else {
4916               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4917               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4918             }         
4919             break;
4920           }
4921         }
4922
4923         if(ifx) ifx->generated = 1;
4924         goto check_carry;
4925 //      return;
4926
4927       } else {
4928
4929         /* Size is greater than 1 */
4930
4931         if(sign) {
4932           int lp1 = lit+1;
4933
4934           size--;
4935
4936           if(lp1 == 0) {
4937             /* this means lit = 0xffffffff, or -1 */
4938
4939
4940             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4941             rFalseIfx.condition ^= 1;
4942             genSkipCond(&rFalseIfx,right,size,7);
4943             if(ifx) ifx->generated = 1;
4944             return;
4945           }
4946
4947           if(lit == 0) {
4948             int s = size;
4949
4950             if(rFalseIfx.condition) {
4951               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4952               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4953             }
4954
4955             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4956             while(size--)
4957               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4958
4959
4960             emitSKPZ;
4961             if(rFalseIfx.condition) {
4962               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4963               pic16_emitpLabel(truelbl->key);
4964             }else {
4965               rFalseIfx.condition ^= 1;
4966               genSkipCond(&rFalseIfx,right,s,7);
4967             }
4968
4969             if(ifx) ifx->generated = 1;
4970             return;
4971           }
4972
4973           if((size == 1) &&  (0 == (lp1&0xff))) {
4974             /* lower byte of signed word is zero */
4975             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4976             i = ((lp1 >> 8) & 0xff) ^0x80;
4977             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4978             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4979             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4980             rFalseIfx.condition ^= 1;
4981             genSkipc(&rFalseIfx);
4982
4983
4984             if(ifx) ifx->generated = 1;
4985             return;
4986           }
4987
4988           if(lit & (0x80 << (size*8))) {
4989             /* Lit is less than zero */
4990             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4991             //rFalseIfx.condition ^= 1;
4992             //genSkipCond(&rFalseIfx,left,size,7);
4993             //rFalseIfx.condition ^= 1;
4994             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4995             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4996
4997             if(rFalseIfx.condition)
4998               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4999             else
5000               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5001
5002
5003           } else {
5004             /* Lit is greater than or equal to zero */
5005             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
5006             //rFalseIfx.condition ^= 1;
5007             //genSkipCond(&rFalseIfx,right,size,7);
5008             //rFalseIfx.condition ^= 1;
5009
5010             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5011             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5012
5013             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
5014             if(rFalseIfx.condition)
5015               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5016             else
5017               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5018
5019           }
5020
5021
5022           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5023           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5024
5025           while(size--) {
5026
5027             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
5028             emitSKPNZ;
5029             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5030           }
5031           rFalseIfx.condition ^= 1;
5032           //rFalseIfx.condition = 1;
5033           genSkipc(&rFalseIfx);
5034
5035           pic16_emitpLabel(truelbl->key);
5036
5037           if(ifx) ifx->generated = 1;
5038           return;
5039           // end of if (sign)
5040         } else {
5041
5042           /* compare word or long to an unsigned literal on the right.*/
5043
5044
5045           size--;
5046           if(lit < 0xff) {
5047             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5048             switch (lit) {
5049             case 0:
5050               break; /* handled above */
5051 /*
5052             case 0xff:
5053               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5054               while(size--)
5055                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5056               genSkipz2(&rFalseIfx,0);
5057               break;
5058 */
5059             default:
5060               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5061               while(--size)
5062                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5063
5064               emitSKPZ;
5065               if(rFalseIfx.condition)
5066                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5067               else
5068                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5069
5070
5071               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5072               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5073
5074               rFalseIfx.condition ^= 1;
5075               genSkipc(&rFalseIfx);
5076             }
5077
5078             pic16_emitpLabel(truelbl->key);
5079
5080             if(ifx) ifx->generated = 1;
5081             return;
5082           }
5083
5084
5085           lit++;
5086           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5087           i = (lit >> (size*8)) & 0xff;
5088
5089           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5090           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5091
5092           while(size--) {
5093             i = (lit >> (size*8)) & 0xff;
5094
5095             if(i) {
5096               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5097               emitSKPNZ;
5098               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5099             } else {
5100               /* this byte of the lit is zero, 
5101                * if it's not the last then OR in the variable */
5102               if(size)
5103                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5104             }
5105           }
5106
5107
5108           pic16_emitpLabel(lbl->key);
5109
5110           rFalseIfx.condition ^= 1;
5111
5112           genSkipc(&rFalseIfx);
5113         }
5114
5115         if(sign)
5116           pic16_emitpLabel(truelbl->key);
5117         if(ifx) ifx->generated = 1;
5118         return;
5119       }
5120     }
5121     /* Compare two variables */
5122
5123     DEBUGpic16_emitcode(";sign","%d",sign);
5124
5125     size--;
5126     if(sign) {
5127       /* Sigh. thus sucks... */
5128       if(size) {
5129         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5130         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5131         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5132         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5133         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5134         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5135       } else {
5136         /* Signed char comparison */
5137         /* Special thanks to Nikolai Golovchenko for this snippet */
5138         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5139         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5140         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5141         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5142         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5143         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5144
5145         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5146         genSkipc(&rFalseIfx);
5147           
5148         if(ifx) ifx->generated = 1;
5149         return;
5150       }
5151
5152     } else {
5153
5154       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5155       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5156     }
5157
5158
5159     /* The rest of the bytes of a multi-byte compare */
5160     while (size) {
5161
5162       emitSKPZ;
5163       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5164       size--;
5165
5166       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5167       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5168
5169
5170     }
5171
5172     pic16_emitpLabel(lbl->key);
5173
5174     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5175     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5176         (AOP_TYPE(result) == AOP_REG)) {
5177       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5178       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5179     } else {
5180       genSkipc(&rFalseIfx);
5181     }         
5182     //genSkipc(&rFalseIfx);
5183     if(ifx) ifx->generated = 1;
5184
5185     return;
5186
5187   }
5188
5189 check_carry:
5190   if ((AOP_TYPE(result) != AOP_CRY) 
5191         && AOP_SIZE(result)) {
5192     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5193 //    pic16_emitpLabel( rFalseIfx.lbl->key );
5194
5195     pic16_outBitC(result);
5196   } else {
5197     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5198     /* if the result is used in the next
5199        ifx conditional branch then generate
5200        code a little differently */
5201     if (ifx )
5202       genIfxJump (ifx,"c");
5203     else
5204       pic16_outBitC(result);
5205     /* leave the result in acc */
5206   }
5207
5208 }
5209
5210 /*-----------------------------------------------------------------*/
5211 /* genCmpGt :- greater than comparison                             */
5212 /*-----------------------------------------------------------------*/
5213 static void genCmpGt (iCode *ic, iCode *ifx)
5214 {
5215     operand *left, *right, *result;
5216     sym_link *letype , *retype;
5217     int sign ;
5218
5219     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5220     left = IC_LEFT(ic);
5221     right= IC_RIGHT(ic);
5222     result = IC_RESULT(ic);
5223
5224     letype = getSpec(operandType(left));
5225     retype =getSpec(operandType(right));
5226     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5227     /* assign the amsops */
5228     pic16_aopOp (left,ic,FALSE);
5229     pic16_aopOp (right,ic,FALSE);
5230     pic16_aopOp (result,ic,TRUE);
5231
5232     genCmp(right, left, result, ifx, sign);
5233
5234     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5235     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5236     pic16_freeAsmop(result,NULL,ic,TRUE); 
5237 }
5238
5239 /*-----------------------------------------------------------------*/
5240 /* genCmpLt - less than comparisons                                */
5241 /*-----------------------------------------------------------------*/
5242 static void genCmpLt (iCode *ic, iCode *ifx)
5243 {
5244     operand *left, *right, *result;
5245     sym_link *letype , *retype;
5246     int sign ;
5247
5248     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5249     left = IC_LEFT(ic);
5250     right= IC_RIGHT(ic);
5251     result = IC_RESULT(ic);
5252
5253     letype = getSpec(operandType(left));
5254     retype =getSpec(operandType(right));
5255     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5256
5257     /* assign the amsops */
5258     pic16_aopOp (left,ic,FALSE);
5259     pic16_aopOp (right,ic,FALSE);
5260     pic16_aopOp (result,ic,TRUE);
5261
5262     genCmp(left, right, result, ifx, sign);
5263
5264     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5265     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5266     pic16_freeAsmop(result,NULL,ic,TRUE); 
5267 }
5268
5269 #if 0
5270 // not needed ATM
5271 // FIXME reenable literal optimisation when the pic16 port is stable
5272
5273 /*-----------------------------------------------------------------*/
5274 /* genc16bit2lit - compare a 16 bit value to a literal             */
5275 /*-----------------------------------------------------------------*/
5276 static void genc16bit2lit(operand *op, int lit, int offset)
5277 {
5278   int i;
5279
5280   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5281   if( (lit&0xff) == 0) 
5282     i=1;
5283   else
5284     i=0;
5285
5286   switch( BYTEofLONG(lit,i)) { 
5287   case 0:
5288     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5289     break;
5290   case 1:
5291     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5292     break;
5293   case 0xff:
5294     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5295     break;
5296   default:
5297     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5298     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5299   }
5300
5301   i ^= 1;
5302
5303   switch( BYTEofLONG(lit,i)) { 
5304   case 0:
5305     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5306     break;
5307   case 1:
5308     emitSKPNZ;
5309     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5310     break;
5311   case 0xff:
5312     emitSKPNZ;
5313     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5314     break;
5315   default:
5316     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5317     emitSKPNZ;
5318     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5319
5320   }
5321
5322 }
5323 #endif
5324
5325 #if 0
5326 // not needed ATM
5327 /*-----------------------------------------------------------------*/
5328 /* gencjneshort - compare and jump if not equal                    */
5329 /*-----------------------------------------------------------------*/
5330 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5331 {
5332   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5333   int offset = 0;
5334   int res_offset = 0;  /* the result may be a different size then left or right */
5335   int res_size = AOP_SIZE(result);
5336   resolvedIfx rIfx;
5337   symbol *lbl, *lbl_done;
5338
5339   unsigned long lit = 0L;
5340   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5341
5342   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5343   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5344   if(result)
5345     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5346   resolveIfx(&rIfx,ifx);
5347   lbl =  newiTempLabel(NULL);
5348   lbl_done =  newiTempLabel(NULL);
5349
5350
5351   /* if the left side is a literal or 
5352      if the right is in a pointer register and left 
5353      is not */
5354   if ((AOP_TYPE(left) == AOP_LIT) || 
5355       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5356     operand *t = right;
5357     right = left;
5358     left = t;
5359   }
5360   if(AOP_TYPE(right) == AOP_LIT)
5361     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5362
5363   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5364     preserve_result = 1;
5365
5366   if(result && !preserve_result)
5367     {
5368       int i;
5369       for(i = 0; i < AOP_SIZE(result); i++)
5370         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5371     }
5372
5373
5374   /* if the right side is a literal then anything goes */
5375   if (AOP_TYPE(right) == AOP_LIT &&
5376       AOP_TYPE(left) != AOP_DIR ) {
5377     switch(size) {
5378     case 2:
5379       genc16bit2lit(left, lit, 0);
5380       emitSKPZ;
5381       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5382       break;
5383     default:
5384       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5385       while (size--) {
5386         if(lit & 0xff) {
5387           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5388           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5389         } else {
5390           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5391         }
5392
5393         emitSKPZ;
5394         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5395         offset++;
5396         if(res_offset < res_size-1)
5397           res_offset++;
5398         lit >>= 8;
5399       }
5400       break;
5401     }
5402   }
5403
5404   /* if the right side is in a register or in direct space or
5405      if the left is a pointer register & right is not */    
5406   else if (AOP_TYPE(right) == AOP_REG ||
5407            AOP_TYPE(right) == AOP_DIR || 
5408            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5409            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5410     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5411     int lbl_key = lbl->key;
5412
5413     if(result) {
5414       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5415       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5416     }else {
5417       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5418       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5419               __FUNCTION__,__LINE__);
5420       return;
5421     }
5422    
5423 /*     switch(size) { */
5424 /*     case 2: */
5425 /*       genc16bit2lit(left, lit, 0); */
5426 /*       emitSKPNZ; */
5427 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5428 /*       break; */
5429 /*     default: */
5430     while (size--) {
5431       int emit_skip=1;
5432       if((AOP_TYPE(left) == AOP_DIR) && 
5433          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5434
5435         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5436         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5437
5438       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5439             
5440         switch (lit & 0xff) {
5441         case 0:
5442           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5443           break;
5444         case 1:
5445           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5446           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5447           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5448           emit_skip=0;
5449           break;
5450         case 0xff:
5451           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5452           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5453           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5454           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5455           emit_skip=0;
5456           break;
5457         default:
5458           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5459           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5460         }
5461         lit >>= 8;
5462
5463       } else {
5464         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5465       }
5466       if(emit_skip) {
5467         if(AOP_TYPE(result) == AOP_CRY) {
5468           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5469           if(rIfx.condition)
5470             emitSKPNZ;
5471           else
5472             emitSKPZ;
5473           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5474         } else {
5475           /* fix me. probably need to check result size too */
5476           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5477           if(rIfx.condition)
5478             emitSKPZ;
5479           else
5480             emitSKPNZ;
5481           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5482           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5483         }
5484         if(ifx)
5485           ifx->generated=1;
5486       }
5487       emit_skip++;
5488       offset++;
5489       if(res_offset < res_size-1)
5490         res_offset++;
5491     }
5492 /*       break; */
5493 /*     } */
5494   } else if(AOP_TYPE(right) == AOP_REG &&
5495             AOP_TYPE(left) != AOP_DIR){
5496
5497     while(size--) {
5498       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5499       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5500       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5501       if(rIfx.condition)
5502         emitSKPNZ;
5503       else
5504         emitSKPZ;
5505       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5506       offset++;
5507       if(res_offset < res_size-1)
5508         res_offset++;
5509     }
5510       
5511   }else{
5512     /* right is a pointer reg need both a & b */
5513     while(size--) {
5514       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5515       if(strcmp(l,"b"))
5516         pic16_emitcode("mov","b,%s",l);
5517       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5518       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5519       offset++;
5520     }
5521   }
5522
5523   if(result && preserve_result)
5524     {
5525       int i;
5526       for(i = 0; i < AOP_SIZE(result); i++)
5527         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5528     }
5529
5530   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5531
5532   if(result && preserve_result)
5533     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5534
5535   if(!rIfx.condition)
5536     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5537
5538   pic16_emitpLabel(lbl->key);
5539
5540   if(result && preserve_result)
5541     {
5542       int i;
5543       for(i = 0; i < AOP_SIZE(result); i++)
5544         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5545
5546       pic16_emitpLabel(lbl_done->key);
5547    }
5548
5549   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5550
5551   if(ifx)
5552     ifx->generated = 1;
5553 }
5554 #endif
5555
5556 #if 0
5557 /*-----------------------------------------------------------------*/
5558 /* gencjne - compare and jump if not equal                         */
5559 /*-----------------------------------------------------------------*/
5560 static void gencjne(operand *left, operand *right, iCode *ifx)
5561 {
5562     symbol *tlbl  = newiTempLabel(NULL);
5563
5564     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5565     gencjneshort(left, right, lbl);
5566
5567     pic16_emitcode("mov","a,%s",one);
5568     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5569     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5570     pic16_emitcode("clr","a");
5571     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5572
5573     pic16_emitpLabel(lbl->key);
5574     pic16_emitpLabel(tlbl->key);
5575
5576 }
5577 #endif
5578
5579
5580 /*-----------------------------------------------------------------*/
5581 /* is_LitOp - check if operand has to be treated as literal        */
5582 /*-----------------------------------------------------------------*/
5583 static bool is_LitOp(operand *op)
5584 {
5585   return (AOP_TYPE(op) == AOP_LIT)
5586       || ( (AOP_TYPE(op) == AOP_PCODE)
5587           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5588               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5589 }
5590
5591
5592 /*-----------------------------------------------------------------*/
5593 /* genCmpEq - generates code for equal to                          */
5594 /*-----------------------------------------------------------------*/
5595 static void genCmpEq (iCode *ic, iCode *ifx)
5596 {
5597   operand *left, *right, *result;
5598   symbol *falselbl = newiTempLabel(NULL);
5599   symbol *donelbl = newiTempLabel(NULL);
5600
5601   int preserve_result = 0;
5602   int generate_result = 0;
5603   int i=0;
5604
5605   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5606   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5607   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5608  
5609   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5610   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5611
5612   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5613     {
5614       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5615       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5616       goto release;
5617     }
5618
5619   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5620     {
5621       operand *tmp = right ;
5622       right = left;
5623       left = tmp;
5624     }
5625
5626   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5627     preserve_result = 1;
5628
5629   if(result && AOP_SIZE(result))
5630     generate_result = 1;
5631
5632   if(generate_result && !preserve_result)
5633     {
5634       for(i = 0; i < AOP_SIZE(result); i++)
5635         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5636     }
5637
5638   for(i=0; i < AOP_SIZE(left); i++)
5639     {
5640       if(AOP_TYPE(left) != AOP_ACC)
5641         {
5642           if(is_LitOp(left))
5643             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5644           else
5645             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5646         }
5647       if(is_LitOp(right))
5648         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5649       else
5650         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5651
5652       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5653     }
5654
5655   // result == true
5656
5657   if(generate_result && preserve_result)
5658     {
5659       for(i = 0; i < AOP_SIZE(result); i++)
5660         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5661     }
5662
5663   if(generate_result)
5664     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5665
5666   if(generate_result && preserve_result)
5667     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5668
5669   if(ifx && IC_TRUE(ifx))
5670     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5671
5672   if(ifx && IC_FALSE(ifx))
5673     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5674
5675   pic16_emitpLabel(falselbl->key);
5676
5677   // result == false
5678
5679   if(ifx && IC_FALSE(ifx))
5680     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5681
5682   if(generate_result && preserve_result)
5683     {
5684       for(i = 0; i < AOP_SIZE(result); i++)
5685         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5686     }
5687
5688   pic16_emitpLabel(donelbl->key);
5689
5690   if(ifx)
5691     ifx->generated = 1;
5692
5693 release:
5694   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5695   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5696   pic16_freeAsmop(result,NULL,ic,TRUE);
5697
5698 }
5699
5700
5701 #if 0
5702 // old version kept for reference
5703
5704 /*-----------------------------------------------------------------*/
5705 /* genCmpEq - generates code for equal to                          */
5706 /*-----------------------------------------------------------------*/
5707 static void genCmpEq (iCode *ic, iCode *ifx)
5708 {
5709     operand *left, *right, *result;
5710     unsigned long lit = 0L;
5711     int size,offset=0;
5712     symbol *falselbl  = newiTempLabel(NULL);
5713
5714
5715     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5716
5717     if(ifx)
5718       DEBUGpic16_emitcode ("; ifx is non-null","");
5719     else
5720       DEBUGpic16_emitcode ("; ifx is null","");
5721
5722     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5723     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5724     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5725
5726     size = max(AOP_SIZE(left),AOP_SIZE(right));
5727
5728     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5729
5730     /* if literal, literal on the right or 
5731     if the right is in a pointer register and left 
5732     is not */
5733     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5734         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5735       operand *tmp = right ;
5736       right = left;
5737       left = tmp;
5738     }
5739
5740
5741     if(ifx && !AOP_SIZE(result)){
5742         symbol *tlbl;
5743         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5744         /* if they are both bit variables */
5745         if (AOP_TYPE(left) == AOP_CRY &&
5746             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5747                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5748             if(AOP_TYPE(right) == AOP_LIT){
5749                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5750                 if(lit == 0L){
5751                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5752                     pic16_emitcode("cpl","c");
5753                 } else if(lit == 1L) {
5754                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5755                 } else {
5756                     pic16_emitcode("clr","c");
5757                 }
5758                 /* AOP_TYPE(right) == AOP_CRY */
5759             } else {
5760                 symbol *lbl = newiTempLabel(NULL);
5761                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5762                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5763                 pic16_emitcode("cpl","c");
5764                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5765             }
5766             /* if true label then we jump if condition
5767             supplied is true */
5768             tlbl = newiTempLabel(NULL);
5769             if ( IC_TRUE(ifx) ) {
5770                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5771                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5772             } else {
5773                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5774                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5775             }
5776             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5777
5778                 {
5779                 /* left and right are both bit variables, result is carry */
5780                         resolvedIfx rIfx;
5781               
5782                         resolveIfx(&rIfx,ifx);
5783
5784                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5785                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5786                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5787                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5788                         genSkipz2(&rIfx,0);
5789                 }
5790         } else {
5791
5792                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5793
5794                         /* They're not both bit variables. Is the right a literal? */
5795                         if(AOP_TYPE(right) == AOP_LIT) {
5796                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5797             
5798                         switch(size) {
5799
5800                                 case 1:
5801                                         switch(lit & 0xff) {
5802                                                 case 1:
5803                                                                 if ( IC_TRUE(ifx) ) {
5804                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5805                                                                         emitSKPNZ;
5806                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5807                                                                 } else {
5808                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5809                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5810                                                                 }
5811                                                                 break;
5812                                                 case 0xff:
5813                                                                 if ( IC_TRUE(ifx) ) {
5814                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5815                                                                         emitSKPNZ;
5816                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5817                                                                 } else {
5818                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5819                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5820                                                                 }
5821                                                                 break;
5822                                                 default:
5823                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5824                                                                 if(lit)
5825                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5826                                                                 genSkip(ifx,'z');
5827                                         } // switch lit
5828
5829
5830                                         /* end of size == 1 */
5831                                         break;
5832               
5833                                 case 2:
5834                                         genc16bit2lit(left,lit,offset);
5835                                         genSkip(ifx,'z');
5836                                         break;
5837                                         /* end of size == 2 */
5838
5839                                 default:
5840                                         /* size is 4 */
5841                                         if(lit==0) {
5842                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5843                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5844                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5845                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5846                                                 genSkip(ifx,'z');
5847                                         } else {
5848                                                 /* search for patterns that can be optimized */
5849
5850                                                 genc16bit2lit(left,lit,0);
5851                                                 lit >>= 16;
5852                                                 if(lit) {
5853                                                                 if(IC_TRUE(ifx))
5854                                                                 emitSKPZ; // if hi word unequal
5855                                                                 else
5856                                                                 emitSKPNZ; // if hi word equal
5857                                                                 // fail early
5858                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5859                                                         genc16bit2lit(left,lit,2);
5860                                                         genSkip(ifx,'z');
5861                                                 } else {
5862                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5863                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5864                                                         genSkip(ifx,'z');
5865                                                 }
5866                                         }
5867                                                 pic16_emitpLabel(falselbl->key);
5868                                                 break;
5869
5870                         } // switch size
5871           
5872                         ifx->generated = 1;
5873                         goto release ;
5874             
5875
5876           } else if(AOP_TYPE(right) == AOP_CRY ) {
5877             /* we know the left is not a bit, but that the right is */
5878             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5879             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5880                       pic16_popGet(AOP(right),offset));
5881             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5882
5883             /* if the two are equal, then W will be 0 and the Z bit is set
5884              * we could test Z now, or go ahead and check the high order bytes if
5885              * the variable we're comparing is larger than a byte. */
5886
5887             while(--size)
5888               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5889
5890             if ( IC_TRUE(ifx) ) {
5891               emitSKPNZ;
5892               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5893               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5894             } else {
5895               emitSKPZ;
5896               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5897               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5898             }
5899
5900           } else {
5901             /* They're both variables that are larger than bits */
5902             int s = size;
5903
5904             tlbl = newiTempLabel(NULL);
5905
5906             while(size--) {
5907               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5908               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5909
5910               if ( IC_TRUE(ifx) ) {
5911                 if(size) {
5912                   emitSKPZ;
5913                 
5914                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5915
5916                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5917                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5918                 } else {
5919                   emitSKPNZ;
5920
5921                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5922
5923
5924                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5925                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5926                 }
5927               } else {
5928                 emitSKPZ;
5929
5930                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5931
5932                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5933                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5934               }
5935               offset++;
5936             }
5937             if(s>1 && IC_TRUE(ifx)) {
5938               pic16_emitpLabel(tlbl->key);
5939               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5940             }
5941           }
5942         }
5943         /* mark the icode as generated */
5944         ifx->generated = 1;
5945         goto release ;
5946     }
5947
5948     /* if they are both bit variables */
5949     if (AOP_TYPE(left) == AOP_CRY &&
5950         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5951         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5952         if(AOP_TYPE(right) == AOP_LIT){
5953             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5954             if(lit == 0L){
5955                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5956                 pic16_emitcode("cpl","c");
5957             } else if(lit == 1L) {
5958                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5959             } else {
5960                 pic16_emitcode("clr","c");
5961             }
5962             /* AOP_TYPE(right) == AOP_CRY */
5963         } else {
5964             symbol *lbl = newiTempLabel(NULL);
5965             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5966             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5967             pic16_emitcode("cpl","c");
5968             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5969         }
5970         /* c = 1 if egal */
5971         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5972             pic16_outBitC(result);
5973             goto release ;
5974         }
5975         if (ifx) {
5976             genIfxJump (ifx,"c");
5977             goto release ;
5978         }
5979         /* if the result is used in an arithmetic operation
5980         then put the result in place */
5981         pic16_outBitC(result);
5982     } else {
5983       
5984       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5985       gencjne(left,right,result,ifx);
5986 /*
5987       if(ifx) 
5988         gencjne(left,right,newiTempLabel(NULL));
5989       else {
5990         if(IC_TRUE(ifx)->key)
5991           gencjne(left,right,IC_TRUE(ifx)->key);
5992         else
5993           gencjne(left,right,IC_FALSE(ifx)->key);
5994         ifx->generated = 1;
5995         goto release ;
5996       }
5997       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5998         pic16_aopPut(AOP(result),"a",0);
5999         goto release ;
6000       }
6001
6002       if (ifx) {
6003         genIfxJump (ifx,"a");
6004         goto release ;
6005       }
6006 */
6007       /* if the result is used in an arithmetic operation
6008          then put the result in place */
6009 /*
6010       if (AOP_TYPE(result) != AOP_CRY) 
6011         pic16_outAcc(result);
6012 */
6013       /* leave the result in acc */
6014     }
6015
6016 release:
6017     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6018     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6019     pic16_freeAsmop(result,NULL,ic,TRUE);
6020 }
6021 #endif
6022
6023 /*-----------------------------------------------------------------*/
6024 /* ifxForOp - returns the icode containing the ifx for operand     */
6025 /*-----------------------------------------------------------------*/
6026 static iCode *ifxForOp ( operand *op, iCode *ic )
6027 {
6028     /* if true symbol then needs to be assigned */
6029     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6030     if (IS_TRUE_SYMOP(op))
6031         return NULL ;
6032
6033     /* if this has register type condition and
6034     the next instruction is ifx with the same operand
6035     and live to of the operand is upto the ifx only then */
6036     if (ic->next
6037         && ic->next->op == IFX
6038         && IC_COND(ic->next)->key == op->key
6039         && OP_SYMBOL(op)->liveTo <= ic->next->seq
6040         ) {
6041                 DEBUGpic16_emitcode(";", "%d %s", __LINE__, __FUNCTION__);
6042           return ic->next;
6043     }
6044
6045     if (ic->next &&
6046         ic->next->op == IFX &&
6047         IC_COND(ic->next)->key == op->key) {
6048       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6049       return ic->next;
6050     }
6051
6052     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6053     if (ic->next &&
6054         ic->next->op == IFX)
6055       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6056
6057     if (ic->next &&
6058         ic->next->op == IFX &&
6059         IC_COND(ic->next)->key == op->key) {
6060       DEBUGpic16_emitcode ("; "," key is okay");
6061       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6062                            OP_SYMBOL(op)->liveTo,
6063                            ic->next->seq);
6064     }
6065
6066 #if 0
6067     /* the code below is completely untested
6068      * it just allows ulong2fs.c compile -- VR */
6069          
6070     ic = ic->next;
6071     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6072                                         __FILE__, __FUNCTION__, __LINE__);
6073         
6074     /* if this has register type condition and
6075     the next instruction is ifx with the same operand
6076     and live to of the operand is upto the ifx only then */
6077     if (ic->next &&
6078         ic->next->op == IFX &&
6079         IC_COND(ic->next)->key == op->key &&
6080         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6081         return ic->next;
6082
6083     if (ic->next &&
6084         ic->next->op == IFX &&
6085         IC_COND(ic->next)->key == op->key) {
6086       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6087       return ic->next;
6088     }
6089
6090     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6091                                         __FILE__, __FUNCTION__, __LINE__);
6092
6093 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6094 #endif
6095
6096     return NULL;
6097 }
6098 /*-----------------------------------------------------------------*/
6099 /* genAndOp - for && operation                                     */
6100 /*-----------------------------------------------------------------*/
6101 static void genAndOp (iCode *ic)
6102 {
6103     operand *left,*right, *result;
6104 /*     symbol *tlbl; */
6105
6106     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6107     /* note here that && operations that are in an
6108     if statement are taken away by backPatchLabels
6109     only those used in arthmetic operations remain */
6110     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6111     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6112     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6113
6114     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6115
6116     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6117     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6118     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6119
6120     /* if both are bit variables */
6121 /*     if (AOP_TYPE(left) == AOP_CRY && */
6122 /*         AOP_TYPE(right) == AOP_CRY ) { */
6123 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6124 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6125 /*         pic16_outBitC(result); */
6126 /*     } else { */
6127 /*         tlbl = newiTempLabel(NULL); */
6128 /*         pic16_toBoolean(left);     */
6129 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6130 /*         pic16_toBoolean(right); */
6131 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6132 /*         pic16_outBitAcc(result); */
6133 /*     } */
6134
6135     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6136     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6137     pic16_freeAsmop(result,NULL,ic,TRUE);
6138 }
6139
6140
6141 /*-----------------------------------------------------------------*/
6142 /* genOrOp - for || operation                                      */
6143 /*-----------------------------------------------------------------*/
6144 /*
6145   tsd pic port -
6146   modified this code, but it doesn't appear to ever get called
6147 */
6148
6149 static void genOrOp (iCode *ic)
6150 {
6151     operand *left,*right, *result;
6152     symbol *tlbl;
6153
6154     /* note here that || operations that are in an
6155     if statement are taken away by backPatchLabels
6156     only those used in arthmetic operations remain */
6157     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6158     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6159     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6160     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6161
6162     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6163
6164     /* if both are bit variables */
6165     if (AOP_TYPE(left) == AOP_CRY &&
6166         AOP_TYPE(right) == AOP_CRY ) {
6167       pic16_emitcode("clrc","");
6168       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6169                AOP(left)->aopu.aop_dir,
6170                AOP(left)->aopu.aop_dir);
6171       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6172                AOP(right)->aopu.aop_dir,
6173                AOP(right)->aopu.aop_dir);
6174       pic16_emitcode("setc","");
6175
6176     } else {
6177         tlbl = newiTempLabel(NULL);
6178         pic16_toBoolean(left);
6179         emitSKPZ;
6180         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
6181         pic16_toBoolean(right);
6182         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
6183
6184         pic16_outBitAcc(result);
6185     }
6186
6187     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6188     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6189     pic16_freeAsmop(result,NULL,ic,TRUE);            
6190 }
6191
6192 /*-----------------------------------------------------------------*/
6193 /* isLiteralBit - test if lit == 2^n                               */
6194 /*-----------------------------------------------------------------*/
6195 static int isLiteralBit(unsigned long lit)
6196 {
6197     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6198     0x100L,0x200L,0x400L,0x800L,
6199     0x1000L,0x2000L,0x4000L,0x8000L,
6200     0x10000L,0x20000L,0x40000L,0x80000L,
6201     0x100000L,0x200000L,0x400000L,0x800000L,
6202     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6203     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6204     int idx;
6205     
6206     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6207     for(idx = 0; idx < 32; idx++)
6208         if(lit == pw[idx])
6209             return idx+1;
6210     return 0;
6211 }
6212
6213 /*-----------------------------------------------------------------*/
6214 /* continueIfTrue -                                                */
6215 /*-----------------------------------------------------------------*/
6216 static void continueIfTrue (iCode *ic)
6217 {
6218     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6219     if(IC_TRUE(ic))
6220         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6221     ic->generated = 1;
6222 }
6223
6224 /*-----------------------------------------------------------------*/
6225 /* jmpIfTrue -                                                     */
6226 /*-----------------------------------------------------------------*/
6227 static void jumpIfTrue (iCode *ic)
6228 {
6229     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6230     if(!IC_TRUE(ic))
6231         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6232     ic->generated = 1;
6233 }
6234
6235 /*-----------------------------------------------------------------*/
6236 /* jmpTrueOrFalse -                                                */
6237 /*-----------------------------------------------------------------*/
6238 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6239 {
6240     // ugly but optimized by peephole
6241     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6242     if(IC_TRUE(ic)){
6243         symbol *nlbl = newiTempLabel(NULL);
6244         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6245         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6246         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6247         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6248     }
6249     else{
6250         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6251         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6252     }
6253     ic->generated = 1;
6254 }
6255
6256 /*-----------------------------------------------------------------*/
6257 /* genAnd  - code for and                                          */
6258 /*-----------------------------------------------------------------*/
6259 static void genAnd (iCode *ic, iCode *ifx)
6260 {
6261   operand *left, *right, *result;
6262   int size, offset=0;  
6263   unsigned long lit = 0L;
6264   int bytelit = 0;
6265   resolvedIfx rIfx;
6266
6267
6268   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6269   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6270   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6271   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6272
6273   resolveIfx(&rIfx,ifx);
6274
6275   /* if left is a literal & right is not then exchange them */
6276   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6277       AOP_NEEDSACC(left)) {
6278     operand *tmp = right ;
6279     right = left;
6280     left = tmp;
6281   }
6282
6283   /* if result = right then exchange them */
6284   if(pic16_sameRegs(AOP(result),AOP(right))){
6285     operand *tmp = right ;
6286     right = left;
6287     left = tmp;
6288   }
6289
6290   /* if right is bit then exchange them */
6291   if (AOP_TYPE(right) == AOP_CRY &&
6292       AOP_TYPE(left) != AOP_CRY){
6293     operand *tmp = right ;
6294     right = left;
6295     left = tmp;
6296   }
6297   if(AOP_TYPE(right) == AOP_LIT)
6298     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6299
6300   size = AOP_SIZE(result);
6301
6302   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6303
6304   // if(bit & yy)
6305   // result = bit & yy;
6306   if (AOP_TYPE(left) == AOP_CRY){
6307     // c = bit & literal;
6308     if(AOP_TYPE(right) == AOP_LIT){
6309       if(lit & 1) {
6310         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6311           // no change
6312           goto release;
6313         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6314       } else {
6315         // bit(result) = 0;
6316         if(size && (AOP_TYPE(result) == AOP_CRY)){
6317           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6318           goto release;
6319         }
6320         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6321           jumpIfTrue(ifx);
6322           goto release;
6323         }
6324         pic16_emitcode("clr","c");
6325       }
6326     } else {
6327       if (AOP_TYPE(right) == AOP_CRY){
6328         // c = bit & bit;
6329         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6330         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6331       } else {
6332         // c = bit & val;
6333         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6334         // c = lsb
6335         pic16_emitcode("rrc","a");
6336         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6337       }
6338     }
6339     // bit = c
6340     // val = c
6341     if(size)
6342       pic16_outBitC(result);
6343     // if(bit & ...)
6344     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6345       genIfxJump(ifx, "c");           
6346     goto release ;
6347   }
6348
6349   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6350   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6351   if((AOP_TYPE(right) == AOP_LIT) &&
6352      (AOP_TYPE(result) == AOP_CRY) &&
6353      (AOP_TYPE(left) != AOP_CRY)){
6354     int posbit = isLiteralBit(lit);
6355     /* left &  2^n */
6356     if(posbit){
6357       posbit--;
6358       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6359       // bit = left & 2^n
6360       if(size)
6361         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6362       // if(left &  2^n)
6363       else{
6364         if(ifx){
6365 /*
6366           if(IC_TRUE(ifx)) {
6367             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6368             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6369           } else {
6370             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6371             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6372           }
6373 */
6374         DEBUGpic16_emitcode("***", "%d %s", __LINE__, __FUNCTION__);
6375         size = AOP_SIZE(left);
6376
6377         {
6378           int bp = posbit, ofs=0;
6379           
6380             while(bp > 7) {
6381               bp -= 8;
6382               ofs++;
6383             }
6384         
6385           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6386                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),ofs,FALSE,FALSE),bp,0));
6387
6388         }
6389 /*
6390           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6391                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6392 */
6393           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6394           
6395           ifx->generated = 1;
6396         }
6397         goto release;
6398       }
6399     } else {
6400       symbol *tlbl = newiTempLabel(NULL);
6401       int sizel = AOP_SIZE(left);
6402       if(size)
6403         pic16_emitcode("setb","c");
6404       while(sizel--){
6405         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6406           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6407           // byte ==  2^n ?
6408           if((posbit = isLiteralBit(bytelit)) != 0)
6409             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6410           else{
6411             if(bytelit != 0x0FFL)
6412               pic16_emitcode("anl","a,%s",
6413                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6414             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6415           }
6416         }
6417         offset++;
6418       }
6419       // bit = left & literal
6420       if(size){
6421         pic16_emitcode("clr","c");
6422         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6423       }
6424       // if(left & literal)
6425       else{
6426         if(ifx)
6427           jmpTrueOrFalse(ifx, tlbl);
6428         goto release ;
6429       }
6430     }
6431     pic16_outBitC(result);
6432     goto release ;
6433   }
6434
6435   /* if left is same as result */
6436   if(pic16_sameRegs(AOP(result),AOP(left))){
6437     int know_W = -1;
6438     for(;size--; offset++,lit>>=8) {
6439       if(AOP_TYPE(right) == AOP_LIT){
6440         switch(lit & 0xff) {
6441         case 0x00:
6442           /*  and'ing with 0 has clears the result */
6443 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6444           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6445           break;
6446         case 0xff:
6447           /* and'ing with 0xff is a nop when the result and left are the same */
6448           break;
6449
6450         default:
6451           {
6452             int p = my_powof2( (~lit) & 0xff );
6453             if(p>=0) {
6454               /* only one bit is set in the literal, so use a bcf instruction */
6455 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6456               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6457
6458             } else {
6459               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6460               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6461               if(know_W != (lit&0xff))
6462                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6463               know_W = lit &0xff;
6464               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6465             }
6466           }    
6467         }
6468       } else {
6469         if (AOP_TYPE(left) == AOP_ACC) {
6470           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6471         } else {                    
6472           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6473           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6474
6475         }
6476       }
6477     }
6478
6479   } else {
6480     // left & result in different registers
6481     if(AOP_TYPE(result) == AOP_CRY){
6482       // result = bit
6483       // if(size), result in bit
6484       // if(!size && ifx), conditional oper: if(left & right)
6485       symbol *tlbl = newiTempLabel(NULL);
6486       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6487       if(size)
6488         pic16_emitcode("setb","c");
6489       while(sizer--){
6490         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6491         pic16_emitcode("anl","a,%s",
6492                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6493         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6494         offset++;
6495       }
6496       if(size){
6497         CLRC;
6498         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6499         pic16_outBitC(result);
6500       } else if(ifx)
6501         jmpTrueOrFalse(ifx, tlbl);
6502     } else {
6503       for(;(size--);offset++) {
6504         // normal case
6505         // result = left & right
6506         if(AOP_TYPE(right) == AOP_LIT){
6507           int t = (lit >> (offset*8)) & 0x0FFL;
6508           switch(t) { 
6509           case 0x00:
6510             pic16_emitcode("clrf","%s",
6511                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6512             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6513             break;
6514           case 0xff:
6515             pic16_emitcode("movf","%s,w",
6516                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6517             pic16_emitcode("movwf","%s",
6518                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6519             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6520             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6521             break;
6522           default:
6523             pic16_emitcode("movlw","0x%x",t);
6524             pic16_emitcode("andwf","%s,w",
6525                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6526             pic16_emitcode("movwf","%s",
6527                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6528               
6529             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6530             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6531             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6532           }
6533           continue;
6534         }
6535
6536         if (AOP_TYPE(left) == AOP_ACC) {
6537           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6538           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6539         } else {
6540           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6541           pic16_emitcode("andwf","%s,w",
6542                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6543           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6544           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6545         }
6546         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6547         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6548       }
6549     }
6550   }
6551
6552   release :
6553     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6554   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6555   pic16_freeAsmop(result,NULL,ic,TRUE);     
6556 }
6557
6558 /*-----------------------------------------------------------------*/
6559 /* genOr  - code for or                                            */
6560 /*-----------------------------------------------------------------*/
6561 static void genOr (iCode *ic, iCode *ifx)
6562 {
6563     operand *left, *right, *result;
6564     int size, offset=0;
6565     unsigned long lit = 0L;
6566
6567     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6568
6569     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6570     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6571     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6572
6573     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6574
6575     /* if left is a literal & right is not then exchange them */
6576     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6577         AOP_NEEDSACC(left)) {
6578         operand *tmp = right ;
6579         right = left;
6580         left = tmp;
6581     }
6582
6583     /* if result = right then exchange them */
6584     if(pic16_sameRegs(AOP(result),AOP(right))){
6585         operand *tmp = right ;
6586         right = left;
6587         left = tmp;
6588     }
6589
6590     /* if right is bit then exchange them */
6591     if (AOP_TYPE(right) == AOP_CRY &&
6592         AOP_TYPE(left) != AOP_CRY){
6593         operand *tmp = right ;
6594         right = left;
6595         left = tmp;
6596     }
6597
6598     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6599
6600     if(AOP_TYPE(right) == AOP_LIT)
6601         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6602
6603     size = AOP_SIZE(result);
6604
6605     // if(bit | yy)
6606     // xx = bit | yy;
6607     if (AOP_TYPE(left) == AOP_CRY){
6608         if(AOP_TYPE(right) == AOP_LIT){
6609             // c = bit & literal;
6610             if(lit){
6611                 // lit != 0 => result = 1
6612                 if(AOP_TYPE(result) == AOP_CRY){
6613                   if(size)
6614                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6615                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6616                   //     AOP(result)->aopu.aop_dir,
6617                   //     AOP(result)->aopu.aop_dir);
6618                     else if(ifx)
6619                         continueIfTrue(ifx);
6620                     goto release;
6621                 }
6622             } else {
6623                 // lit == 0 => result = left
6624                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6625                     goto release;
6626                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6627             }
6628         } else {
6629             if (AOP_TYPE(right) == AOP_CRY){
6630               if(pic16_sameRegs(AOP(result),AOP(left))){
6631                 // c = bit | bit;
6632                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6633                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6634                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6635
6636                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6637                          AOP(result)->aopu.aop_dir,
6638                          AOP(result)->aopu.aop_dir);
6639                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6640                          AOP(right)->aopu.aop_dir,
6641                          AOP(right)->aopu.aop_dir);
6642                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6643                          AOP(result)->aopu.aop_dir,
6644                          AOP(result)->aopu.aop_dir);
6645               } else {
6646                 if( AOP_TYPE(result) == AOP_ACC) {
6647                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6648                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6649                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6650                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6651
6652                 } else {
6653
6654                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6655                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6656                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6657                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6658
6659                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6660                                  AOP(result)->aopu.aop_dir,
6661                                  AOP(result)->aopu.aop_dir);
6662                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6663                                  AOP(right)->aopu.aop_dir,
6664                                  AOP(right)->aopu.aop_dir);
6665                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6666                                  AOP(left)->aopu.aop_dir,
6667                                  AOP(left)->aopu.aop_dir);
6668                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6669                                  AOP(result)->aopu.aop_dir,
6670                                  AOP(result)->aopu.aop_dir);
6671                 }
6672               }
6673             } else {
6674                 // c = bit | val;
6675                 symbol *tlbl = newiTempLabel(NULL);
6676                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6677
6678
6679                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6680                 if( AOP_TYPE(right) == AOP_ACC) {
6681                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6682                   emitSKPNZ;
6683                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6684                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6685                 }
6686
6687
6688
6689                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6690                     pic16_emitcode(";XXX setb","c");
6691                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6692                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6693                 pic16_toBoolean(right);
6694                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6695                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6696                     jmpTrueOrFalse(ifx, tlbl);
6697                     goto release;
6698                 } else {
6699                     CLRC;
6700                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6701                 }
6702             }
6703         }
6704         // bit = c
6705         // val = c
6706         if(size)
6707             pic16_outBitC(result);
6708         // if(bit | ...)
6709         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6710             genIfxJump(ifx, "c");           
6711         goto release ;
6712     }
6713
6714     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6715     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6716     if((AOP_TYPE(right) == AOP_LIT) &&
6717        (AOP_TYPE(result) == AOP_CRY) &&
6718        (AOP_TYPE(left) != AOP_CRY)){
6719         if(lit){
6720           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6721             // result = 1
6722             if(size)
6723                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6724             else 
6725                 continueIfTrue(ifx);
6726             goto release;
6727         } else {
6728           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6729             // lit = 0, result = boolean(left)
6730             if(size)
6731                 pic16_emitcode(";XXX setb","c");
6732             pic16_toBoolean(right);
6733             if(size){
6734                 symbol *tlbl = newiTempLabel(NULL);
6735                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6736                 CLRC;
6737                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6738             } else {
6739                 genIfxJump (ifx,"a");
6740                 goto release;
6741             }
6742         }
6743         pic16_outBitC(result);
6744         goto release ;
6745     }
6746
6747     /* if left is same as result */
6748     if(pic16_sameRegs(AOP(result),AOP(left))){
6749       int know_W = -1;
6750       for(;size--; offset++,lit>>=8) {
6751         if(AOP_TYPE(right) == AOP_LIT){
6752           if((lit & 0xff) == 0)
6753             /*  or'ing with 0 has no effect */
6754             continue;
6755           else {
6756             int p = my_powof2(lit & 0xff);
6757             if(p>=0) {
6758               /* only one bit is set in the literal, so use a bsf instruction */
6759               pic16_emitpcode(POC_BSF,
6760                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6761             } else {
6762               if(know_W != (lit & 0xff))
6763                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6764               know_W = lit & 0xff;
6765               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6766             }
6767                     
6768           }
6769         } else {
6770           if (AOP_TYPE(left) == AOP_ACC) {
6771             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6772             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6773           } else {                  
6774             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6775             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6776
6777             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6778             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6779
6780           }
6781         }
6782       }
6783     } else {
6784         // left & result in different registers
6785         if(AOP_TYPE(result) == AOP_CRY){
6786             // result = bit
6787             // if(size), result in bit
6788             // if(!size && ifx), conditional oper: if(left | right)
6789             symbol *tlbl = newiTempLabel(NULL);
6790             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6791             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6792
6793
6794             if(size)
6795                 pic16_emitcode(";XXX setb","c");
6796             while(sizer--){
6797                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6798                 pic16_emitcode(";XXX orl","a,%s",
6799                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6800                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6801                 offset++;
6802             }
6803             if(size){
6804                 CLRC;
6805                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6806                 pic16_outBitC(result);
6807             } else if(ifx)
6808                 jmpTrueOrFalse(ifx, tlbl);
6809         } else for(;(size--);offset++){
6810           // normal case
6811           // result = left & right
6812           if(AOP_TYPE(right) == AOP_LIT){
6813             int t = (lit >> (offset*8)) & 0x0FFL;
6814             switch(t) { 
6815             case 0x00:
6816               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6817               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6818
6819               pic16_emitcode("movf","%s,w",
6820                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6821               pic16_emitcode("movwf","%s",
6822                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6823               break;
6824             default:
6825               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6826               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6827               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6828
6829               pic16_emitcode("movlw","0x%x",t);
6830               pic16_emitcode("iorwf","%s,w",
6831                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6832               pic16_emitcode("movwf","%s",
6833                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6834               
6835             }
6836             continue;
6837           }
6838
6839           // faster than result <- left, anl result,right
6840           // and better if result is SFR
6841           if (AOP_TYPE(left) == AOP_ACC) {
6842             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6843             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6844           } else {
6845             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6846             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6847
6848             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6849             pic16_emitcode("iorwf","%s,w",
6850                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6851           }
6852           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6853           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6854         }
6855     }
6856
6857 release :
6858     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6859     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6860     pic16_freeAsmop(result,NULL,ic,TRUE);     
6861 }
6862
6863 /*-----------------------------------------------------------------*/
6864 /* genXor - code for xclusive or                                   */
6865 /*-----------------------------------------------------------------*/
6866 static void genXor (iCode *ic, iCode *ifx)
6867 {
6868   operand *left, *right, *result;
6869   int size, offset=0;
6870   unsigned long lit = 0L;
6871
6872   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6873
6874   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6875   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6876   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6877
6878   /* if left is a literal & right is not ||
6879      if left needs acc & right does not */
6880   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6881       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6882     operand *tmp = right ;
6883     right = left;
6884     left = tmp;
6885   }
6886
6887   /* if result = right then exchange them */
6888   if(pic16_sameRegs(AOP(result),AOP(right))){
6889     operand *tmp = right ;
6890     right = left;
6891     left = tmp;
6892   }
6893
6894   /* if right is bit then exchange them */
6895   if (AOP_TYPE(right) == AOP_CRY &&
6896       AOP_TYPE(left) != AOP_CRY){
6897     operand *tmp = right ;
6898     right = left;
6899     left = tmp;
6900   }
6901   if(AOP_TYPE(right) == AOP_LIT)
6902     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6903
6904   size = AOP_SIZE(result);
6905
6906   // if(bit ^ yy)
6907   // xx = bit ^ yy;
6908   if (AOP_TYPE(left) == AOP_CRY){
6909     if(AOP_TYPE(right) == AOP_LIT){
6910       // c = bit & literal;
6911       if(lit>>1){
6912         // lit>>1  != 0 => result = 1
6913         if(AOP_TYPE(result) == AOP_CRY){
6914           if(size)
6915             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6916             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6917           else if(ifx)
6918             continueIfTrue(ifx);
6919           goto release;
6920         }
6921         pic16_emitcode("setb","c");
6922       } else{
6923         // lit == (0 or 1)
6924         if(lit == 0){
6925           // lit == 0, result = left
6926           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6927             goto release;
6928           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6929         } else{
6930           // lit == 1, result = not(left)
6931           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6932             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6933             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6934             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6935             goto release;
6936           } else {
6937             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6938             pic16_emitcode("cpl","c");
6939           }
6940         }
6941       }
6942
6943     } else {
6944       // right != literal
6945       symbol *tlbl = newiTempLabel(NULL);
6946       if (AOP_TYPE(right) == AOP_CRY){
6947         // c = bit ^ bit;
6948         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6949       }
6950       else{
6951         int sizer = AOP_SIZE(right);
6952         // c = bit ^ val
6953         // if val>>1 != 0, result = 1
6954         pic16_emitcode("setb","c");
6955         while(sizer){
6956           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6957           if(sizer == 1)
6958             // test the msb of the lsb
6959             pic16_emitcode("anl","a,#0xfe");
6960           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6961           sizer--;
6962         }
6963         // val = (0,1)
6964         pic16_emitcode("rrc","a");
6965       }
6966       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6967       pic16_emitcode("cpl","c");
6968       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6969     }
6970     // bit = c
6971     // val = c
6972     if(size)
6973       pic16_outBitC(result);
6974     // if(bit | ...)
6975     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6976       genIfxJump(ifx, "c");           
6977     goto release ;
6978   }
6979
6980   if(pic16_sameRegs(AOP(result),AOP(left))){
6981     /* if left is same as result */
6982     for(;size--; offset++) {
6983       if(AOP_TYPE(right) == AOP_LIT){
6984         int t  = (lit >> (offset*8)) & 0x0FFL;
6985         if(t == 0x00L)
6986           continue;
6987         else
6988           if (IS_AOP_PREG(left)) {
6989             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6990             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6991             pic16_aopPut(AOP(result),"a",offset);
6992           } else {
6993             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6994             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6995             pic16_emitcode("xrl","%s,%s",
6996                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6997                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6998           }
6999       } else {
7000         if (AOP_TYPE(left) == AOP_ACC)
7001           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7002         else {
7003           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7004           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
7005 /*
7006           if (IS_AOP_PREG(left)) {
7007             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7008             pic16_aopPut(AOP(result),"a",offset);
7009           } else
7010             pic16_emitcode("xrl","%s,a",
7011                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
7012 */
7013         }
7014       }
7015     }
7016   } else {
7017     // left & result in different registers
7018     if(AOP_TYPE(result) == AOP_CRY){
7019       // result = bit
7020       // if(size), result in bit
7021       // if(!size && ifx), conditional oper: if(left ^ right)
7022       symbol *tlbl = newiTempLabel(NULL);
7023       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
7024       if(size)
7025         pic16_emitcode("setb","c");
7026       while(sizer--){
7027         if((AOP_TYPE(right) == AOP_LIT) &&
7028            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
7029           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7030         } else {
7031           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7032           pic16_emitcode("xrl","a,%s",
7033                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7034         }
7035         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
7036         offset++;
7037       }
7038       if(size){
7039         CLRC;
7040         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7041         pic16_outBitC(result);
7042       } else if(ifx)
7043         jmpTrueOrFalse(ifx, tlbl);
7044     } else for(;(size--);offset++){
7045       // normal case
7046       // result = left & right
7047       if(AOP_TYPE(right) == AOP_LIT){
7048         int t = (lit >> (offset*8)) & 0x0FFL;
7049         switch(t) { 
7050         case 0x00:
7051           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
7052           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7053           pic16_emitcode("movf","%s,w",
7054                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7055           pic16_emitcode("movwf","%s",
7056                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7057           break;
7058         case 0xff:
7059           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7060           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7061           pic16_emitcode("comf","%s,w",
7062                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7063           pic16_emitcode("movwf","%s",
7064                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7065           break;
7066         default:
7067           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7068           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7069           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7070           pic16_emitcode("movlw","0x%x",t);
7071           pic16_emitcode("xorwf","%s,w",
7072                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7073           pic16_emitcode("movwf","%s",
7074                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7075
7076         }
7077         continue;
7078       }
7079
7080       // faster than result <- left, anl result,right
7081       // and better if result is SFR
7082       if (AOP_TYPE(left) == AOP_ACC) {
7083         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7084         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7085       } else {
7086         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7087         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7088         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7089         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7090       }
7091       if ( AOP_TYPE(result) != AOP_ACC){
7092         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7093         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7094       }
7095     }
7096   }
7097
7098   release :
7099     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7100   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7101   pic16_freeAsmop(result,NULL,ic,TRUE);     
7102 }
7103
7104 /*-----------------------------------------------------------------*/
7105 /* genInline - write the inline code out                           */
7106 /*-----------------------------------------------------------------*/
7107 static void genInline (iCode *ic)
7108 {
7109   char *buffer, *bp, *bp1;
7110     
7111         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7112
7113         _G.inLine += (!options.asmpeep);
7114
7115         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7116         strcpy(buffer,IC_INLINE(ic));
7117
7118 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7119
7120         /* emit each line as a code */
7121         while (*bp) {
7122                 if (*bp == '\n') {
7123                         *bp++ = '\0';
7124
7125                         if(*bp1)
7126                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7127                         bp1 = bp;
7128                 } else {
7129                         if (*bp == ':') {
7130                                 bp++;
7131                                 *bp = '\0';
7132                                 bp++;
7133
7134                                 /* print label, use this special format with NULL directive
7135                                  * to denote that the argument should not be indented with tab */
7136                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7137                                 bp1 = bp;
7138                         } else
7139                                 bp++;
7140                 }
7141         }
7142
7143         if ((bp1 != bp) && *bp1)
7144                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7145
7146
7147     Safe_free(buffer);
7148
7149     _G.inLine -= (!options.asmpeep);
7150 }
7151
7152 /*-----------------------------------------------------------------*/
7153 /* genRRC - rotate right with carry                                */
7154 /*-----------------------------------------------------------------*/
7155 static void genRRC (iCode *ic)
7156 {
7157   operand *left , *result ;
7158   int size, offset = 0, same;
7159
7160   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7161
7162   /* rotate right with carry */
7163   left = IC_LEFT(ic);
7164   result=IC_RESULT(ic);
7165   pic16_aopOp (left,ic,FALSE);
7166   pic16_aopOp (result,ic,FALSE);
7167
7168   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7169
7170   same = pic16_sameRegs(AOP(result),AOP(left));
7171
7172   size = AOP_SIZE(result);    
7173
7174   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7175
7176   /* get the lsb and put it into the carry */
7177   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7178
7179   offset = 0 ;
7180
7181   while(size--) {
7182
7183     if(same) {
7184       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7185     } else {
7186       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7187       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7188     }
7189
7190     offset++;
7191   }
7192
7193   pic16_freeAsmop(left,NULL,ic,TRUE);
7194   pic16_freeAsmop(result,NULL,ic,TRUE);
7195 }
7196
7197 /*-----------------------------------------------------------------*/
7198 /* genRLC - generate code for rotate left with carry               */
7199 /*-----------------------------------------------------------------*/
7200 static void genRLC (iCode *ic)
7201 {    
7202   operand *left , *result ;
7203   int size, offset = 0;
7204   int same;
7205
7206   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7207   /* rotate right with carry */
7208   left = IC_LEFT(ic);
7209   result=IC_RESULT(ic);
7210   pic16_aopOp (left,ic,FALSE);
7211   pic16_aopOp (result,ic,FALSE);
7212
7213   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7214
7215   same = pic16_sameRegs(AOP(result),AOP(left));
7216
7217   /* move it to the result */
7218   size = AOP_SIZE(result);    
7219
7220   /* get the msb and put it into the carry */
7221   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7222
7223   offset = 0 ;
7224
7225   while(size--) {
7226
7227     if(same) {
7228       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7229     } else {
7230       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7231       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7232     }
7233
7234     offset++;
7235   }
7236
7237
7238   pic16_freeAsmop(left,NULL,ic,TRUE);
7239   pic16_freeAsmop(result,NULL,ic,TRUE);
7240 }
7241
7242
7243 /* gpasm can get the highest order bit with HIGH/UPPER
7244  * so the following probably is not needed -- VR */
7245  
7246 /*-----------------------------------------------------------------*/
7247 /* genGetHbit - generates code get highest order bit               */
7248 /*-----------------------------------------------------------------*/
7249 static void genGetHbit (iCode *ic)
7250 {
7251     operand *left, *result;
7252     left = IC_LEFT(ic);
7253     result=IC_RESULT(ic);
7254     pic16_aopOp (left,ic,FALSE);
7255     pic16_aopOp (result,ic,FALSE);
7256
7257     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7258     /* get the highest order byte into a */
7259     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7260     if(AOP_TYPE(result) == AOP_CRY){
7261         pic16_emitcode("rlc","a");
7262         pic16_outBitC(result);
7263     }
7264     else{
7265         pic16_emitcode("rl","a");
7266         pic16_emitcode("anl","a,#0x01");
7267         pic16_outAcc(result);
7268     }
7269
7270
7271     pic16_freeAsmop(left,NULL,ic,TRUE);
7272     pic16_freeAsmop(result,NULL,ic,TRUE);
7273 }
7274
7275 #if 0
7276 /*-----------------------------------------------------------------*/
7277 /* AccRol - rotate left accumulator by known count                 */
7278 /*-----------------------------------------------------------------*/
7279 static void AccRol (int shCount)
7280 {
7281     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7282     shCount &= 0x0007;              // shCount : 0..7
7283     switch(shCount){
7284         case 0 :
7285             break;
7286         case 1 :
7287             pic16_emitcode("rl","a");
7288             break;
7289         case 2 :
7290             pic16_emitcode("rl","a");
7291             pic16_emitcode("rl","a");
7292             break;
7293         case 3 :
7294             pic16_emitcode("swap","a");
7295             pic16_emitcode("rr","a");
7296             break;
7297         case 4 :
7298             pic16_emitcode("swap","a");
7299             break;
7300         case 5 :
7301             pic16_emitcode("swap","a");
7302             pic16_emitcode("rl","a");
7303             break;
7304         case 6 :
7305             pic16_emitcode("rr","a");
7306             pic16_emitcode("rr","a");
7307             break;
7308         case 7 :
7309             pic16_emitcode("rr","a");
7310             break;
7311     }
7312 }
7313 #endif
7314
7315 /*-----------------------------------------------------------------*/
7316 /* AccLsh - left shift accumulator by known count                  */
7317 /*-----------------------------------------------------------------*/
7318 static void AccLsh (int shCount)
7319 {
7320         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7321         switch(shCount){
7322                 case 0 :
7323                         return;
7324                         break;
7325                 case 1 :
7326                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7327                         break;
7328                 case 2 :
7329                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7330                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7331                         break;
7332                 case 3 :
7333                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7334                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7335                         break;
7336                 case 4 :
7337                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7338                         break;
7339                 case 5 :
7340                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7341                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7342                         break;
7343                 case 6 :
7344                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7345                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7346                         break;
7347                 case 7 :
7348                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7349                         break;
7350         }
7351
7352         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7353 }
7354
7355 /*-----------------------------------------------------------------*/
7356 /* AccRsh - right shift accumulator by known count                 */
7357 /*-----------------------------------------------------------------*/
7358 static void AccRsh (int shCount, int andmask)
7359 {
7360         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7361         switch(shCount){
7362                 case 0 :
7363                         return; break;
7364                 case 1 :
7365                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7366 //                      andmask = 0;    /* no need */
7367                         break;
7368                 case 2 :
7369                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7370                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7371 //                      andmask = 0;    /* no need */
7372                         break;
7373                 case 3 :
7374                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7375                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7376                         break;
7377                 case 4 :
7378                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7379                         break;
7380                 case 5 :
7381                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7382                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7383                         break;
7384                 case 6 :
7385                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7386                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7387                         break;
7388                 case 7 :
7389                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7390                         break;
7391         }
7392         
7393         if(andmask)
7394                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7395         else
7396                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7397 }
7398
7399 #if 0
7400 /*-----------------------------------------------------------------*/
7401 /* AccSRsh - signed right shift accumulator by known count                 */
7402 /*-----------------------------------------------------------------*/
7403 static void AccSRsh (int shCount)
7404 {
7405     symbol *tlbl ;
7406     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7407     if(shCount != 0){
7408         if(shCount == 1){
7409             pic16_emitcode("mov","c,acc.7");
7410             pic16_emitcode("rrc","a");
7411         } else if(shCount == 2){
7412             pic16_emitcode("mov","c,acc.7");
7413             pic16_emitcode("rrc","a");
7414             pic16_emitcode("mov","c,acc.7");
7415             pic16_emitcode("rrc","a");
7416         } else {
7417             tlbl = newiTempLabel(NULL);
7418             /* rotate right accumulator */
7419             AccRol(8 - shCount);
7420             /* and kill the higher order bits */
7421             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7422             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7423             pic16_emitcode("orl","a,#0x%02x",
7424                      (unsigned char)~SRMask[shCount]);
7425             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7426         }
7427     }
7428 }
7429 #endif
7430 /*-----------------------------------------------------------------*/
7431 /* shiftR1Left2Result - shift right one byte from left to result   */
7432 /*-----------------------------------------------------------------*/
7433 static void shiftR1Left2ResultSigned (operand *left, int offl,
7434                                 operand *result, int offr,
7435                                 int shCount)
7436 {
7437   int same;
7438
7439   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7440
7441   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7442
7443   switch(shCount) {
7444   case 1:
7445     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7446     if(same) 
7447       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7448     else {
7449       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7450       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7451     }
7452
7453     break;
7454   case 2:
7455
7456     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7457     if(same) 
7458       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7459     else {
7460       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7461       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7462     }
7463     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7464     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7465
7466     break;
7467
7468   case 3:
7469     if(same)
7470       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7471     else {
7472       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7473       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7474     }
7475
7476     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7477     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7478     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7479
7480     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7481     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7482
7483     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7484     break;
7485
7486   case 4:
7487     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7488     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7489     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7490     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7491     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7492     break;
7493   case 5:
7494     if(same) {
7495       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7496     } else {
7497       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7498       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7499     }
7500     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7501     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7502     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7503     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7504     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7505     break;
7506
7507   case 6:
7508     if(same) {
7509       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7510       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7511       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7512       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7513       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7514       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7515     } else {
7516       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7517       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7518       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7519       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7520       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7521     }
7522     break;
7523
7524   case 7:
7525     if(same) {
7526       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7527       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7528       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7529       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7530     } else {
7531       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7532       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7533       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7534     }
7535
7536   default:
7537     break;
7538   }
7539 }
7540
7541 /*-----------------------------------------------------------------*/
7542 /* shiftR1Left2Result - shift right one byte from left to result   */
7543 /*-----------------------------------------------------------------*/
7544 static void shiftR1Left2Result (operand *left, int offl,
7545                                 operand *result, int offr,
7546                                 int shCount, int sign)
7547 {
7548   int same;
7549
7550   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7551
7552   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7553
7554   /* Copy the msb into the carry if signed. */
7555   if(sign) {
7556     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7557     return;
7558   }
7559
7560
7561
7562   switch(shCount) {
7563   case 1:
7564     emitCLRC;
7565     if(same) 
7566       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7567     else {
7568       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7569       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7570     }
7571     break;
7572   case 2:
7573     emitCLRC;
7574     if(same) {
7575       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7576     } else {
7577       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7578       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7579     }
7580     emitCLRC;
7581     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7582
7583     break;
7584   case 3:
7585     if(same)
7586       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7587     else {
7588       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7589       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7590     }
7591
7592     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7593     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7594     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7595     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7596     break;
7597       
7598   case 4:
7599     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7600     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7601     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7602     break;
7603
7604   case 5:
7605     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7606     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7607     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7608     emitCLRC;
7609     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7610
7611     break;
7612   case 6:
7613
7614     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7615     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7616     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7617     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7618     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7619     break;
7620
7621   case 7:
7622
7623     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7624     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7625     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7626
7627     break;
7628
7629   default:
7630     break;
7631   }
7632 }
7633
7634 /*-----------------------------------------------------------------*/
7635 /* shiftL1Left2Result - shift left one byte from left to result    */
7636 /*-----------------------------------------------------------------*/
7637 static void shiftL1Left2Result (operand *left, int offl,
7638                                 operand *result, int offr, int shCount)
7639 {
7640   int same;
7641
7642   //    char *l;
7643   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7644
7645   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7646   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7647     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7648     //    MOVA(l);
7649     /* shift left accumulator */
7650     //AccLsh(shCount); // don't comment out just yet...
7651   //    pic16_aopPut(AOP(result),"a",offr);
7652
7653   switch(shCount) {
7654   case 1:
7655     /* Shift left 1 bit position */
7656     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7657     if(same) {
7658       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7659     } else {
7660       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7661       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7662     }
7663     break;
7664   case 2:
7665     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7666     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7667     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7668     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7669     break;
7670   case 3:
7671     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7672     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7673     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7674     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7675     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7676     break;
7677   case 4:
7678     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7679     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7680     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7681     break;
7682   case 5:
7683     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7684     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7685     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7686     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7687     break;
7688   case 6:
7689     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7690     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7691     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7692     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7693     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7694     break;
7695   case 7:
7696     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7697     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7698     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7699     break;
7700
7701   default:
7702     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7703   }
7704
7705 }
7706
7707 /*-----------------------------------------------------------------*/
7708 /* movLeft2Result - move byte from left to result                  */
7709 /*-----------------------------------------------------------------*/
7710 static void movLeft2Result (operand *left, int offl,
7711                             operand *result, int offr)
7712 {
7713   char *l;
7714   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7715   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7716     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7717
7718     if (*l == '@' && (IS_AOP_PREG(result))) {
7719       pic16_emitcode("mov","a,%s",l);
7720       pic16_aopPut(AOP(result),"a",offr);
7721     } else {
7722       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7723       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7724     }
7725   }
7726 }
7727
7728 /*-----------------------------------------------------------------*/
7729 /* shiftL2Left2Result - shift left two bytes from left to result   */
7730 /*-----------------------------------------------------------------*/
7731 static void shiftL2Left2Result (operand *left, int offl,
7732                                 operand *result, int offr, int shCount)
7733 {
7734   int same = pic16_sameRegs(AOP(result), AOP(left));
7735   int i;
7736
7737   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7738
7739   if (same && (offl != offr)) { // shift bytes
7740     if (offr > offl) {
7741        for(i=1;i>-1;i--) {
7742          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7743          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7744        }
7745     } else { // just treat as different later on
7746                 same = 0;
7747     }
7748   }
7749
7750   if(same) {
7751     switch(shCount) {
7752     case 0:
7753       break;
7754     case 1:
7755     case 2:
7756     case 3:
7757
7758       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7759       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7760       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7761
7762       while(--shCount) {
7763                 emitCLRC;
7764                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7765                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7766       }
7767
7768       break;
7769     case 4:
7770     case 5:
7771       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7772       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7773       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7774       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7775       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7776       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7777       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7778       if(shCount >=5) {
7779                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7780                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7781       }
7782       break;
7783     case 6:
7784       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7785       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7786       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7787       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7788       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7789       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7790       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7791       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7792       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7793       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7794       break;
7795     case 7:
7796       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7797       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7798       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7799       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7800       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7801     }
7802
7803   } else {
7804     switch(shCount) {
7805     case 0:
7806       break;
7807     case 1:
7808     case 2:
7809     case 3:
7810       /* note, use a mov/add for the shift since the mov has a
7811          chance of getting optimized out */
7812       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7813       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7814       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7815       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7816       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7817
7818       while(--shCount) {
7819                 emitCLRC;
7820                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7821                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7822       }
7823       break;
7824
7825     case 4:
7826     case 5:
7827       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7828       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7829       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7830       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7831       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7832       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7833       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7834       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7835
7836
7837       if(shCount == 5) {
7838                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7839                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7840       }
7841       break;
7842     case 6:
7843       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7844       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7845       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7846       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7847
7848       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7849       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7850       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7851       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7852       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7853       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7854       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7855       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7856       break;
7857     case 7:
7858       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7859       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7860       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7861       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7862       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7863     }
7864   }
7865
7866 }
7867 /*-----------------------------------------------------------------*/
7868 /* shiftR2Left2Result - shift right two bytes from left to result  */
7869 /*-----------------------------------------------------------------*/
7870 static void shiftR2Left2Result (operand *left, int offl,
7871                                 operand *result, int offr,
7872                                 int shCount, int sign)
7873 {
7874   int same = pic16_sameRegs(AOP(result), AOP(left));
7875   int i;
7876   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7877
7878   if (same && (offl != offr)) { // shift right bytes
7879     if (offr < offl) {
7880        for(i=0;i<2;i++) {
7881          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7882          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7883        }
7884     } else { // just treat as different later on
7885                 same = 0;
7886     }
7887   }
7888
7889   switch(shCount) {
7890   case 0:
7891     break;
7892   case 1:
7893   case 2:
7894   case 3:
7895     if(sign)
7896       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7897     else
7898       emitCLRC;
7899
7900     if(same) {
7901       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7902       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7903     } else {
7904       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7905       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7906       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7907       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7908     }
7909
7910     while(--shCount) {
7911       if(sign)
7912                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7913       else
7914                 emitCLRC;
7915       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7916       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7917     }
7918     break;
7919   case 4:
7920   case 5:
7921     if(same) {
7922
7923       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7924       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7925       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7926
7927       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7928       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7929       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7930       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7931     } else {
7932       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7933       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7934       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7935
7936       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7937       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7938       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7939       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7940       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7941     }
7942
7943     if(shCount >=5) {
7944       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7945       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7946     }
7947
7948     if(sign) {
7949       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7950       pic16_emitpcode(POC_BTFSC, 
7951                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7952       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7953     }
7954
7955     break;
7956
7957   case 6:
7958     if(same) {
7959
7960       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7961       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7962
7963       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7964       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7965       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7966       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7967       if(sign) {
7968         pic16_emitpcode(POC_BTFSC, 
7969                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7970         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7971       }
7972       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7973       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7974       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7975       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7976     } else {
7977       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7978       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7979       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7980       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7981       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7982       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7983       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7984       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7985       if(sign) {
7986         pic16_emitpcode(POC_BTFSC, 
7987                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7988         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7989       }
7990       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7991       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7992
7993         
7994     }
7995
7996     break;
7997   case 7:
7998     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7999     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
8000     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
8001     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
8002     if(sign) {
8003       emitSKPNC;
8004       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
8005     } else 
8006       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
8007   }
8008 }
8009
8010
8011 /*-----------------------------------------------------------------*/
8012 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
8013 /*-----------------------------------------------------------------*/
8014 static void shiftLLeftOrResult (operand *left, int offl,
8015                                 operand *result, int offr, int shCount)
8016 {
8017     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8018
8019     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8020     /* shift left accumulator */
8021     AccLsh(shCount);
8022     /* or with result */
8023     /* back to result */
8024     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8025 }
8026
8027 /*-----------------------------------------------------------------*/
8028 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
8029 /*-----------------------------------------------------------------*/
8030 static void shiftRLeftOrResult (operand *left, int offl,
8031                                 operand *result, int offr, int shCount)
8032 {
8033     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8034     
8035     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
8036     /* shift right accumulator */
8037     AccRsh(shCount, 1);
8038     /* or with result */
8039     /* back to result */
8040     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
8041 }
8042
8043 /*-----------------------------------------------------------------*/
8044 /* genlshOne - left shift a one byte quantity by known count       */
8045 /*-----------------------------------------------------------------*/
8046 static void genlshOne (operand *result, operand *left, int shCount)
8047 {       
8048     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8049     shiftL1Left2Result(left, LSB, result, LSB, shCount);
8050 }
8051
8052 /*-----------------------------------------------------------------*/
8053 /* genlshTwo - left shift two bytes by known amount != 0           */
8054 /*-----------------------------------------------------------------*/
8055 static void genlshTwo (operand *result,operand *left, int shCount)
8056 {
8057     int size;
8058     
8059     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8060     size = pic16_getDataSize(result);
8061
8062     /* if shCount >= 8 */
8063     if (shCount >= 8) {
8064         shCount -= 8 ;
8065
8066         if (size > 1){
8067             if (shCount)
8068                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8069             else 
8070                 movLeft2Result(left, LSB, result, MSB16);
8071         }
8072         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8073     }
8074
8075     /*  1 <= shCount <= 7 */
8076     else {  
8077         if(size == 1)
8078             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8079         else 
8080             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8081     }
8082 }
8083
8084 /*-----------------------------------------------------------------*/
8085 /* shiftLLong - shift left one long from left to result            */
8086 /* offr = LSB or MSB16                                             */
8087 /*-----------------------------------------------------------------*/
8088 static void shiftLLong (operand *left, operand *result, int offr )
8089 {
8090     int size = AOP_SIZE(result);
8091     int same = pic16_sameRegs(AOP(left),AOP(result));
8092         int i;
8093
8094     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8095
8096         if (same && (offr == MSB16)) { //shift one byte
8097                 for(i=size-1;i>=MSB16;i--) {
8098                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8099                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8100                 }
8101         } else {
8102                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8103         }
8104         
8105     if (size >= LSB+offr ){
8106                 if (same) {
8107                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8108                 } else {
8109                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8110                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8111                 }
8112          }
8113
8114     if(size >= MSB16+offr){
8115                 if (same) {
8116                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8117                 } else {
8118                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8119                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8120                 }
8121     }
8122
8123     if(size >= MSB24+offr){
8124                 if (same) {
8125                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8126                 } else {
8127                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8128                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8129                 }
8130     }
8131
8132     if(size > MSB32+offr){
8133                 if (same) {
8134                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8135                 } else {
8136                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8137                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8138                 }
8139     }
8140     if(offr != LSB)
8141                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8142
8143 }
8144
8145 /*-----------------------------------------------------------------*/
8146 /* genlshFour - shift four byte by a known amount != 0             */
8147 /*-----------------------------------------------------------------*/
8148 static void genlshFour (operand *result, operand *left, int shCount)
8149 {
8150     int size;
8151
8152     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8153     size = AOP_SIZE(result);
8154
8155     /* if shifting more that 3 bytes */
8156     if (shCount >= 24 ) {
8157         shCount -= 24;
8158         if (shCount)
8159             /* lowest order of left goes to the highest
8160             order of the destination */
8161             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8162         else
8163             movLeft2Result(left, LSB, result, MSB32);
8164
8165                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8166                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8167                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8168
8169         return;
8170     }
8171
8172     /* more than two bytes */
8173     else if ( shCount >= 16 ) {
8174         /* lower order two bytes goes to higher order two bytes */
8175         shCount -= 16;
8176         /* if some more remaining */
8177         if (shCount)
8178             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8179         else {
8180             movLeft2Result(left, MSB16, result, MSB32);
8181             movLeft2Result(left, LSB, result, MSB24);
8182         }
8183                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8184                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8185         return;
8186     }    
8187
8188     /* if more than 1 byte */
8189     else if ( shCount >= 8 ) {
8190         /* lower order three bytes goes to higher order  three bytes */
8191         shCount -= 8;
8192         if(size == 2){
8193             if(shCount)
8194                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8195             else
8196                 movLeft2Result(left, LSB, result, MSB16);
8197         }
8198         else{   /* size = 4 */
8199             if(shCount == 0){
8200                 movLeft2Result(left, MSB24, result, MSB32);
8201                 movLeft2Result(left, MSB16, result, MSB24);
8202                 movLeft2Result(left, LSB, result, MSB16);
8203                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8204             }
8205             else if(shCount == 1)
8206                 shiftLLong(left, result, MSB16);
8207             else{
8208                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8209                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8210                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8211                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8212             }
8213         }
8214     }
8215
8216     /* 1 <= shCount <= 7 */
8217     else if(shCount <= 3)
8218     { 
8219         shiftLLong(left, result, LSB);
8220         while(--shCount >= 1)
8221             shiftLLong(result, result, LSB);
8222     }
8223     /* 3 <= shCount <= 7, optimize */
8224     else{
8225         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8226         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8227         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8228     }
8229 }
8230
8231 /*-----------------------------------------------------------------*/
8232 /* genLeftShiftLiteral - left shifting by known count              */
8233 /*-----------------------------------------------------------------*/
8234 static void genLeftShiftLiteral (operand *left,
8235                                  operand *right,
8236                                  operand *result,
8237                                  iCode *ic)
8238 {    
8239     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8240     int size;
8241
8242     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8243     pic16_freeAsmop(right,NULL,ic,TRUE);
8244
8245     pic16_aopOp(left,ic,FALSE);
8246     pic16_aopOp(result,ic,FALSE);
8247
8248     size = getSize(operandType(result));
8249
8250 #if VIEW_SIZE
8251     pic16_emitcode("; shift left ","result %d, left %d",size,
8252              AOP_SIZE(left));
8253 #endif
8254
8255     /* I suppose that the left size >= result size */
8256     if(shCount == 0){
8257         while(size--){
8258             movLeft2Result(left, size, result, size);
8259         }
8260     }
8261
8262     else if(shCount >= (size * 8))
8263         while(size--)
8264             pic16_aopPut(AOP(result),zero,size);
8265     else{
8266         switch (size) {
8267             case 1:
8268                 genlshOne (result,left,shCount);
8269                 break;
8270
8271             case 2:
8272             case 3:
8273                 genlshTwo (result,left,shCount);
8274                 break;
8275
8276             case 4:
8277                 genlshFour (result,left,shCount);
8278                 break;
8279         }
8280     }
8281     pic16_freeAsmop(left,NULL,ic,TRUE);
8282     pic16_freeAsmop(result,NULL,ic,TRUE);
8283 }
8284
8285 /*-----------------------------------------------------------------*
8286  * genMultiAsm - repeat assembly instruction for size of register.
8287  * if endian == 1, then the high byte (i.e base address + size of 
8288  * register) is used first else the low byte is used first;
8289  *-----------------------------------------------------------------*/
8290 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8291 {
8292
8293   int offset = 0;
8294
8295   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8296
8297   if(!reg)
8298     return;
8299
8300   if(!endian) {
8301     endian = 1;
8302   } else {
8303     endian = -1;
8304     offset = size-1;
8305   }
8306
8307   while(size--) {
8308     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8309     offset += endian;
8310   }
8311
8312 }
8313 /*-----------------------------------------------------------------*/
8314 /* genLeftShift - generates code for left shifting                 */
8315 /*-----------------------------------------------------------------*/
8316 static void genLeftShift (iCode *ic)
8317 {
8318   operand *left,*right, *result;
8319   int size, offset;
8320   char *l;
8321   symbol *tlbl , *tlbl1;
8322   pCodeOp *pctemp;
8323
8324   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8325
8326   right = IC_RIGHT(ic);
8327   left  = IC_LEFT(ic);
8328   result = IC_RESULT(ic);
8329
8330   pic16_aopOp(right,ic,FALSE);
8331
8332   /* if the shift count is known then do it 
8333      as efficiently as possible */
8334   if (AOP_TYPE(right) == AOP_LIT) {
8335     genLeftShiftLiteral (left,right,result,ic);
8336     return ;
8337   }
8338
8339   /* shift count is unknown then we have to form 
8340      a loop get the loop count in B : Note: we take
8341      only the lower order byte since shifting
8342      more that 32 bits make no sense anyway, ( the
8343      largest size of an object can be only 32 bits ) */  
8344
8345     
8346   pic16_aopOp(left,ic,FALSE);
8347   pic16_aopOp(result,ic,FALSE);
8348
8349   /* now move the left to the result if they are not the
8350      same */
8351   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8352       AOP_SIZE(result) > 1) {
8353
8354     size = AOP_SIZE(result);
8355     offset=0;
8356     while (size--) {
8357       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8358       if (*l == '@' && (IS_AOP_PREG(result))) {
8359
8360         pic16_emitcode("mov","a,%s",l);
8361         pic16_aopPut(AOP(result),"a",offset);
8362       } else {
8363         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8364         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8365         //pic16_aopPut(AOP(result),l,offset);
8366       }
8367       offset++;
8368     }
8369   }
8370
8371   size = AOP_SIZE(result);
8372
8373   /* if it is only one byte then */
8374   if (size == 1) {
8375     if(optimized_for_speed) {
8376       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8377       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8378       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8379       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8380       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8381       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8382       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8383       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8384       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8385       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8386       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8387       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8388     } else {
8389
8390       tlbl = newiTempLabel(NULL);
8391       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8392                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8393                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8394       }
8395
8396       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8397       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8398       pic16_emitpLabel(tlbl->key);
8399       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8400       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8401       emitSKPC;
8402       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8403     }
8404     goto release ;
8405   }
8406     
8407   if (pic16_sameRegs(AOP(left),AOP(result))) {
8408
8409     tlbl = newiTempLabel(NULL);
8410     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8411     genMultiAsm(POC_RRCF, result, size,1);
8412     pic16_emitpLabel(tlbl->key);
8413     genMultiAsm(POC_RLCF, result, size,0);
8414     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8415     emitSKPC;
8416     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8417     goto release;
8418   }
8419
8420   //tlbl = newiTempLabel(NULL);
8421   //offset = 0 ;   
8422   //tlbl1 = newiTempLabel(NULL);
8423
8424   //reAdjustPreg(AOP(result));    
8425     
8426   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8427   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8428   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8429   //MOVA(l);
8430   //pic16_emitcode("add","a,acc");         
8431   //pic16_aopPut(AOP(result),"a",offset++);
8432   //while (--size) {
8433   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8434   //  MOVA(l);
8435   //  pic16_emitcode("rlc","a");         
8436   //  pic16_aopPut(AOP(result),"a",offset++);
8437   //}
8438   //reAdjustPreg(AOP(result));
8439
8440   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8441   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8442
8443
8444   tlbl = newiTempLabel(NULL);
8445   tlbl1= newiTempLabel(NULL);
8446
8447   size = AOP_SIZE(result);
8448   offset = 1;
8449
8450   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8451
8452   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8453
8454   /* offset should be 0, 1 or 3 */
8455   
8456   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8457   emitSKPNZ;
8458   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8459
8460   pic16_emitpcode(POC_MOVWF, pctemp);
8461
8462
8463   pic16_emitpLabel(tlbl->key);
8464
8465   emitCLRC;
8466   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8467   while(--size)
8468     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8469
8470   pic16_emitpcode(POC_DECFSZ,  pctemp);
8471   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8472   pic16_emitpLabel(tlbl1->key);
8473
8474   pic16_popReleaseTempReg(pctemp);
8475
8476
8477  release:
8478   pic16_freeAsmop (right,NULL,ic,TRUE);
8479   pic16_freeAsmop(left,NULL,ic,TRUE);
8480   pic16_freeAsmop(result,NULL,ic,TRUE);
8481 }
8482
8483 /*-----------------------------------------------------------------*/
8484 /* genrshOne - right shift a one byte quantity by known count      */
8485 /*-----------------------------------------------------------------*/
8486 static void genrshOne (operand *result, operand *left,
8487                        int shCount, int sign)
8488 {
8489     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8490     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8491 }
8492
8493 /*-----------------------------------------------------------------*/
8494 /* genrshTwo - right shift two bytes by known amount != 0          */
8495 /*-----------------------------------------------------------------*/
8496 static void genrshTwo (operand *result,operand *left,
8497                        int shCount, int sign)
8498 {
8499   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8500   /* if shCount >= 8 */
8501   if (shCount >= 8) {
8502     shCount -= 8 ;
8503     if (shCount)
8504       shiftR1Left2Result(left, MSB16, result, LSB,
8505                          shCount, sign);
8506     else
8507       movLeft2Result(left, MSB16, result, LSB);
8508
8509     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8510
8511     if(sign) {
8512       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8513       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8514     }
8515   }
8516
8517   /*  1 <= shCount <= 7 */
8518   else
8519     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8520 }
8521
8522 /*-----------------------------------------------------------------*/
8523 /* shiftRLong - shift right one long from left to result           */
8524 /* offl = LSB or MSB16                                             */
8525 /*-----------------------------------------------------------------*/
8526 static void shiftRLong (operand *left, int offl,
8527                         operand *result, int sign)
8528 {
8529     int size = AOP_SIZE(result);
8530     int same = pic16_sameRegs(AOP(left),AOP(result));
8531     int i;
8532     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8533
8534         if (same && (offl == MSB16)) { //shift one byte right
8535                 for(i=MSB16;i<size;i++) {
8536                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8537                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8538                 }
8539         }
8540
8541     if(sign)
8542                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8543         else
8544                 emitCLRC;
8545
8546         if (same) {
8547                 if (offl == LSB)
8548                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8549         } else {
8550         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8551         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8552         }
8553
8554     if(offl == MSB16) {
8555         /* add sign of "a" */
8556         pic16_addSign(result, MSB32, sign);
8557         }
8558
8559         if (same) {
8560         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8561         } else {
8562         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8563         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8564         }
8565         
8566         if (same) {
8567         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8568         } else {
8569         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8570         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8571         }
8572
8573         if (same) {
8574         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8575         } else {
8576         if(offl == LSB){
8577                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8578                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8579         }
8580         }
8581 }
8582
8583 /*-----------------------------------------------------------------*/
8584 /* genrshFour - shift four byte by a known amount != 0             */
8585 /*-----------------------------------------------------------------*/
8586 static void genrshFour (operand *result, operand *left,
8587                         int shCount, int sign)
8588 {
8589   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8590   /* if shifting more that 3 bytes */
8591   if(shCount >= 24 ) {
8592     shCount -= 24;
8593     if(shCount)
8594       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8595     else
8596       movLeft2Result(left, MSB32, result, LSB);
8597
8598     pic16_addSign(result, MSB16, sign);
8599   }
8600   else if(shCount >= 16){
8601     shCount -= 16;
8602     if(shCount)
8603       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8604     else{
8605       movLeft2Result(left, MSB24, result, LSB);
8606       movLeft2Result(left, MSB32, result, MSB16);
8607     }
8608     pic16_addSign(result, MSB24, sign);
8609   }
8610   else if(shCount >= 8){
8611     shCount -= 8;
8612     if(shCount == 1)
8613       shiftRLong(left, MSB16, result, sign);
8614     else if(shCount == 0){
8615       movLeft2Result(left, MSB16, result, LSB);
8616       movLeft2Result(left, MSB24, result, MSB16);
8617       movLeft2Result(left, MSB32, result, MSB24);
8618       pic16_addSign(result, MSB32, sign);
8619     }
8620     else{ //shcount >= 2
8621       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8622       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8623       /* the last shift is signed */
8624       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8625       pic16_addSign(result, MSB32, sign);
8626     }
8627   }
8628   else{   /* 1 <= shCount <= 7 */
8629     if(shCount <= 2){
8630       shiftRLong(left, LSB, result, sign);
8631       if(shCount == 2)
8632         shiftRLong(result, LSB, result, sign);
8633     }
8634     else{
8635       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8636       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8637       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8638     }
8639   }
8640 }
8641
8642 /*-----------------------------------------------------------------*/
8643 /* genRightShiftLiteral - right shifting by known count            */
8644 /*-----------------------------------------------------------------*/
8645 static void genRightShiftLiteral (operand *left,
8646                                   operand *right,
8647                                   operand *result,
8648                                   iCode *ic,
8649                                   int sign)
8650 {    
8651   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8652   int lsize,res_size;
8653
8654   pic16_freeAsmop(right,NULL,ic,TRUE);
8655
8656   pic16_aopOp(left,ic,FALSE);
8657   pic16_aopOp(result,ic,FALSE);
8658
8659   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8660
8661 #if VIEW_SIZE
8662   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8663                  AOP_SIZE(left));
8664 #endif
8665
8666   lsize = pic16_getDataSize(left);
8667   res_size = pic16_getDataSize(result);
8668   /* test the LEFT size !!! */
8669
8670   /* I suppose that the left size >= result size */
8671   if(shCount == 0){
8672     while(res_size--)
8673       movLeft2Result(left, lsize, result, res_size);
8674   }
8675
8676   else if(shCount >= (lsize * 8)){
8677
8678     if(res_size == 1) {
8679       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8680       if(sign) {
8681         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8682         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8683       }
8684     } else {
8685
8686       if(sign) {
8687         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8688         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8689         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8690         while(res_size--)
8691           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8692
8693       } else {
8694
8695         while(res_size--)
8696           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8697       }
8698     }
8699   } else {
8700
8701     switch (res_size) {
8702     case 1:
8703       genrshOne (result,left,shCount,sign);
8704       break;
8705
8706     case 2:
8707       genrshTwo (result,left,shCount,sign);
8708       break;
8709
8710     case 4:
8711       genrshFour (result,left,shCount,sign);
8712       break;
8713     default :
8714       break;
8715     }
8716
8717   }
8718
8719   pic16_freeAsmop(left,NULL,ic,TRUE);
8720   pic16_freeAsmop(result,NULL,ic,TRUE);
8721 }
8722
8723 /*-----------------------------------------------------------------*/
8724 /* genSignedRightShift - right shift of signed number              */
8725 /*-----------------------------------------------------------------*/
8726 static void genSignedRightShift (iCode *ic)
8727 {
8728   operand *right, *left, *result;
8729   int size, offset;
8730   //  char *l;
8731   symbol *tlbl, *tlbl1 ;
8732   pCodeOp *pctemp;
8733
8734   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8735
8736   /* we do it the hard way put the shift count in b
8737      and loop thru preserving the sign */
8738   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8739
8740   right = IC_RIGHT(ic);
8741   left  = IC_LEFT(ic);
8742   result = IC_RESULT(ic);
8743
8744   pic16_aopOp(right,ic,FALSE);  
8745   pic16_aopOp(left,ic,FALSE);
8746   pic16_aopOp(result,ic,FALSE);
8747
8748
8749   if ( AOP_TYPE(right) == AOP_LIT) {
8750     genRightShiftLiteral (left,right,result,ic,1);
8751     return ;
8752   }
8753   /* shift count is unknown then we have to form 
8754      a loop get the loop count in B : Note: we take
8755      only the lower order byte since shifting
8756      more that 32 bits make no sense anyway, ( the
8757      largest size of an object can be only 32 bits ) */  
8758
8759   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8760   //pic16_emitcode("inc","b");
8761   //pic16_freeAsmop (right,NULL,ic,TRUE);
8762   //pic16_aopOp(left,ic,FALSE);
8763   //pic16_aopOp(result,ic,FALSE);
8764
8765   /* now move the left to the result if they are not the
8766      same */
8767   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8768       AOP_SIZE(result) > 1) {
8769
8770     size = AOP_SIZE(result);
8771     offset=0;
8772     while (size--) { 
8773       /*
8774         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8775         if (*l == '@' && IS_AOP_PREG(result)) {
8776
8777         pic16_emitcode("mov","a,%s",l);
8778         pic16_aopPut(AOP(result),"a",offset);
8779         } else
8780         pic16_aopPut(AOP(result),l,offset);
8781       */
8782       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8783       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8784
8785       offset++;
8786     }
8787   }
8788
8789   /* mov the highest order bit to OVR */    
8790   tlbl = newiTempLabel(NULL);
8791   tlbl1= newiTempLabel(NULL);
8792
8793   size = AOP_SIZE(result);
8794   offset = size - 1;
8795
8796   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8797
8798   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8799
8800   /* offset should be 0, 1 or 3 */
8801   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8802   emitSKPNZ;
8803   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8804
8805   pic16_emitpcode(POC_MOVWF, pctemp);
8806
8807
8808   pic16_emitpLabel(tlbl->key);
8809
8810   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8811   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8812
8813   while(--size) {
8814     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8815   }
8816
8817   pic16_emitpcode(POC_DECFSZ,  pctemp);
8818   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8819   pic16_emitpLabel(tlbl1->key);
8820
8821   pic16_popReleaseTempReg(pctemp);
8822 #if 0
8823   size = AOP_SIZE(result);
8824   offset = size - 1;
8825   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8826   pic16_emitcode("rlc","a");
8827   pic16_emitcode("mov","ov,c");
8828   /* if it is only one byte then */
8829   if (size == 1) {
8830     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8831     MOVA(l);
8832     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8833     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8834     pic16_emitcode("mov","c,ov");
8835     pic16_emitcode("rrc","a");
8836     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8837     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8838     pic16_aopPut(AOP(result),"a",0);
8839     goto release ;
8840   }
8841
8842   reAdjustPreg(AOP(result));
8843   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8844   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8845   pic16_emitcode("mov","c,ov");
8846   while (size--) {
8847     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8848     MOVA(l);
8849     pic16_emitcode("rrc","a");         
8850     pic16_aopPut(AOP(result),"a",offset--);
8851   }
8852   reAdjustPreg(AOP(result));
8853   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8854   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8855
8856  release:
8857 #endif
8858
8859   pic16_freeAsmop(left,NULL,ic,TRUE);
8860   pic16_freeAsmop(result,NULL,ic,TRUE);
8861   pic16_freeAsmop(right,NULL,ic,TRUE);
8862 }
8863
8864 /*-----------------------------------------------------------------*/
8865 /* genRightShift - generate code for right shifting                */
8866 /*-----------------------------------------------------------------*/
8867 static void genRightShift (iCode *ic)
8868 {
8869     operand *right, *left, *result;
8870     sym_link *letype ;
8871     int size, offset;
8872     char *l;
8873     symbol *tlbl, *tlbl1 ;
8874
8875     /* if signed then we do it the hard way preserve the
8876     sign bit moving it inwards */
8877     letype = getSpec(operandType(IC_LEFT(ic)));
8878     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8879
8880     if (!SPEC_USIGN(letype)) {
8881         genSignedRightShift (ic);
8882         return ;
8883     }
8884
8885     /* signed & unsigned types are treated the same : i.e. the
8886     signed is NOT propagated inwards : quoting from the
8887     ANSI - standard : "for E1 >> E2, is equivalent to division
8888     by 2**E2 if unsigned or if it has a non-negative value,
8889     otherwise the result is implementation defined ", MY definition
8890     is that the sign does not get propagated */
8891
8892     right = IC_RIGHT(ic);
8893     left  = IC_LEFT(ic);
8894     result = IC_RESULT(ic);
8895
8896     pic16_aopOp(right,ic,FALSE);
8897
8898     /* if the shift count is known then do it 
8899     as efficiently as possible */
8900     if (AOP_TYPE(right) == AOP_LIT) {
8901         genRightShiftLiteral (left,right,result,ic, 0);
8902         return ;
8903     }
8904
8905     /* shift count is unknown then we have to form 
8906     a loop get the loop count in B : Note: we take
8907     only the lower order byte since shifting
8908     more that 32 bits make no sense anyway, ( the
8909     largest size of an object can be only 32 bits ) */  
8910
8911     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8912     pic16_emitcode("inc","b");
8913     pic16_aopOp(left,ic,FALSE);
8914     pic16_aopOp(result,ic,FALSE);
8915
8916     /* now move the left to the result if they are not the
8917     same */
8918     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8919         AOP_SIZE(result) > 1) {
8920
8921         size = AOP_SIZE(result);
8922         offset=0;
8923         while (size--) {
8924             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8925             if (*l == '@' && IS_AOP_PREG(result)) {
8926
8927                 pic16_emitcode("mov","a,%s",l);
8928                 pic16_aopPut(AOP(result),"a",offset);
8929             } else
8930                 pic16_aopPut(AOP(result),l,offset);
8931             offset++;
8932         }
8933     }
8934
8935     tlbl = newiTempLabel(NULL);
8936     tlbl1= newiTempLabel(NULL);
8937     size = AOP_SIZE(result);
8938     offset = size - 1;
8939
8940     /* if it is only one byte then */
8941     if (size == 1) {
8942
8943       tlbl = newiTempLabel(NULL);
8944       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8945         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8946         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8947       }
8948
8949       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8950       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8951       pic16_emitpLabel(tlbl->key);
8952       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8953       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8954       emitSKPC;
8955       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8956
8957       goto release ;
8958     }
8959
8960     reAdjustPreg(AOP(result));
8961     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8962     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8963     CLRC;
8964     while (size--) {
8965         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8966         MOVA(l);
8967         pic16_emitcode("rrc","a");         
8968         pic16_aopPut(AOP(result),"a",offset--);
8969     }
8970     reAdjustPreg(AOP(result));
8971
8972     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8973     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8974
8975 release:
8976     pic16_freeAsmop(left,NULL,ic,TRUE);
8977     pic16_freeAsmop (right,NULL,ic,TRUE);
8978     pic16_freeAsmop(result,NULL,ic,TRUE);
8979 }
8980
8981 /*-----------------------------------------------------------------*/
8982 /* genUnpackBits - generates code for unpacking bits               */
8983 /*-----------------------------------------------------------------*/
8984 static void genUnpackBits (operand *result, char *rname, int ptype)
8985 {    
8986     int shCnt ;
8987     int rlen = 0 ;
8988     sym_link *etype;
8989     int offset = 0 ;
8990
8991         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8992         etype = getSpec(operandType(result));
8993
8994         /* read the first byte  */
8995         switch (ptype) {
8996                 case POINTER:
8997                 case IPOINTER:
8998                 case PPOINTER:
8999                 case FPOINTER:
9000                 case GPOINTER:
9001                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9002                         break;
9003                 case CPOINTER:
9004                         pic16_emitcode("clr","a");
9005                         pic16_emitcode("movc","a","@a+dptr");
9006                         break;
9007         }
9008         
9009
9010         /* if we have bitdisplacement then it fits   */
9011         /* into this byte completely or if length is */
9012         /* less than a byte                          */
9013         if ((shCnt = SPEC_BSTR(etype)) || 
9014                 (SPEC_BLEN(etype) <= 8))  {
9015
9016                 /* shift right acc */
9017                 AccRsh(shCnt, 0);
9018
9019                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9020                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
9021
9022 /* VR -- normally I would use the following, but since we use the hack,
9023  * to avoid the masking from AccRsh, why not mask it right now? */
9024
9025 /*
9026                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
9027 */
9028
9029                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9030           return ;
9031         }
9032
9033
9034
9035         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9036         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9037         exit(-1);
9038
9039     /* bit field did not fit in a byte  */
9040     rlen = SPEC_BLEN(etype) - 8;
9041     pic16_aopPut(AOP(result),"a",offset++);
9042
9043     while (1)  {
9044
9045         switch (ptype) {
9046         case POINTER:
9047         case IPOINTER:
9048             pic16_emitcode("inc","%s",rname);
9049             pic16_emitcode("mov","a,@%s",rname);
9050             break;
9051             
9052         case PPOINTER:
9053             pic16_emitcode("inc","%s",rname);
9054             pic16_emitcode("movx","a,@%s",rname);
9055             break;
9056
9057         case FPOINTER:
9058             pic16_emitcode("inc","dptr");
9059             pic16_emitcode("movx","a,@dptr");
9060             break;
9061             
9062         case CPOINTER:
9063             pic16_emitcode("clr","a");
9064             pic16_emitcode("inc","dptr");
9065             pic16_emitcode("movc","a","@a+dptr");
9066             break;
9067             
9068         case GPOINTER:
9069             pic16_emitcode("inc","dptr");
9070             pic16_emitcode("lcall","__gptrget");
9071             break;
9072         }
9073
9074         rlen -= 8;            
9075         /* if we are done */
9076         if ( rlen <= 0 )
9077             break ;
9078         
9079         pic16_aopPut(AOP(result),"a",offset++);
9080                               
9081     }
9082     
9083     if (rlen) {
9084         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9085         pic16_aopPut(AOP(result),"a",offset);          
9086     }
9087     
9088     return ;
9089 }
9090
9091
9092 static void genDataPointerGet(operand *left,
9093                               operand *result,
9094                               iCode *ic)
9095 {
9096   int size, offset = 0, leoffset=0 ;
9097
9098         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9099         pic16_aopOp(result, ic, FALSE);
9100
9101         size = AOP_SIZE(result);
9102 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9103
9104
9105 #if 0
9106         /* The following tests may save a redudant movff instruction when
9107          * accessing unions */
9108          
9109         /* if they are the same */
9110         if (operandsEqu (left, result)) {
9111                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9112                 goto release;
9113         }
9114 #endif
9115
9116 #if 0
9117         /* if they are the same registers */
9118         if (pic16_sameRegs(AOP(left),AOP(result))) {
9119                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9120                 goto release;
9121         }
9122 #endif
9123
9124 #if 0
9125         if ( AOP_TYPE(left) == AOP_PCODE) {
9126                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9127                                 AOP(left)->aopu.pcop->name,
9128                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9129                                 PCOR(AOP(left)->aopu.pcop)->instance:
9130                                 PCOI(AOP(left)->aopu.pcop)->offset);
9131         }
9132 #endif
9133
9134         if(AOP(left)->aopu.pcop->type == PO_DIR)
9135                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9136
9137         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9138
9139         while (size--) {
9140                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9141                 
9142                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9143                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9144                         mov2w(AOP(left), offset); // patch 8
9145                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9146                 } else {
9147                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9148                                 pic16_popGet(AOP(left), offset), //patch 8
9149                                 pic16_popGet(AOP(result), offset)));
9150                 }
9151
9152                 offset++;
9153                 leoffset++;
9154         }
9155
9156 //release:
9157     pic16_freeAsmop(result,NULL,ic,TRUE);
9158 }
9159
9160 void pic16_loadFSR0(operand *op)
9161 {
9162         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9163 }
9164
9165
9166 /*-----------------------------------------------------------------*/
9167 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9168 /*-----------------------------------------------------------------*/
9169 static void genNearPointerGet (operand *left, 
9170                                operand *result, 
9171                                iCode *ic)
9172 {
9173     asmop *aop = NULL;
9174     //regs *preg = NULL ;
9175     sym_link *rtype, *retype;
9176     sym_link *ltype = operandType(left);    
9177
9178         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9179         rtype = operandType(result);
9180         retype= getSpec(rtype);
9181     
9182         pic16_aopOp(left,ic,FALSE);
9183
9184         pic16_DumpOp("(left)",left);
9185         pic16_DumpOp("(result)",result);
9186
9187         /* if left is rematerialisable and
9188          * result is not bit variable type and
9189          * the left is pointer to data space i.e
9190          * lower 128 bytes of space */
9191         if (AOP_TYPE(left) == AOP_PCODE
9192                 && !IS_BITFIELD(retype)
9193                 && DCL_TYPE(ltype) == POINTER) {
9194
9195                 genDataPointerGet (left,result,ic);
9196                 pic16_freeAsmop(left, NULL, ic, TRUE);
9197           return ;
9198         }
9199     
9200         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9201
9202         /* if the value is already in a pointer register
9203          * then don't need anything more */
9204         if (!AOP_INPREG(AOP(left))) {
9205                 /* otherwise get a free pointer register */
9206                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9207                 
9208                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9209                 if( (AOP_TYPE(left) == AOP_PCODE) 
9210                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9211                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9212                 {
9213                         pic16_loadFSR0( left );  // patch 10
9214                 } else {
9215                         // set up FSR0 with address from left
9216                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9217                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9218                 }
9219         }
9220 //       else
9221 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9222     
9223         pic16_aopOp (result,ic,FALSE);
9224     
9225       /* if bitfield then unpack the bits */
9226     if (IS_BITFIELD(retype)) 
9227         genUnpackBits (result, NULL, POINTER);
9228     else {
9229         /* we have can just get the values */
9230       int size = AOP_SIZE(result);
9231       int offset = 0;   
9232         
9233       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9234
9235
9236         /* fsr0 is loaded already -- VR */
9237 //      pic16_loadFSR0( left );
9238
9239 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9240 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9241       while(size--) {
9242
9243         if(size) {
9244                 pic16_emitpcode(POC_MOVFF,
9245                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9246                                 pic16_popGet(AOP(result), offset++)));
9247         } else {
9248                 pic16_emitpcode(POC_MOVFF,
9249                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9250                                 pic16_popGet(AOP(result), offset++)));
9251         }
9252       }
9253 #if 0
9254 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9255 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9256         if(size)
9257           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9258 #endif
9259 /*
9260         while (size--) {
9261             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9262
9263                 pic16_emitcode("mov","a,@%s",rname);
9264                 pic16_aopPut(AOP(result),"a",offset);
9265             } else {
9266                 sprintf(buffer,"@%s",rname);
9267                 pic16_aopPut(AOP(result),buffer,offset);
9268             }
9269             offset++ ;
9270             if (size)
9271                 pic16_emitcode("inc","%s",rname);
9272         }
9273 */
9274     }
9275
9276     /* now some housekeeping stuff */
9277     if (aop) {
9278         /* we had to allocate for this iCode */
9279     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9280         pic16_freeAsmop(NULL,aop,ic,TRUE);
9281     } else { 
9282         /* we did not allocate which means left
9283            already in a pointer register, then
9284            if size > 0 && this could be used again
9285            we have to point it back to where it 
9286            belongs */
9287     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9288         if (AOP_SIZE(result) > 1 &&
9289             !OP_SYMBOL(left)->remat &&
9290             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9291               ic->depth )) {
9292 //          int size = AOP_SIZE(result) - 1;
9293 //          while (size--)
9294 //              pic16_emitcode("dec","%s",rname);
9295         }
9296     }
9297
9298     /* done */
9299     pic16_freeAsmop(left,NULL,ic,TRUE);
9300     pic16_freeAsmop(result,NULL,ic,TRUE);
9301      
9302 }
9303
9304 /*-----------------------------------------------------------------*/
9305 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9306 /*-----------------------------------------------------------------*/
9307 static void genPagedPointerGet (operand *left, 
9308                                operand *result, 
9309                                iCode *ic)
9310 {
9311     asmop *aop = NULL;
9312     regs *preg = NULL ;
9313     char *rname ;
9314     sym_link *rtype, *retype;    
9315
9316     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9317
9318     rtype = operandType(result);
9319     retype= getSpec(rtype);
9320     
9321     pic16_aopOp(left,ic,FALSE);
9322
9323   /* if the value is already in a pointer register
9324        then don't need anything more */
9325     if (!AOP_INPREG(AOP(left))) {
9326         /* otherwise get a free pointer register */
9327         aop = newAsmop(0);
9328         preg = getFreePtr(ic,&aop,FALSE);
9329         pic16_emitcode("mov","%s,%s",
9330                 preg->name,
9331                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9332         rname = preg->name ;
9333     } else
9334         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9335     
9336     pic16_freeAsmop(left,NULL,ic,TRUE);
9337     pic16_aopOp (result,ic,FALSE);
9338
9339     /* if bitfield then unpack the bits */
9340     if (IS_BITFIELD(retype)) 
9341         genUnpackBits (result,rname,PPOINTER);
9342     else {
9343         /* we have can just get the values */
9344         int size = AOP_SIZE(result);
9345         int offset = 0 ;        
9346         
9347         while (size--) {
9348             
9349             pic16_emitcode("movx","a,@%s",rname);
9350             pic16_aopPut(AOP(result),"a",offset);
9351             
9352             offset++ ;
9353             
9354             if (size)
9355                 pic16_emitcode("inc","%s",rname);
9356         }
9357     }
9358
9359     /* now some housekeeping stuff */
9360     if (aop) {
9361         /* we had to allocate for this iCode */
9362         pic16_freeAsmop(NULL,aop,ic,TRUE);
9363     } else { 
9364         /* we did not allocate which means left
9365            already in a pointer register, then
9366            if size > 0 && this could be used again
9367            we have to point it back to where it 
9368            belongs */
9369         if (AOP_SIZE(result) > 1 &&
9370             !OP_SYMBOL(left)->remat &&
9371             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9372               ic->depth )) {
9373             int size = AOP_SIZE(result) - 1;
9374             while (size--)
9375                 pic16_emitcode("dec","%s",rname);
9376         }
9377     }
9378
9379     /* done */
9380     pic16_freeAsmop(result,NULL,ic,TRUE);
9381     
9382         
9383 }
9384
9385 /*-----------------------------------------------------------------*/
9386 /* genFarPointerGet - gget value from far space                    */
9387 /*-----------------------------------------------------------------*/
9388 static void genFarPointerGet (operand *left,
9389                               operand *result, iCode *ic)
9390 {
9391     int size, offset ;
9392     sym_link *retype = getSpec(operandType(result));
9393
9394     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9395
9396     pic16_aopOp(left,ic,FALSE);
9397
9398     /* if the operand is already in dptr 
9399     then we do nothing else we move the value to dptr */
9400     if (AOP_TYPE(left) != AOP_STR) {
9401         /* if this is remateriazable */
9402         if (AOP_TYPE(left) == AOP_IMMD)
9403             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9404         else { /* we need to get it byte by byte */
9405             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9406             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9407             if (options.model == MODEL_FLAT24)
9408             {
9409                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9410             }
9411         }
9412     }
9413     /* so dptr know contains the address */
9414     pic16_freeAsmop(left,NULL,ic,TRUE);
9415     pic16_aopOp(result,ic,FALSE);
9416
9417     /* if bit then unpack */
9418     if (IS_BITFIELD(retype)) 
9419         genUnpackBits(result,"dptr",FPOINTER);
9420     else {
9421         size = AOP_SIZE(result);
9422         offset = 0 ;
9423
9424         while (size--) {
9425             pic16_emitcode("movx","a,@dptr");
9426             pic16_aopPut(AOP(result),"a",offset++);
9427             if (size)
9428                 pic16_emitcode("inc","dptr");
9429         }
9430     }
9431
9432     pic16_freeAsmop(result,NULL,ic,TRUE);
9433 }
9434 #if 0
9435 /*-----------------------------------------------------------------*/
9436 /* genCodePointerGet - get value from code space                  */
9437 /*-----------------------------------------------------------------*/
9438 static void genCodePointerGet (operand *left,
9439                                 operand *result, iCode *ic)
9440 {
9441     int size, offset ;
9442     sym_link *retype = getSpec(operandType(result));
9443
9444     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9445
9446     pic16_aopOp(left,ic,FALSE);
9447
9448     /* if the operand is already in dptr 
9449     then we do nothing else we move the value to dptr */
9450     if (AOP_TYPE(left) != AOP_STR) {
9451         /* if this is remateriazable */
9452         if (AOP_TYPE(left) == AOP_IMMD)
9453             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9454         else { /* we need to get it byte by byte */
9455             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9456             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9457             if (options.model == MODEL_FLAT24)
9458             {
9459                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9460             }
9461         }
9462     }
9463     /* so dptr know contains the address */
9464     pic16_freeAsmop(left,NULL,ic,TRUE);
9465     pic16_aopOp(result,ic,FALSE);
9466
9467     /* if bit then unpack */
9468     if (IS_BITFIELD(retype)) 
9469         genUnpackBits(result,"dptr",CPOINTER);
9470     else {
9471         size = AOP_SIZE(result);
9472         offset = 0 ;
9473
9474         while (size--) {
9475             pic16_emitcode("clr","a");
9476             pic16_emitcode("movc","a,@a+dptr");
9477             pic16_aopPut(AOP(result),"a",offset++);
9478             if (size)
9479                 pic16_emitcode("inc","dptr");
9480         }
9481     }
9482
9483     pic16_freeAsmop(result,NULL,ic,TRUE);
9484 }
9485 #endif
9486 /*-----------------------------------------------------------------*/
9487 /* genGenPointerGet - gget value from generic pointer space        */
9488 /*-----------------------------------------------------------------*/
9489 static void genGenPointerGet (operand *left,
9490                               operand *result, iCode *ic)
9491 {
9492   int size, offset, lit;
9493   sym_link *retype = getSpec(operandType(result));
9494
9495         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9496         pic16_aopOp(left,ic,FALSE);
9497         pic16_aopOp(result,ic,FALSE);
9498         size = AOP_SIZE(result);
9499
9500         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9501
9502         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9503
9504                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9505                 // load FSR0 from immediate
9506                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9507
9508 //              pic16_loadFSR0( left );
9509
9510                 offset = 0;
9511                 while(size--) {
9512                         if(size) {
9513                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9514                         } else {
9515                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9516                         }
9517                         offset++;
9518                 }
9519                 goto release;
9520
9521         }
9522         else { /* we need to get it byte by byte */
9523                 // set up FSR0 with address from left
9524                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9525                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9526
9527                 offset = 0 ;
9528
9529                 while(size--) {
9530                         if(size) {
9531                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9532                         } else {
9533                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9534                         }
9535                         offset++;
9536                 }
9537                 goto release;
9538         }
9539
9540   /* if bit then unpack */
9541         if (IS_BITFIELD(retype)) 
9542                 genUnpackBits(result,"BAD",GPOINTER);
9543
9544         release:
9545         pic16_freeAsmop(left,NULL,ic,TRUE);
9546         pic16_freeAsmop(result,NULL,ic,TRUE);
9547
9548 }
9549
9550 /*-----------------------------------------------------------------*/
9551 /* genConstPointerGet - get value from const generic pointer space */
9552 /*-----------------------------------------------------------------*/
9553 static void genConstPointerGet (operand *left,
9554                                 operand *result, iCode *ic)
9555 {
9556   //sym_link *retype = getSpec(operandType(result));
9557   // symbol *albl = newiTempLabel(NULL);        // patch 15
9558   // symbol *blbl = newiTempLabel(NULL);        //
9559   // PIC_OPCODE poc;                            // patch 15
9560   int size;
9561   int offset = 0;
9562
9563   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9564   pic16_aopOp(left,ic,FALSE);
9565   pic16_aopOp(result,ic,TRUE);
9566   size = AOP_SIZE(result);
9567
9568   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9569
9570   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9571 #if 0                                                                   // patch 15
9572   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9573   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9574   pic16_emitpLabel(albl->key);
9575
9576   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9577     
9578   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9579   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9580   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9581   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9582   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9583
9584   pic16_emitpLabel(blbl->key);
9585
9586   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9587 #endif                                                                  // patch 15
9588
9589
9590   // set up table pointer
9591   if( (AOP_TYPE(left) == AOP_PCODE) 
9592       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9593           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9594     {
9595       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9596       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9597       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9598       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9599       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9600       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9601     }
9602   else
9603     {
9604       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9605       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9606       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9607     }
9608
9609
9610   while(size--)
9611     {
9612       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9613       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9614       offset++;
9615     }
9616                                                                         // .... patch 15
9617   pic16_freeAsmop(left,NULL,ic,TRUE);
9618   pic16_freeAsmop(result,NULL,ic,TRUE);
9619
9620 }
9621 /*-----------------------------------------------------------------*/
9622 /* genPointerGet - generate code for pointer get                   */
9623 /*-----------------------------------------------------------------*/
9624 static void genPointerGet (iCode *ic)
9625 {
9626     operand *left, *result ;
9627     sym_link *type, *etype;
9628     int p_type;
9629
9630     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9631
9632     left = IC_LEFT(ic);
9633     result = IC_RESULT(ic) ;
9634
9635     /* depending on the type of pointer we need to
9636     move it to the correct pointer register */
9637     type = operandType(left);
9638     etype = getSpec(type);
9639
9640 #if 0
9641     if (IS_PTR_CONST(type))
9642 #else
9643     if (IS_CODEPTR(type))
9644 #endif
9645       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9646
9647     /* if left is of type of pointer then it is simple */
9648     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9649         p_type = DCL_TYPE(type);
9650     else {
9651         /* we have to go by the storage class */
9652         p_type = PTR_TYPE(SPEC_OCLS(etype));
9653
9654         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9655
9656         if (SPEC_OCLS(etype)->codesp ) {
9657           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9658           //p_type = CPOINTER ; 
9659         }
9660         else
9661             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9662               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9663                /*p_type = FPOINTER ;*/ 
9664             else
9665                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9666                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9667 /*                  p_type = PPOINTER; */
9668                 else
9669                     if (SPEC_OCLS(etype) == idata )
9670                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9671 /*                      p_type = IPOINTER; */
9672                     else
9673                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9674 /*                      p_type = POINTER ; */
9675     }
9676
9677     /* now that we have the pointer type we assign
9678     the pointer values */
9679     switch (p_type) {
9680
9681     case POINTER:       
9682     case IPOINTER:
9683         genNearPointerGet (left,result,ic);
9684         break;
9685
9686     case PPOINTER:
9687         genPagedPointerGet(left,result,ic);
9688         break;
9689
9690     case FPOINTER:
9691         genFarPointerGet (left,result,ic);
9692         break;
9693
9694     case CPOINTER:
9695         genConstPointerGet (left,result,ic);
9696         //pic16_emitcodePointerGet (left,result,ic);
9697         break;
9698
9699     case GPOINTER:
9700 #if 0
9701       if (IS_PTR_CONST(type))
9702         genConstPointerGet (left,result,ic);
9703       else
9704 #endif
9705         genGenPointerGet (left,result,ic);
9706       break;
9707     }
9708
9709 }
9710
9711 /*-----------------------------------------------------------------*/
9712 /* genPackBits - generates code for packed bit storage             */
9713 /*-----------------------------------------------------------------*/
9714 static void genPackBits (sym_link    *etype ,
9715                          operand *right ,
9716                          char *rname, int p_type)
9717 {
9718   int shCnt = 0 ;
9719   int offset = 0  ;
9720   int rLen = 0 ;
9721   int blen, bstr ;   
9722   char *l ;
9723
9724         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9725         blen = SPEC_BLEN(etype);
9726         bstr = SPEC_BSTR(etype);
9727
9728         if(AOP_TYPE(right) == AOP_LIT) {
9729                 if((blen == 1) && (bstr < 8)) {
9730                   unsigned long lit;
9731                         /* it is a single bit, so use the appropriate bit instructions */
9732
9733                         DEBUGpic16_emitcode (";","%s %d optimize bit assignment",__FUNCTION__,__LINE__);
9734
9735                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9736 //                      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9737                         if(lit) {
9738                                 pic16_emitpcode(POC_BSF,
9739                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9740                         } else {
9741                                 pic16_emitpcode(POC_BCF,
9742                                         pic16_popCopyGPR2Bit(pic16_popCopyReg(&pic16_pc_indf0), bstr));
9743                         }
9744         
9745                   return;
9746                 }
9747
9748                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9749                 offset++;
9750         } else
9751                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9752
9753         /* if the bit lenth is less than or    */
9754         /* it exactly fits a byte then         */
9755         if((shCnt=SPEC_BSTR(etype))
9756                 || SPEC_BLEN(etype) <= 8 )  {
9757
9758                 /* shift left acc */
9759                 AccLsh(shCnt);
9760
9761                 /* using PRODL as a temporary register here */
9762                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9763
9764                 switch (p_type) {
9765                         case FPOINTER:
9766                         case POINTER:
9767                         case GPOINTER:
9768                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9769 //                              pic16_emitcode ("mov","b,a");
9770 //                              pic16_emitcode("mov","a,@%s",rname);
9771                                 break;
9772                 }
9773 #if 1
9774                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9775                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9776                                         (unsigned char)(0xff >> (8-bstr))) ));
9777                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9778                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9779 #endif
9780
9781           return;
9782         }
9783
9784
9785         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9786         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9787         exit(-1);
9788
9789
9790     /* if we r done */
9791     if ( SPEC_BLEN(etype) <= 8 )
9792         return ;
9793
9794     pic16_emitcode("inc","%s",rname);
9795     rLen = SPEC_BLEN(etype) ;     
9796
9797
9798
9799     /* now generate for lengths greater than one byte */
9800     while (1) {
9801
9802         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9803
9804         rLen -= 8 ;
9805         if (rLen <= 0 )
9806             break ;
9807
9808         switch (p_type) {
9809             case POINTER:
9810                 if (*l == '@') {
9811                     MOVA(l);
9812                     pic16_emitcode("mov","@%s,a",rname);
9813                 } else
9814                     pic16_emitcode("mov","@%s,%s",rname,l);
9815                 break;
9816
9817             case FPOINTER:
9818                 MOVA(l);
9819                 pic16_emitcode("movx","@dptr,a");
9820                 break;
9821
9822             case GPOINTER:
9823                 MOVA(l);
9824                 DEBUGpic16_emitcode(";lcall","__gptrput");
9825                 break;  
9826         }   
9827         pic16_emitcode ("inc","%s",rname);
9828     }
9829
9830     MOVA(l);
9831
9832     /* last last was not complete */
9833     if (rLen)   {
9834         /* save the byte & read byte */
9835         switch (p_type) {
9836             case POINTER:
9837                 pic16_emitcode ("mov","b,a");
9838                 pic16_emitcode("mov","a,@%s",rname);
9839                 break;
9840
9841             case FPOINTER:
9842                 pic16_emitcode ("mov","b,a");
9843                 pic16_emitcode("movx","a,@dptr");
9844                 break;
9845
9846             case GPOINTER:
9847                 pic16_emitcode ("push","b");
9848                 pic16_emitcode ("push","acc");
9849                 pic16_emitcode ("lcall","__gptrget");
9850                 pic16_emitcode ("pop","b");
9851                 break;
9852         }
9853
9854         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9855         pic16_emitcode ("orl","a,b");
9856     }
9857
9858     if (p_type == GPOINTER)
9859         pic16_emitcode("pop","b");
9860
9861     switch (p_type) {
9862
9863     case POINTER:
9864         pic16_emitcode("mov","@%s,a",rname);
9865         break;
9866         
9867     case FPOINTER:
9868         pic16_emitcode("movx","@dptr,a");
9869         break;
9870         
9871     case GPOINTER:
9872         DEBUGpic16_emitcode(";lcall","__gptrput");
9873         break;                  
9874     }
9875 }
9876 /*-----------------------------------------------------------------*/
9877 /* genDataPointerSet - remat pointer to data space                 */
9878 /*-----------------------------------------------------------------*/
9879 static void genDataPointerSet(operand *right,
9880                               operand *result,
9881                               iCode *ic)
9882 {
9883     int size, offset = 0, resoffset=0 ;
9884
9885     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9886     pic16_aopOp(right,ic,FALSE);
9887
9888     size = AOP_SIZE(right);
9889
9890 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9891
9892 #if 0
9893     if ( AOP_TYPE(result) == AOP_PCODE) {
9894       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9895               AOP(result)->aopu.pcop->name,
9896                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9897               PCOR(AOP(result)->aopu.pcop)->instance:
9898               PCOI(AOP(result)->aopu.pcop)->offset);
9899     }
9900 #endif
9901
9902         if(AOP(result)->aopu.pcop->type == PO_DIR)
9903                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9904
9905         while (size--) {
9906                 if (AOP_TYPE(right) == AOP_LIT) {
9907                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9908
9909                         lit = lit >> (8*offset);
9910                         if(lit&0xff) {
9911                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9912                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9913                         } else {
9914                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9915                         }
9916                 } else {
9917                         mov2w(AOP(right), offset);
9918                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9919                 }
9920                 offset++;
9921                 resoffset++;
9922         }
9923
9924     pic16_freeAsmop(right,NULL,ic,TRUE);
9925 }
9926
9927
9928
9929 /*-----------------------------------------------------------------*/
9930 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9931 /*-----------------------------------------------------------------*/
9932 static void genNearPointerSet (operand *right,
9933                                operand *result, 
9934                                iCode *ic)
9935 {
9936   asmop *aop = NULL;
9937   char *l;
9938   sym_link *retype;
9939   sym_link *ptype = operandType(result);
9940   sym_link *resetype;
9941     
9942         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9943         retype= getSpec(operandType(right));
9944         resetype = getSpec(operandType(result));
9945   
9946         pic16_aopOp(result,ic,FALSE);
9947     
9948         /* if the result is rematerializable &
9949          * in data space & not a bit variable */
9950         
9951         /* and result is not a bit variable */
9952         if (AOP_TYPE(result) == AOP_PCODE
9953 //              && AOP_TYPE(result) == AOP_IMMD
9954                 && DCL_TYPE(ptype) == POINTER
9955                 && !IS_BITFIELD(retype)
9956                 && !IS_BITFIELD(resetype)) {
9957
9958                 genDataPointerSet (right,result,ic);
9959                 pic16_freeAsmop(result,NULL,ic,TRUE);
9960           return;
9961         }
9962
9963         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9964         pic16_aopOp(right,ic,FALSE);
9965         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9966
9967         /* if the value is already in a pointer register
9968          * then don't need anything more */
9969         if (!AOP_INPREG(AOP(result))) {
9970                 /* otherwise get a free pointer register */
9971                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9972
9973                 if( (AOP_TYPE(result) == AOP_PCODE) 
9974                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
9975                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
9976                 {
9977                         pic16_loadFSR0( result );  // patch 10
9978                 } else {
9979                         // set up FSR0 with address of result
9980                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9981                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9982                 }
9983
9984         }
9985 //      else
9986 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9987
9988         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9989
9990         /* if bitfield then unpack the bits */
9991         if (IS_BITFIELD(resetype)) {
9992                 genPackBits (resetype, right, NULL, POINTER);
9993         } else {
9994                 /* we have can just get the values */
9995           int size = AOP_SIZE(right);
9996           int offset = 0 ;    
9997
9998                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9999                 while (size--) {
10000                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10001                         if (*l == '@' ) {
10002                                 //MOVA(l);
10003                                 //pic16_emitcode("mov","@%s,a",rname);
10004                                 pic16_emitcode("movf","indf0,w ;1");
10005                         } else {
10006
10007                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
10008                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
10009                                         if (size) {                                                                     // 
10010                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
10011                                         } else {                                                                        // 
10012                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
10013                                         }                                                                               // 
10014                                 } else { // no literal                                                                  // 
10015                                         if(size) {                                                                      // 
10016                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10017                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10018                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
10019                                         } else {                                                                        // 
10020                                                 pic16_emitpcode(POC_MOVFF,                                              // 
10021                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
10022                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
10023                                         }                                                                               //
10024                                 }                                                                                       // patch 10
10025                         }
10026                         offset++;
10027                 }
10028         }
10029
10030         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10031         /* now some housekeeping stuff */
10032         if (aop) {
10033                 /* we had to allocate for this iCode */
10034                 pic16_freeAsmop(NULL,aop,ic,TRUE);
10035         } else { 
10036                 /* we did not allocate which means left
10037                  * already in a pointer register, then
10038                  * if size > 0 && this could be used again
10039                  * we have to point it back to where it 
10040                  * belongs */
10041                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10042                 if (AOP_SIZE(right) > 1
10043                         && !OP_SYMBOL(result)->remat
10044                         && ( OP_SYMBOL(result)->liveTo > ic->seq
10045                                 || ic->depth )) {
10046
10047                   int size = AOP_SIZE(right) - 1;
10048
10049                         while (size--)
10050                                 pic16_emitcode("decf","fsr0,f");
10051                         //pic16_emitcode("dec","%s",rname);
10052                 }
10053         }
10054
10055         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10056         /* done */
10057 //release:
10058         pic16_freeAsmop(right,NULL,ic,TRUE);
10059         pic16_freeAsmop(result,NULL,ic,TRUE);
10060 }
10061
10062 /*-----------------------------------------------------------------*/
10063 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10064 /*-----------------------------------------------------------------*/
10065 static void genPagedPointerSet (operand *right,
10066                                operand *result, 
10067                                iCode *ic)
10068 {
10069     asmop *aop = NULL;
10070     regs *preg = NULL ;
10071     char *rname , *l;
10072     sym_link *retype;
10073        
10074     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10075
10076     retype= getSpec(operandType(right));
10077     
10078     pic16_aopOp(result,ic,FALSE);
10079     
10080     /* if the value is already in a pointer register
10081        then don't need anything more */
10082     if (!AOP_INPREG(AOP(result))) {
10083         /* otherwise get a free pointer register */
10084         aop = newAsmop(0);
10085         preg = getFreePtr(ic,&aop,FALSE);
10086         pic16_emitcode("mov","%s,%s",
10087                 preg->name,
10088                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10089         rname = preg->name ;
10090     } else
10091         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10092     
10093     pic16_freeAsmop(result,NULL,ic,TRUE);
10094     pic16_aopOp (right,ic,FALSE);
10095
10096     /* if bitfield then unpack the bits */
10097     if (IS_BITFIELD(retype)) 
10098         genPackBits (retype,right,rname,PPOINTER);
10099     else {
10100         /* we have can just get the values */
10101         int size = AOP_SIZE(right);
10102         int offset = 0 ;        
10103         
10104         while (size--) {
10105             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10106             
10107             MOVA(l);
10108             pic16_emitcode("movx","@%s,a",rname);
10109
10110             if (size)
10111                 pic16_emitcode("inc","%s",rname);
10112
10113             offset++;
10114         }
10115     }
10116     
10117     /* now some housekeeping stuff */
10118     if (aop) {
10119         /* we had to allocate for this iCode */
10120         pic16_freeAsmop(NULL,aop,ic,TRUE);
10121     } else { 
10122         /* we did not allocate which means left
10123            already in a pointer register, then
10124            if size > 0 && this could be used again
10125            we have to point it back to where it 
10126            belongs */
10127         if (AOP_SIZE(right) > 1 &&
10128             !OP_SYMBOL(result)->remat &&
10129             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10130               ic->depth )) {
10131             int size = AOP_SIZE(right) - 1;
10132             while (size--)
10133                 pic16_emitcode("dec","%s",rname);
10134         }
10135     }
10136
10137     /* done */
10138     pic16_freeAsmop(right,NULL,ic,TRUE);
10139     
10140         
10141 }
10142
10143 /*-----------------------------------------------------------------*/
10144 /* genFarPointerSet - set value from far space                     */
10145 /*-----------------------------------------------------------------*/
10146 static void genFarPointerSet (operand *right,
10147                               operand *result, iCode *ic)
10148 {
10149     int size, offset ;
10150     sym_link *retype = getSpec(operandType(right));
10151
10152     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10153     pic16_aopOp(result,ic,FALSE);
10154
10155     /* if the operand is already in dptr 
10156     then we do nothing else we move the value to dptr */
10157     if (AOP_TYPE(result) != AOP_STR) {
10158         /* if this is remateriazable */
10159         if (AOP_TYPE(result) == AOP_IMMD)
10160             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10161         else { /* we need to get it byte by byte */
10162             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10163             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10164             if (options.model == MODEL_FLAT24)
10165             {
10166                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10167             }
10168         }
10169     }
10170     /* so dptr know contains the address */
10171     pic16_freeAsmop(result,NULL,ic,TRUE);
10172     pic16_aopOp(right,ic,FALSE);
10173
10174     /* if bit then unpack */
10175     if (IS_BITFIELD(retype)) 
10176         genPackBits(retype,right,"dptr",FPOINTER);
10177     else {
10178         size = AOP_SIZE(right);
10179         offset = 0 ;
10180
10181         while (size--) {
10182             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10183             MOVA(l);
10184             pic16_emitcode("movx","@dptr,a");
10185             if (size)
10186                 pic16_emitcode("inc","dptr");
10187         }
10188     }
10189
10190     pic16_freeAsmop(right,NULL,ic,TRUE);
10191 }
10192
10193 /*-----------------------------------------------------------------*/
10194 /* genGenPointerSet - set value from generic pointer space         */
10195 /*-----------------------------------------------------------------*/
10196 static void genGenPointerSet (operand *right,
10197                               operand *result, iCode *ic)
10198 {
10199         int i, size, offset, lit;
10200         sym_link *retype = getSpec(operandType(right));
10201
10202         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10203
10204         pic16_aopOp(result,ic,FALSE);
10205         pic16_aopOp(right,ic,FALSE);
10206         size = AOP_SIZE(right);
10207         offset = 0;
10208
10209         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10210
10211         /* if the operand is already in dptr 
10212                 then we do nothing else we move the value to dptr */
10213         if (AOP_TYPE(result) != AOP_STR) {
10214                 /* if this is remateriazable */
10215                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10216                 // WARNING: anythig until "else" is untested!
10217                 if (AOP_TYPE(result) == AOP_IMMD) {
10218                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10219                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10220                         // load FSR0 from immediate
10221                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10222                         offset = 0;
10223                         while(size--) {
10224                                 if(size) {
10225                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10226                                 } else {
10227                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10228                                 }
10229                                 offset++;
10230                         }
10231                         goto release;
10232                 }
10233                 else { /* we need to get it byte by byte */
10234                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10235                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10236
10237                         // set up FSR0 with address of result
10238                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10239                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10240
10241                         /* hack hack! see if this the FSR. If so don't load W */
10242                         if(AOP_TYPE(right) != AOP_ACC) {
10243
10244                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10245
10246                                 if(AOP_TYPE(right) == AOP_LIT)
10247                                 {
10248                                         // copy literal
10249                                         // note: pic16_popGet handles sign extension
10250                                         for(i=0;i<size;i++) {
10251                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10252                                                 if(i < size-1)
10253                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10254                                                 else
10255                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10256                                         }
10257                                 } else {
10258                                         // copy regs
10259
10260                                         for(i=0;i<size;i++) {
10261                                                 if(i < size-1)
10262                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10263                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10264                                                 else
10265                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10266                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10267                                         }
10268                                 }
10269                                 goto release;
10270                         } 
10271                         // right = ACC
10272                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10273                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10274                         goto release;
10275         } // if (AOP_TYPE(result) != AOP_IMMD)
10276
10277         } // if (AOP_TYPE(result) != AOP_STR)
10278         /* so dptr know contains the address */
10279
10280
10281         /* if bit then unpack */
10282         if (IS_BITFIELD(retype)) 
10283                 genPackBits(retype,right,"dptr",GPOINTER);
10284         else {
10285                 size = AOP_SIZE(right);
10286                 offset = 0 ;
10287
10288                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10289
10290                 // set up FSR0 with address of result
10291                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10292                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10293         
10294                 while (size--) {
10295                         if (AOP_TYPE(right) == AOP_LIT) {
10296                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10297                                 if (size) {
10298                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10299                                 } else {
10300                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10301                                 }
10302                         } else { // no literal
10303                                 if(size) {
10304                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10305                                 } else {
10306                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10307                                 }
10308                         }
10309                         offset++;
10310                 }
10311         }
10312
10313         release:
10314         pic16_freeAsmop(right,NULL,ic,TRUE);
10315         pic16_freeAsmop(result,NULL,ic,TRUE);
10316 }
10317
10318 /*-----------------------------------------------------------------*/
10319 /* genPointerSet - stores the value into a pointer location        */
10320 /*-----------------------------------------------------------------*/
10321 static void genPointerSet (iCode *ic)
10322 {    
10323     operand *right, *result ;
10324     sym_link *type, *etype;
10325     int p_type;
10326
10327     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10328
10329     right = IC_RIGHT(ic);
10330     result = IC_RESULT(ic) ;
10331
10332     /* depending on the type of pointer we need to
10333     move it to the correct pointer register */
10334     type = operandType(result);
10335     etype = getSpec(type);
10336     /* if left is of type of pointer then it is simple */
10337     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10338         p_type = DCL_TYPE(type);
10339     }
10340     else {
10341         /* we have to go by the storage class */
10342         p_type = PTR_TYPE(SPEC_OCLS(etype));
10343
10344 /*      if (SPEC_OCLS(etype)->codesp ) { */
10345 /*          p_type = CPOINTER ;  */
10346 /*      } */
10347 /*      else */
10348 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10349 /*              p_type = FPOINTER ; */
10350 /*          else */
10351 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10352 /*                  p_type = PPOINTER ; */
10353 /*              else */
10354 /*                  if (SPEC_OCLS(etype) == idata ) */
10355 /*                      p_type = IPOINTER ; */
10356 /*                  else */
10357 /*                      p_type = POINTER ; */
10358     }
10359
10360     /* now that we have the pointer type we assign
10361     the pointer values */
10362     switch (p_type) {
10363
10364     case POINTER:
10365     case IPOINTER:
10366         genNearPointerSet (right,result,ic);
10367         break;
10368
10369     case PPOINTER:
10370         genPagedPointerSet (right,result,ic);
10371         break;
10372
10373     case FPOINTER:
10374         genFarPointerSet (right,result,ic);
10375         break;
10376
10377     case GPOINTER:
10378         genGenPointerSet (right,result,ic);
10379         break;
10380
10381     default:
10382       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10383               "genPointerSet: illegal pointer type");
10384     }
10385 }
10386
10387 /*-----------------------------------------------------------------*/
10388 /* genIfx - generate code for Ifx statement                        */
10389 /*-----------------------------------------------------------------*/
10390 static void genIfx (iCode *ic, iCode *popIc)
10391 {
10392   operand *cond = IC_COND(ic);
10393   int isbit =0;
10394
10395   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10396
10397   pic16_aopOp(cond,ic,FALSE);
10398
10399   /* get the value into acc */
10400   if (AOP_TYPE(cond) != AOP_CRY)
10401     pic16_toBoolean(cond);
10402   else
10403     isbit = 1;
10404   /* the result is now in the accumulator */
10405   pic16_freeAsmop(cond,NULL,ic,TRUE);
10406
10407   /* if there was something to be popped then do it */
10408   if (popIc)
10409     genIpop(popIc);
10410
10411   /* if the condition is  a bit variable */
10412   if (isbit && IS_ITEMP(cond) && 
10413       SPIL_LOC(cond)) {
10414     genIfxJump(ic,SPIL_LOC(cond)->rname);
10415     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10416   }
10417   else {
10418     if (isbit && !IS_ITEMP(cond))
10419       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10420     else
10421       genIfxJump(ic,"a");
10422   }
10423   ic->generated = 1;
10424
10425 }
10426
10427 /*-----------------------------------------------------------------*/
10428 /* genAddrOf - generates code for address of                       */
10429 /*-----------------------------------------------------------------*/
10430 static void genAddrOf (iCode *ic)
10431 {
10432   operand *result, *left;
10433   int size;
10434   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10435   pCodeOp *pcop0, *pcop1, *pcop2;
10436
10437         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10438
10439         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10440         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10441
10442         sym = OP_SYMBOL( left );
10443
10444         size = AOP_SIZE(IC_RESULT(ic));
10445
10446 //      if(pic16_debug_verbose) {
10447 //              fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10448 //                      __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10449 //      }
10450         
10451         /* Assume that what we want the address of is in data space
10452          * since there is no stack on the PIC, yet! -- VR */
10453         /* low */
10454         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10455
10456         /* high */
10457         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10458         
10459         /* upper */
10460         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10461         
10462
10463         if (size == 3) {
10464                 pic16_emitpcode(POC_MOVLW, pcop0);
10465                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10466                 pic16_emitpcode(POC_MOVLW, pcop1);
10467                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10468                 pic16_emitpcode(POC_MOVLW, pcop2);
10469                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10470         } else
10471         if (size == 2) {
10472                 pic16_emitpcode(POC_MOVLW, pcop0);
10473                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10474                 pic16_emitpcode(POC_MOVLW, pcop1);
10475                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10476         } else {
10477                 pic16_emitpcode(POC_MOVLW, pcop0);
10478                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10479         }
10480
10481         pic16_freeAsmop(result,NULL,ic,TRUE);
10482         pic16_freeAsmop(left, NULL, ic, FALSE);
10483 }
10484
10485
10486 #if 0
10487 /*-----------------------------------------------------------------*/
10488 /* genFarFarAssign - assignment when both are in far space         */
10489 /*-----------------------------------------------------------------*/
10490 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10491 {
10492     int size = AOP_SIZE(right);
10493     int offset = 0;
10494     char *l ;
10495     /* first push the right side on to the stack */
10496     while (size--) {
10497         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10498         MOVA(l);
10499         pic16_emitcode ("push","acc");
10500     }
10501     
10502     pic16_freeAsmop(right,NULL,ic,FALSE);
10503     /* now assign DPTR to result */
10504     pic16_aopOp(result,ic,FALSE);
10505     size = AOP_SIZE(result);
10506     while (size--) {
10507         pic16_emitcode ("pop","acc");
10508         pic16_aopPut(AOP(result),"a",--offset);
10509     }
10510     pic16_freeAsmop(result,NULL,ic,FALSE);
10511         
10512 }
10513 #endif
10514
10515 /*-----------------------------------------------------------------*/
10516 /* genAssign - generate code for assignment                        */
10517 /*-----------------------------------------------------------------*/
10518 static void genAssign (iCode *ic)
10519 {
10520   operand *result, *right;
10521   int size, offset,know_W;
10522   unsigned long lit = 0L;
10523
10524   result = IC_RESULT(ic);
10525   right  = IC_RIGHT(ic) ;
10526
10527   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10528   
10529   /* if they are the same */
10530   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10531     return ;
10532
10533   pic16_aopOp(right,ic,FALSE);
10534   pic16_aopOp(result,ic,TRUE);
10535
10536   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10537
10538   /* if they are the same registers */
10539   if (pic16_sameRegs(AOP(right),AOP(result)))
10540     goto release;
10541
10542   /* if the result is a bit */
10543   if (AOP_TYPE(result) == AOP_CRY) {
10544     /* if the right size is a literal then
10545        we know what the value is */
10546     if (AOP_TYPE(right) == AOP_LIT) {
10547           
10548       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10549                   pic16_popGet(AOP(result),0));
10550
10551       if (((int) operandLitValue(right))) 
10552         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10553                        AOP(result)->aopu.aop_dir,
10554                        AOP(result)->aopu.aop_dir);
10555       else
10556         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10557                        AOP(result)->aopu.aop_dir,
10558                        AOP(result)->aopu.aop_dir);
10559       goto release;
10560     }
10561
10562     /* the right is also a bit variable */
10563     if (AOP_TYPE(right) == AOP_CRY) {
10564       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10565       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10566       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10567
10568       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10569                      AOP(result)->aopu.aop_dir,
10570                      AOP(result)->aopu.aop_dir);
10571       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10572                      AOP(right)->aopu.aop_dir,
10573                      AOP(right)->aopu.aop_dir);
10574       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10575                      AOP(result)->aopu.aop_dir,
10576                      AOP(result)->aopu.aop_dir);
10577       goto release ;
10578     }
10579
10580     /* we need to or */
10581     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10582     pic16_toBoolean(right);
10583     emitSKPZ;
10584     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10585     //pic16_aopPut(AOP(result),"a",0);
10586     goto release ;
10587   }
10588
10589   /* bit variables done */
10590   /* general case */
10591   size = AOP_SIZE(result);
10592   offset = 0 ;
10593
10594   if(AOP_TYPE(right) == AOP_LIT) {
10595         if(!IS_FLOAT(operandType( right )))
10596                 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10597         else {
10598            union {
10599               unsigned long lit_int;
10600               float lit_float;
10601             } info;
10602         
10603                 /* take care if literal is a float */
10604                 info.lit_float = floatFromVal(AOP(right)->aopu.aop_lit);
10605                 lit = info.lit_int;
10606         }
10607   }
10608
10609 //  fprintf(stderr, "%s:%d: assigning value 0x%04lx (%d:%d)\n", __FUNCTION__, __LINE__, lit,
10610 //                      sizeof(unsigned long int), sizeof(float));
10611
10612 /* VR - What is this?! */
10613   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10614   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10615     if(aopIdx(AOP(result),0) == 4) {
10616   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10617       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10618       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10619       goto release;
10620     } else
10621       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10622   }
10623
10624   know_W=-1;
10625   while (size--) {
10626   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10627     if(AOP_TYPE(right) == AOP_LIT) {
10628       if(lit&0xff) {
10629         if(know_W != (lit&0xff))
10630           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10631         know_W = lit&0xff;
10632         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10633       } else
10634         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10635
10636       lit >>= 8;
10637
10638     } else if (AOP_TYPE(right) == AOP_CRY) {
10639       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10640       if(offset == 0) {
10641         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10642         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10643       }
10644     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10645         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10646         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10647     } else {
10648   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10649
10650 #if 1
10651         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10652            normally should work, but mind that the W register live range
10653            is not checked, so if the code generator assumes that the W
10654            is already loaded after such a pair, wrong code will be generated.
10655            
10656            Checking the live range is the next step.
10657            This is experimental code yet and has not been fully tested yet.
10658            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10659            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10660            
10661         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10662 #else   
10663         /* This is the old code, which is assumed(?!) that works fine(!?) */
10664
10665         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10666         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10667 #endif
10668     }
10669             
10670     offset++;
10671   }
10672
10673     
10674  release:
10675   pic16_freeAsmop (right,NULL,ic,FALSE);
10676   pic16_freeAsmop (result,NULL,ic,TRUE);
10677 }   
10678
10679 /*-----------------------------------------------------------------*/
10680 /* genJumpTab - generates code for jump table                       */
10681 /*-----------------------------------------------------------------*/
10682 static void genJumpTab (iCode *ic)
10683 {
10684     symbol *jtab;
10685     char *l;
10686
10687     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10688
10689     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10690     /* get the condition into accumulator */
10691     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10692     MOVA(l);
10693     /* multiply by three */
10694     pic16_emitcode("add","a,acc");
10695     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10696
10697     jtab = newiTempLabel(NULL);
10698     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10699     pic16_emitcode("jmp","@a+dptr");
10700     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10701
10702     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10703     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10704     emitSKPNC;
10705     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10706     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10707     pic16_emitpLabel(jtab->key);
10708
10709     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10710
10711     /* now generate the jump labels */
10712     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10713          jtab = setNextItem(IC_JTLABELS(ic))) {
10714         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10715         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10716         
10717     }
10718
10719 }
10720
10721 /*-----------------------------------------------------------------*/
10722 /* genMixedOperation - gen code for operators between mixed types  */
10723 /*-----------------------------------------------------------------*/
10724 /*
10725   TSD - Written for the PIC port - but this unfortunately is buggy.
10726   This routine is good in that it is able to efficiently promote 
10727   types to different (larger) sizes. Unfortunately, the temporary
10728   variables that are optimized out by this routine are sometimes
10729   used in other places. So until I know how to really parse the 
10730   iCode tree, I'm going to not be using this routine :(.
10731 */
10732 static int genMixedOperation (iCode *ic)
10733 {
10734 #if 0
10735   operand *result = IC_RESULT(ic);
10736   sym_link *ctype = operandType(IC_LEFT(ic));
10737   operand *right = IC_RIGHT(ic);
10738   int ret = 0;
10739   int big,small;
10740   int offset;
10741
10742   iCode *nextic;
10743   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10744
10745   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10746
10747   nextic = ic->next;
10748   if(!nextic)
10749     return 0;
10750
10751   nextright = IC_RIGHT(nextic);
10752   nextleft  = IC_LEFT(nextic);
10753   nextresult = IC_RESULT(nextic);
10754
10755   pic16_aopOp(right,ic,FALSE);
10756   pic16_aopOp(result,ic,FALSE);
10757   pic16_aopOp(nextright,  nextic, FALSE);
10758   pic16_aopOp(nextleft,   nextic, FALSE);
10759   pic16_aopOp(nextresult, nextic, FALSE);
10760
10761   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10762
10763     operand *t = right;
10764     right = nextright;
10765     nextright = t; 
10766
10767     pic16_emitcode(";remove right +","");
10768
10769   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10770 /*
10771     operand *t = right;
10772     right = nextleft;
10773     nextleft = t; 
10774 */
10775     pic16_emitcode(";remove left +","");
10776   } else
10777     return 0;
10778
10779   big = AOP_SIZE(nextleft);
10780   small = AOP_SIZE(nextright);
10781
10782   switch(nextic->op) {
10783
10784   case '+':
10785     pic16_emitcode(";optimize a +","");
10786     /* if unsigned or not an integral type */
10787     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10788       pic16_emitcode(";add a bit to something","");
10789     } else {
10790
10791       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10792
10793       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10794         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10795         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10796       } else
10797         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10798
10799       offset = 0;
10800       while(--big) {
10801
10802         offset++;
10803
10804         if(--small) {
10805           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10806             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10807             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10808           }
10809
10810           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10811           emitSKPNC;
10812           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10813                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10814                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10815           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10816           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10817
10818         } else {
10819           pic16_emitcode("rlf","known_zero,w");
10820
10821           /*
10822             if right is signed
10823               btfsc  right,7
10824                addlw ff
10825           */
10826           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10827             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10828             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10829           } else {
10830             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10831           }
10832         }
10833       }
10834       ret = 1;
10835     }
10836   }
10837   ret = 1;
10838
10839 release:
10840   pic16_freeAsmop(right,NULL,ic,TRUE);
10841   pic16_freeAsmop(result,NULL,ic,TRUE);
10842   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10843   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10844   if(ret)
10845     nextic->generated = 1;
10846
10847   return ret;
10848 #else
10849   return 0;
10850 #endif
10851 }
10852 /*-----------------------------------------------------------------*/
10853 /* genCast - gen code for casting                                  */
10854 /*-----------------------------------------------------------------*/
10855 static void genCast (iCode *ic)
10856 {
10857   operand *result = IC_RESULT(ic);
10858   sym_link *ctype = operandType(IC_LEFT(ic));
10859   sym_link *rtype = operandType(IC_RIGHT(ic));
10860   operand *right = IC_RIGHT(ic);
10861   int size, offset ;
10862
10863         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10864         /* if they are equivalent then do nothing */
10865         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10866                 return ;
10867
10868         pic16_aopOp(right,ic,FALSE) ;
10869         pic16_aopOp(result,ic,FALSE);
10870
10871         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10872
10873         /* if the result is a bit */
10874         if (AOP_TYPE(result) == AOP_CRY) {
10875         
10876                 /* if the right size is a literal then
10877                  * we know what the value is */
10878                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10879
10880                 if (AOP_TYPE(right) == AOP_LIT) {
10881                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10882                                 pic16_popGet(AOP(result),0));
10883
10884                         if (((int) operandLitValue(right))) 
10885                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10886                                         AOP(result)->aopu.aop_dir,
10887                                         AOP(result)->aopu.aop_dir);
10888                         else
10889                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10890                                         AOP(result)->aopu.aop_dir,
10891                                         AOP(result)->aopu.aop_dir);
10892                         goto release;
10893                 }
10894
10895                 /* the right is also a bit variable */
10896                 if (AOP_TYPE(right) == AOP_CRY) {
10897                         emitCLRC;
10898                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10899
10900                         pic16_emitcode("clrc","");
10901                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10902                                 AOP(right)->aopu.aop_dir,
10903                                 AOP(right)->aopu.aop_dir);
10904                         pic16_aopPut(AOP(result),"c",0);
10905                         goto release ;
10906                 }
10907
10908                 /* we need to or */
10909                 if (AOP_TYPE(right) == AOP_REG) {
10910                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10911                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10912                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10913                 }
10914                 pic16_toBoolean(right);
10915                 pic16_aopPut(AOP(result),"a",0);
10916                 goto release ;
10917         }
10918
10919         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10920           int offset = 1;
10921
10922                 size = AOP_SIZE(result);
10923
10924                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10925
10926                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10927                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10928                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10929
10930                 while (size--)
10931                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10932
10933                 goto release;
10934         }
10935
10936         /* if they are the same size : or less */
10937         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10938
10939                 /* if they are in the same place */
10940                 if (pic16_sameRegs(AOP(right),AOP(result)))
10941                         goto release;
10942
10943                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10944 #if 0
10945                 if (IS_PTR_CONST(rtype))
10946 #else
10947                 if (IS_CODEPTR(rtype))
10948 #endif
10949                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10950
10951 #if 0
10952                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10953 #else
10954                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10955 #endif
10956                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10957
10958 #if 0
10959                 if(AOP_TYPE(right) == AOP_IMMD) {
10960                   pCodeOp *pcop0, *pcop1, *pcop2;
10961                   symbol *sym = OP_SYMBOL( right );
10962
10963                         size = AOP_SIZE(result);
10964                         /* low */
10965                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10966                         /* high */
10967                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10968                         /* upper */
10969                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10970         
10971                         if (size == 3) {
10972                                 pic16_emitpcode(POC_MOVLW, pcop0);
10973                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10974                                 pic16_emitpcode(POC_MOVLW, pcop1);
10975                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10976                                 pic16_emitpcode(POC_MOVLW, pcop2);
10977                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10978                         } else
10979                         if (size == 2) {
10980                                 pic16_emitpcode(POC_MOVLW, pcop0);
10981                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10982                                 pic16_emitpcode(POC_MOVLW, pcop1);
10983                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10984                         } else {
10985                                 pic16_emitpcode(POC_MOVLW, pcop0);
10986                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10987                         }
10988                 } else
10989 #endif
10990                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10991                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10992                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10993                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10994                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10995                         if(AOP_SIZE(result) <2)
10996                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10997                 } else {
10998                         /* if they in different places then copy */
10999                         size = AOP_SIZE(result);
11000                         offset = 0 ;
11001                         while (size--) {
11002                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
11003                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11004                                 offset++;
11005                         }
11006                 }
11007                 goto release;
11008         }
11009
11010         /* if the result is of type pointer */
11011         if (IS_PTR(ctype)) {
11012           int p_type;
11013           sym_link *type = operandType(right);
11014           sym_link *etype = getSpec(type);
11015
11016                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
11017
11018                 /* pointer to generic pointer */
11019                 if (IS_GENPTR(ctype)) {
11020                   char *l = zero;
11021             
11022                         if (IS_PTR(type)) 
11023                                 p_type = DCL_TYPE(type);
11024                         else {
11025                 /* we have to go by the storage class */
11026                 p_type = PTR_TYPE(SPEC_OCLS(etype));
11027
11028 /*              if (SPEC_OCLS(etype)->codesp )  */
11029 /*                  p_type = CPOINTER ;  */
11030 /*              else */
11031 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
11032 /*                      p_type = FPOINTER ; */
11033 /*                  else */
11034 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
11035 /*                          p_type = PPOINTER; */
11036 /*                      else */
11037 /*                          if (SPEC_OCLS(etype) == idata ) */
11038 /*                              p_type = IPOINTER ; */
11039 /*                          else */
11040 /*                              p_type = POINTER ; */
11041             }
11042                 
11043             /* the first two bytes are known */
11044       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
11045             size = GPTRSIZE - 1; 
11046             offset = 0 ;
11047             while (size--) {
11048               if(offset < AOP_SIZE(right)) {
11049       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
11050                 if ((AOP_TYPE(right) == AOP_PCODE) && 
11051                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
11052                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
11053                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
11054                 } else { 
11055                   pic16_aopPut(AOP(result),
11056                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11057                          offset);
11058                 }
11059               } else 
11060                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
11061               offset++;
11062             }
11063             /* the last byte depending on type */
11064             switch (p_type) {
11065             case IPOINTER:
11066             case POINTER:
11067                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11068                 break;
11069             case FPOINTER:
11070               pic16_emitcode(";BUG!? ","%d",__LINE__);
11071                 l = one;
11072                 break;
11073             case CPOINTER:
11074               pic16_emitcode(";BUG!? ","%d",__LINE__);
11075                 l = "#0x02";
11076                 break;                          
11077             case PPOINTER:
11078               pic16_emitcode(";BUG!? ","%d",__LINE__);
11079                 l = "#0x03";
11080                 break;
11081                 
11082             default:
11083                 /* this should never happen */
11084                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11085                        "got unknown pointer type");
11086                 exit(1);
11087             }
11088             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11089             goto release ;
11090         }
11091         
11092         /* just copy the pointers */
11093         size = AOP_SIZE(result);
11094         offset = 0 ;
11095         while (size--) {
11096             pic16_aopPut(AOP(result),
11097                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11098                    offset);
11099             offset++;
11100         }
11101         goto release ;
11102     }
11103     
11104
11105
11106     /* so we now know that the size of destination is greater
11107     than the size of the source.
11108     Now, if the next iCode is an operator then we might be
11109     able to optimize the operation without performing a cast.
11110     */
11111     if(genMixedOperation(ic))
11112       goto release;
11113
11114     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11115     
11116     /* we move to result for the size of source */
11117     size = AOP_SIZE(right);
11118     offset = 0 ;
11119     while (size--) {
11120       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11121       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11122       offset++;
11123     }
11124
11125     /* now depending on the sign of the destination */
11126     size = AOP_SIZE(result) - AOP_SIZE(right);
11127     /* if unsigned or not an integral type */
11128     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11129       while (size--)
11130         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11131     } else {
11132       /* we need to extend the sign :( */
11133
11134       if(size == 1) {
11135         /* Save one instruction of casting char to int */
11136         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11137         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11138         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11139       } else {
11140         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11141
11142         if(offset)
11143           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11144         else
11145           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
11146         
11147         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11148
11149         while (size--)
11150           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11151       }
11152     }
11153
11154 release:
11155     pic16_freeAsmop(right,NULL,ic,TRUE);
11156     pic16_freeAsmop(result,NULL,ic,TRUE);
11157
11158 }
11159
11160 /*-----------------------------------------------------------------*/
11161 /* genDjnz - generate decrement & jump if not zero instrucion      */
11162 /*-----------------------------------------------------------------*/
11163 static int genDjnz (iCode *ic, iCode *ifx)
11164 {
11165     symbol *lbl, *lbl1;
11166     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11167
11168     if (!ifx)
11169         return 0;
11170     
11171     /* if the if condition has a false label
11172        then we cannot save */
11173     if (IC_FALSE(ifx))
11174         return 0;
11175
11176     /* if the minus is not of the form 
11177        a = a - 1 */
11178     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11179         !IS_OP_LITERAL(IC_RIGHT(ic)))
11180         return 0;
11181
11182     if (operandLitValue(IC_RIGHT(ic)) != 1)
11183         return 0;
11184
11185     /* if the size of this greater than one then no
11186        saving */
11187     if (getSize(operandType(IC_RESULT(ic))) > 1)
11188         return 0;
11189
11190     /* otherwise we can save BIG */
11191     lbl = newiTempLabel(NULL);
11192     lbl1= newiTempLabel(NULL);
11193
11194     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11195     
11196     if (IS_AOP_PREG(IC_RESULT(ic))) {
11197         pic16_emitcode("dec","%s",
11198                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11199         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11200         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11201     } else {    
11202
11203
11204       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11205       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11206
11207       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11208       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
11209
11210     }
11211 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11212 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11213 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11214 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11215
11216     
11217     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11218     ifx->generated = 1;
11219     return 1;
11220 }
11221
11222 /*-----------------------------------------------------------------*/
11223 /* genReceive - generate code for a receive iCode                  */
11224 /*-----------------------------------------------------------------*/
11225 static void genReceive (iCode *ic)
11226 {    
11227         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11228
11229         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11230                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11231                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11232
11233           int size = getSize(operandType(IC_RESULT(ic)));
11234           int offset =  pic16_fReturnSizePic - size;
11235
11236                 while (size--) {
11237                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11238                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11239                         offset++;
11240                 }
11241
11242                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11243
11244                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11245                 size = AOP_SIZE(IC_RESULT(ic));
11246                 offset = 0;
11247                 while (size--) {
11248                         pic16_emitcode ("pop","acc");
11249                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11250                 }
11251         } else {
11252                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11253
11254                 _G.accInUse++;
11255                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11256                 _G.accInUse--;
11257                 assignResultValue(IC_RESULT(ic), 0);
11258         }
11259
11260         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11261 }
11262
11263 /*-----------------------------------------------------------------*/
11264 /* genDummyRead - generate code for dummy read of volatiles        */
11265 /*-----------------------------------------------------------------*/
11266 static void
11267 genDummyRead (iCode * ic)
11268 {
11269   pic16_emitcode ("; genDummyRead","");
11270   pic16_emitcode ("; not implemented","");
11271
11272   ic = ic;
11273 }
11274
11275 /*-----------------------------------------------------------------*/
11276 /* genpic16Code - generate code for pic16 based controllers        */
11277 /*-----------------------------------------------------------------*/
11278 /*
11279  * At this point, ralloc.c has gone through the iCode and attempted
11280  * to optimize in a way suitable for a PIC. Now we've got to generate
11281  * PIC instructions that correspond to the iCode.
11282  *
11283  * Once the instructions are generated, we'll pass through both the
11284  * peep hole optimizer and the pCode optimizer.
11285  *-----------------------------------------------------------------*/
11286
11287 void genpic16Code (iCode *lic)
11288 {
11289     iCode *ic;
11290     int cln = 0;
11291
11292     lineHead = lineCurr = NULL;
11293
11294     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11295     pic16_addpBlock(pb);
11296
11297 #if 0
11298     /* if debug information required */
11299     if (options.debug && currFunc) {
11300       if (currFunc) {
11301         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11302       }
11303     }
11304 #endif
11305
11306     for (ic = lic ; ic ; ic = ic->next ) {
11307
11308       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11309         if ( cln != ic->lineno ) {
11310             if ( options.debug ) {
11311               debugFile->writeCLine (ic);
11312             }
11313             
11314             if(!options.noCcodeInAsm) {
11315                 pic16_addpCode2pBlock(pb,
11316                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11317                                 printCLine(ic->filename, ic->lineno)));
11318             }
11319
11320             cln = ic->lineno ;
11321         }
11322         
11323         if(options.iCodeInAsm) {
11324                 char *l;
11325                 /* insert here code to print iCode as comment */
11326                 l = Safe_strdup(printILine(ic));
11327                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11328         }
11329         
11330         /* if the result is marked as
11331            spilt and rematerializable or code for
11332            this has already been generated then
11333            do nothing */
11334         if (resultRemat(ic) || ic->generated ) 
11335             continue ;
11336         
11337         /* depending on the operation */
11338         switch (ic->op) {
11339         case '!' :
11340             pic16_genNot(ic);
11341             break;
11342             
11343         case '~' :
11344             pic16_genCpl(ic);
11345             break;
11346             
11347         case UNARYMINUS:
11348             genUminus (ic);
11349             break;
11350             
11351         case IPUSH:
11352             genIpush (ic);
11353             break;
11354             
11355         case IPOP:
11356             /* IPOP happens only when trying to restore a 
11357                spilt live range, if there is an ifx statement
11358                following this pop then the if statement might
11359                be using some of the registers being popped which
11360                would destroy the contents of the register so
11361                we need to check for this condition and handle it */
11362             if (ic->next            && 
11363                 ic->next->op == IFX &&
11364                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11365                 genIfx (ic->next,ic);
11366             else
11367                 genIpop (ic);
11368             break; 
11369             
11370         case CALL:
11371             genCall (ic);
11372             break;
11373             
11374         case PCALL:
11375             genPcall (ic);
11376             break;
11377             
11378         case FUNCTION:
11379             genFunction (ic);
11380             break;
11381             
11382         case ENDFUNCTION:
11383             genEndFunction (ic);
11384             break;
11385             
11386         case RETURN:
11387             genRet (ic);
11388             break;
11389             
11390         case LABEL:
11391             genLabel (ic);
11392             break;
11393             
11394         case GOTO:
11395             genGoto (ic);
11396             break;
11397             
11398         case '+' :
11399             pic16_genPlus (ic) ;
11400             break;
11401             
11402         case '-' :
11403             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11404                 pic16_genMinus (ic);
11405             break;
11406             
11407         case '*' :
11408             genMult (ic);
11409             break;
11410             
11411         case '/' :
11412             genDiv (ic) ;
11413             break;
11414             
11415         case '%' :
11416             genMod (ic);
11417             break;
11418             
11419         case '>' :
11420             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11421             break;
11422             
11423         case '<' :
11424             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11425             break;
11426             
11427         case LE_OP:
11428         case GE_OP:
11429         case NE_OP:
11430             
11431             /* note these two are xlated by algebraic equivalence
11432                during parsing SDCC.y */
11433             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11434                    "got '>=' or '<=' shouldn't have come here");
11435             break;      
11436             
11437         case EQ_OP:
11438             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11439             break;          
11440             
11441         case AND_OP:
11442             genAndOp (ic);
11443             break;
11444             
11445         case OR_OP:
11446             genOrOp (ic);
11447             break;
11448             
11449         case '^' :
11450             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11451             break;
11452             
11453         case '|' :
11454                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11455             break;
11456             
11457         case BITWISEAND:
11458             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11459             break;
11460             
11461         case INLINEASM:
11462             genInline (ic);
11463             break;
11464             
11465         case RRC:
11466             genRRC (ic);
11467             break;
11468             
11469         case RLC:
11470             genRLC (ic);
11471             break;
11472             
11473         case GETHBIT:
11474             genGetHbit (ic);
11475             break;
11476             
11477         case LEFT_OP:
11478             genLeftShift (ic);
11479             break;
11480             
11481         case RIGHT_OP:
11482             genRightShift (ic);
11483             break;
11484             
11485         case GET_VALUE_AT_ADDRESS:
11486             genPointerGet(ic);
11487             break;
11488             
11489         case '=' :
11490             if (POINTER_SET(ic))
11491                 genPointerSet(ic);
11492             else
11493                 genAssign(ic);
11494             break;
11495             
11496         case IFX:
11497             genIfx (ic,NULL);
11498             break;
11499             
11500         case ADDRESS_OF:
11501             genAddrOf (ic);
11502             break;
11503             
11504         case JUMPTABLE:
11505             genJumpTab (ic);
11506             break;
11507             
11508         case CAST:
11509             genCast (ic);
11510             break;
11511             
11512         case RECEIVE:
11513             genReceive(ic);
11514             break;
11515             
11516         case SEND:
11517             addSet(&_G.sendSet,ic);
11518             break;
11519
11520         case DUMMY_READ_VOLATILE:
11521           genDummyRead (ic);
11522           break;
11523
11524         default :
11525             ic = ic;
11526         }
11527     }
11528
11529
11530     /* now we are ready to call the
11531        peep hole optimizer */
11532     if (!options.nopeep) {
11533       peepHole (&lineHead);
11534     }
11535     /* now do the actual printing */
11536     printLine (lineHead,codeOutFile);
11537
11538 #ifdef PCODE_DEBUG
11539     DFPRINTF((stderr,"printing pBlock\n\n"));
11540     pic16_printpBlock(stdout,pb);
11541 #endif
11542
11543     return;
11544 }
11545