* src/hc08/gen.c (hc08_emitDebuggerSymbol),
[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
86
87 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
88
89 /* this is the down and dirty file with all kinds of 
90    kludgy & hacky stuff. This is what it is all about
91    CODE GENERATION for a specific MCU . some of the
92    routines may be reusable, will have to see */
93
94 static char *zero = "#0x00";
95 static char *one  = "#0x01";
96 static char *spname = "sp";
97
98
99 /*
100  * Function return value policy (MSB-->LSB):
101  *  8 bits      -> WREG
102  * 16 bits      -> PRODL:WREG
103  * 24 bits      -> PRODH:PRODL:WREG
104  * 32 bits      -> FSR0L:PRODH:PRODL:WREG
105  * >32 bits     -> on stack, and FSR0 points to the beginning
106  *
107  */
108  
109
110 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
111 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
112 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
113 static char **fReturn = fReturnpic16;
114
115 static char *accUse[] = {"WREG"};
116
117 //static short rbank = -1;
118
119 static struct {
120     short r0Pushed;
121     short r1Pushed;
122     short accInUse;
123     short inLine;
124     short debugLine;
125     short nRegsSaved;
126     set *sendSet;
127     int interruptvector;
128 } _G;
129
130 /* Resolved ifx structure. This structure stores information
131    about an iCode ifx that makes it easier to generate code.
132 */
133 typedef struct resolvedIfx {
134   symbol *lbl;     /* pointer to a label */
135   int condition;   /* true or false ifx */
136   int generated;   /* set true when the code associated with the ifx
137                     * is generated */
138 } resolvedIfx;
139
140 extern int pic16_ptrRegReq ;
141 extern int pic16_nRegs;
142 extern FILE *codeOutFile;
143 static void saverbank (int, iCode *,bool);
144
145 static lineNode *lineHead = NULL;
146 static lineNode *lineCurr = NULL;
147
148 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
149 0xE0, 0xC0, 0x80, 0x00};
150 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
151 0x07, 0x03, 0x01, 0x00};
152
153 static  pBlock *pb;
154
155 /*-----------------------------------------------------------------*/
156 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
157 /*                 exponent of 2 is returned, otherwise -1 is      */
158 /*                 returned.                                       */
159 /* note that this is similar to the function `powof2' in SDCCsymt  */
160 /* if(n == 2^y)                                                    */
161 /*   return y;                                                     */
162 /* return -1;                                                      */
163 /*-----------------------------------------------------------------*/
164 static int my_powof2 (unsigned long num)
165 {
166   if(num) {
167     if( (num & (num-1)) == 0) {
168       int nshifts = -1;
169       while(num) {
170         num>>=1;
171         nshifts++;
172       }
173       return nshifts;
174     }
175   }
176
177   return -1;
178 }
179
180 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
181 {
182   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
183                        line_no,
184                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
185                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
186                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
187                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
188                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
189                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
190                        ((result) ? AOP_SIZE(result) : 0));
191 }
192
193 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
194 {
195
196   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
197                        line_no,
198                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
199                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
200                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
201                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
202                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
203                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
204
205 }
206
207 void pic16_emitpcomment (char *fmt, ...)
208 {
209     va_list ap;
210     char lb[INITIAL_INLINEASM];  
211     char *lbp = lb;
212
213     va_start(ap,fmt);   
214
215     lb[0] = ';';
216     vsprintf(lb+1,fmt,ap);
217
218     while (isspace(*lbp)) lbp++;
219
220     if (lbp && *lbp) 
221         lineCurr = (lineCurr ?
222                     connectLine(lineCurr,newLineNode(lb)) :
223                     (lineHead = newLineNode(lb)));
224     lineCurr->isInline = _G.inLine;
225     lineCurr->isDebug  = _G.debugLine;
226
227     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
228     va_end(ap);
229
230 //      fprintf(stderr, "%s\n", lb);
231 }
232
233 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
234 {
235     va_list ap;
236     char lb[INITIAL_INLINEASM];  
237     char *lbp = lb;
238
239     if(!pic16_debug_verbose)
240       return;
241
242     va_start(ap,fmt);   
243
244     if (inst && *inst) {
245         if (fmt && *fmt)
246             sprintf(lb,"%s\t",inst);
247         else
248             sprintf(lb,"%s",inst);
249         vsprintf(lb+(strlen(lb)),fmt,ap);
250     }  else
251         vsprintf(lb,fmt,ap);
252
253     while (isspace(*lbp)) lbp++;
254
255     if (lbp && *lbp) 
256         lineCurr = (lineCurr ?
257                     connectLine(lineCurr,newLineNode(lb)) :
258                     (lineHead = newLineNode(lb)));
259     lineCurr->isInline = _G.inLine;
260     lineCurr->isDebug  = _G.debugLine;
261
262     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
263     va_end(ap);
264
265 //      fprintf(stderr, "%s\n", lb);
266 }
267
268 void pic16_emitpLabel(int key)
269 {
270   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
271 }
272
273 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
274 {
275
276   if(pcop)
277     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
278   else
279     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
280     
281 //    fprintf(stderr, "%s\n", pcop->name);
282 }
283
284 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
285 {
286
287   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
288
289 }
290
291
292 #if 1
293 #define pic16_emitcode  DEBUGpic16_emitcode
294 #else
295 /*-----------------------------------------------------------------*/
296 /* pic16_emitcode - writes the code into a file : for now it is simple    */
297 /*-----------------------------------------------------------------*/
298 void pic16_emitcode (char *inst,char *fmt, ...)
299 {
300     va_list ap;
301     char lb[INITIAL_INLINEASM];  
302     char *lbp = lb;
303
304     va_start(ap,fmt);   
305
306     if (inst && *inst) {
307         if (fmt && *fmt)
308             sprintf(lb,"%s\t",inst);
309         else
310             sprintf(lb,"%s",inst);
311         vsprintf(lb+(strlen(lb)),fmt,ap);
312     }  else
313         vsprintf(lb,fmt,ap);
314
315     while (isspace(*lbp)) lbp++;
316
317     if (lbp && *lbp) 
318         lineCurr = (lineCurr ?
319                     connectLine(lineCurr,newLineNode(lb)) :
320                     (lineHead = newLineNode(lb)));
321     lineCurr->isInline = _G.inLine;
322     lineCurr->isDebug  = _G.debugLine;
323
324 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
325
326 //    if(pic16_debug_verbose)
327 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
328
329     va_end(ap);
330 }
331 #endif
332
333 /*-----------------------------------------------------------------*/
334 /* pic16_emitDebuggerSymbol - associate the current code location  */
335 /*   with a debugger symbol                                        */
336 /*-----------------------------------------------------------------*/
337 void
338 pic16_emitDebuggerSymbol (char * debugSym)
339 {
340   _G.debugLine = 1;
341   pic16_emitcode (";", "%s ==.", debugSym);
342   _G.debugLine = 0;
343 }
344
345 /*-----------------------------------------------------------------*/
346 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
347 /*-----------------------------------------------------------------*/
348 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
349 {
350     bool r0iu = FALSE , r1iu = FALSE;
351     bool r0ou = FALSE , r1ou = FALSE;
352
353         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
354
355     /* the logic: if r0 & r1 used in the instruction
356     then we are in trouble otherwise */
357
358     /* first check if r0 & r1 are used by this
359     instruction, in which case we are in trouble */
360     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
361         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
362     {
363         goto endOfWorld;      
364     }
365
366     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
367     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
368
369     /* if no usage of r0 then return it */
370     if (!r0iu && !r0ou) {
371         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
372         (*aopp)->type = AOP_R0;
373         
374         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
375     }
376
377     /* if no usage of r1 then return it */
378     if (!r1iu && !r1ou) {
379         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
380         (*aopp)->type = AOP_R1;
381
382         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
383     }    
384
385     /* now we know they both have usage */
386     /* if r0 not used in this instruction */
387     if (!r0iu) {
388         /* push it if not already pushed */
389         if (!_G.r0Pushed) {
390           //pic16_emitcode ("push","%s",
391           //          pic16_regWithIdx(R0_IDX)->dname);
392             _G.r0Pushed++ ;
393         }
394         
395         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
396         (*aopp)->type = AOP_R0;
397
398         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
399     }
400
401     /* if r1 not used then */
402
403     if (!r1iu) {
404         /* push it if not already pushed */
405         if (!_G.r1Pushed) {
406           //pic16_emitcode ("push","%s",
407           //          pic16_regWithIdx(R1_IDX)->dname);
408             _G.r1Pushed++ ;
409         }
410         
411         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
412         (*aopp)->type = AOP_R1;
413         return pic16_regWithIdx(R1_IDX);
414     }
415
416 endOfWorld :
417     /* I said end of world but not quite end of world yet */
418     /* if this is a result then we can push it on the stack*/
419     if (result) {
420         (*aopp)->type = AOP_STK;    
421         return NULL;
422     }
423
424     /* other wise this is true end of the world */
425     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
426            "getFreePtr should never reach here");
427     exit(0);
428 }
429
430 /*-----------------------------------------------------------------*/
431 /* newAsmop - creates a new asmOp                                  */
432 /*-----------------------------------------------------------------*/
433 static asmop *newAsmop (short type)
434 {
435     asmop *aop;
436
437     aop = Safe_calloc(1,sizeof(asmop));
438     aop->type = type;
439     return aop;
440 }
441
442 static void genSetDPTR(int n)
443 {
444     if (!n)
445     {
446         pic16_emitcode(";", "Select standard DPTR");
447         pic16_emitcode("mov", "dps, #0x00");
448     }
449     else
450     {
451         pic16_emitcode(";", "Select alternate DPTR");
452         pic16_emitcode("mov", "dps, #0x01");
453     }
454 }
455
456 /*-----------------------------------------------------------------*/
457 /* resolveIfx - converts an iCode ifx into a form more useful for  */
458 /*              generating code                                    */
459 /*-----------------------------------------------------------------*/
460 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
461 {
462
463   DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
464
465   if(!resIfx) 
466     return;
467
468
469   resIfx->condition = 1;    /* assume that the ifx is true */
470   resIfx->generated = 0;    /* indicate that the ifx has not been used */
471
472   if(!ifx) {
473     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
474
475 #if 1
476     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
477                         __FUNCTION__,__LINE__,resIfx->lbl->key);
478 #endif
479
480   } else {
481     if(IC_TRUE(ifx)) {
482       resIfx->lbl = IC_TRUE(ifx);
483     } else {
484       resIfx->lbl = IC_FALSE(ifx);
485       resIfx->condition = 0;
486     }
487 /*
488     if(IC_TRUE(ifx)) 
489       DEBUGpic16_emitcode("; ***","ifx true is non-null");
490     if(IC_FALSE(ifx)) 
491       DEBUGpic16_emitcode("; ***","ifx false is non-null");
492 */
493   }
494
495   DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
496
497 }
498 #if 0
499 /*-----------------------------------------------------------------*/
500 /* pointerCode - returns the code for a pointer type               */
501 /*-----------------------------------------------------------------*/
502 static int pointerCode (sym_link *etype)
503 {
504
505     return PTR_TYPE(SPEC_OCLS(etype));
506
507 }
508 #endif
509 /*-----------------------------------------------------------------*/
510 /* aopForSym - for a true symbol                                   */
511 /*-----------------------------------------------------------------*/
512 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
513 {
514     asmop *aop;
515     memmap *space= SPEC_OCLS(sym->etype);
516
517     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
518     /* if already has one */
519     if (sym->aop) {
520             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
521         return sym->aop;
522     }
523
524     /* if symbol was initially placed onStack then we must re-place it
525      * to direct memory, since pic16 does not have a specific stack */
526     if(sym->onStack) {
527         sym->onStack = 0;
528         SPEC_OCLS( sym->etype ) = data;
529         space = data;
530     }
531     
532
533 #if 1
534     /* assign depending on the storage class */
535     /* if it is on the stack or indirectly addressable */
536     /* space we need to assign either r0 or r1 to it   */    
537     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
538
539         DEBUGpic16_emitcode("; ***", "%s:%d sym->onStack:%d || sym->iaccess:%d",
540                 __FUNCTION__, __LINE__, sym->onStack, sym->iaccess);
541         
542         sym->aop = aop = newAsmop(0);
543         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
544         aop->size = getSize(sym->type);
545
546         /* now assign the address of the variable to 
547         the pointer register */
548         if (aop->type != AOP_STK) {
549
550             if (sym->onStack) {
551                     if ( _G.accInUse )
552                         pic16_emitcode("push","acc");
553
554                     pic16_emitcode("mov","a,_bp");
555                     pic16_emitcode("add","a,#0x%02x",
556                              ((sym->stack < 0) ?
557                               ((char)(sym->stack - _G.nRegsSaved )) :
558                               ((char)sym->stack)) & 0xff);
559                     pic16_emitcode("mov","%s,a",
560                              aop->aopu.aop_ptr->name);
561
562                     if ( _G.accInUse )
563                         pic16_emitcode("pop","acc");
564             } else
565                 pic16_emitcode("mov","%s,#%s",
566                          aop->aopu.aop_ptr->name,
567                          sym->rname);
568             aop->paged = space->paged;
569         } else
570             aop->aopu.aop_stk = sym->stack;
571         return aop;
572     }
573 #endif
574
575     if (sym->onStack && options.stack10bit)
576     {
577         /* It's on the 10 bit stack, which is located in
578          * far data space.
579          */
580          
581       //DEBUGpic16_emitcode(";","%d",__LINE__);
582
583         if ( _G.accInUse )
584                 pic16_emitcode("push","acc");
585
586         pic16_emitcode("mov","a,_bp");
587         pic16_emitcode("add","a,#0x%02x",
588                  ((sym->stack < 0) ?
589                    ((char)(sym->stack - _G.nRegsSaved )) :
590                    ((char)sym->stack)) & 0xff);
591         
592         genSetDPTR(1);
593         pic16_emitcode ("mov","dpx1,#0x40");
594         pic16_emitcode ("mov","dph1,#0x00");
595         pic16_emitcode ("mov","dpl1, a");
596         genSetDPTR(0);
597         
598         if ( _G.accInUse )
599             pic16_emitcode("pop","acc");
600             
601         sym->aop = aop = newAsmop(AOP_DPTR2);
602         aop->size = getSize(sym->type); 
603         return aop;
604     }
605
606     //DEBUGpic16_emitcode(";","%d",__LINE__);
607     /* if in bit space */
608     if (IN_BITSPACE(space)) {
609         sym->aop = aop = newAsmop (AOP_CRY);
610         aop->aopu.aop_dir = sym->rname ;
611         aop->size = getSize(sym->type);
612         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
613         return aop;
614     }
615     /* if it is in direct space */
616     if (IN_DIRSPACE(space)) {
617         sym->aop = aop = newAsmop (AOP_DIR);
618         aop->aopu.aop_dir = sym->rname ;
619         aop->size = getSize(sym->type);
620         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
621         pic16_allocDirReg( IC_LEFT(ic) );
622         return aop;
623     }
624
625 #if 0                                                                                           // patch 14
626     /* special case for a function */
627     if (IS_FUNC(sym->type)) {   
628         sym->aop = aop = newAsmop(AOP_IMMD);    
629         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
630         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
631         strcpy(aop->aopu.aop_immd,sym->rname);
632         aop->size = FPTRSIZE; 
633         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
634         return aop;
635     }
636 #endif                                                                                          // patch 14
637
638
639     /* only remaining is far space */
640     /* in which case DPTR gets the address */
641     sym->aop = aop = newAsmop(AOP_PCODE);
642
643 /* change the next if to 1 to revert to good old immediate code */
644         if(IN_CODESPACE(space)) {
645                 aop->aopu.pcop = pic16_popGetImmd(sym->rname, 0, 0);
646                 PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
647                 PCOI(aop->aopu.pcop)->index = 0;
648         } else {
649                 /* try to allocate via direct register */
650                 aop->aopu.pcop = pic16_popRegFromString(sym->rname, getSize(sym->type), sym->offset); // Patch 8
651 //              aop->size = getSize( sym->type );
652         }
653
654         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
655                 __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
656
657 #if 0
658         if(!pic16_allocDirReg (IC_LEFT(ic)))
659                 return NULL;
660 #endif
661
662         if(IN_DIRSPACE( space ))
663                 aop->size = PTRSIZE;
664         else if(IN_CODESPACE( space ))
665                 aop->size = FPTRSIZE;
666         else if(IC_LEFT(ic)) aop->size = AOP_SIZE( IC_LEFT(ic) );
667         else if(IC_RIGHT(ic)) aop->size = AOP_SIZE( IC_RIGHT(ic) );
668         else {
669                 assert( 0 );
670         }
671
672     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
673
674     /* if it is in code space */
675     if (IN_CODESPACE(space))
676         aop->code = 1;
677
678     return aop;     
679 }
680
681 /*-----------------------------------------------------------------*/
682 /* aopForRemat - rematerialzes an object                           */
683 /*-----------------------------------------------------------------*/
684 static asmop *aopForRemat (operand *op) // x symbol *sym)
685 {
686   symbol *sym = OP_SYMBOL(op);
687   iCode *ic = NULL, *oldic;
688   asmop *aop = newAsmop(AOP_PCODE);
689   int val = 0;
690   int offset = 0;
691   int viaimmd=0;
692
693
694         ic = sym->rematiCode;
695
696         DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
697         
698         if(IS_OP_POINTER(op)) {
699                 DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
700         }
701
702         for (;;) {
703                 oldic = ic;
704
705 //              pic16_emitpcomment("ic: %s\n", printILine(ic));
706         
707                 if (ic->op == '+') {
708                         val += (int) operandLitValue(IC_RIGHT(ic));
709                 } else if (ic->op == '-') {
710                         val -= (int) operandLitValue(IC_RIGHT(ic));
711                 } else
712                         break;
713                 
714                 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
715         }
716
717         offset = OP_SYMBOL(IC_LEFT(ic))->offset;
718
719         if(!op->isaddr)viaimmd++; else viaimmd=0;
720                 
721 /* set the following if to 1 to revert to good old immediate code */
722         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)))
723                 || viaimmd) {
724
725                 pic16_emitpcomment("%s:%d immediate", __FILE__, __LINE__);
726
727                 aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname, 0, val);
728
729 #if 0
730                 PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
731 #else
732                 PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
733 #endif
734
735                 PCOI(aop->aopu.pcop)->index = val;
736         } else {
737                 pic16_emitpcomment("%s:%d dir", __FILE__, __LINE__);
738
739                 aop->aopu.pcop = pic16_popRegFromString(OP_SYMBOL(IC_LEFT(ic))->rname, getSize( OP_SYMBOL( IC_LEFT(ic))->type), val);
740 //              aop->size = AOP_SIZE( IC_LEFT(ic) );
741         }
742
743
744         DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
745                 __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
746 #if 0
747                 val, IS_PTR_CONST(operandType(op)));
748 #else
749                 val, IS_CODEPTR(operandType(op)));
750 #endif
751
752 //      DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
753
754         pic16_allocDirReg (IC_LEFT(ic));
755
756         if(IN_CODESPACE( SPEC_OCLS( OP_SYM_ETYPE(op)) ))
757                 aop->code = 1;
758
759   return aop;        
760 }
761
762 static int aopIdx (asmop *aop, int offset)
763 {
764   if(!aop)
765     return -1;
766
767   if(aop->type !=  AOP_REG)
768     return -2;
769         
770   return aop->aopu.aop_reg[offset]->rIdx;
771
772 }
773 /*-----------------------------------------------------------------*/
774 /* regsInCommon - two operands have some registers in common       */
775 /*-----------------------------------------------------------------*/
776 static bool regsInCommon (operand *op1, operand *op2)
777 {
778     symbol *sym1, *sym2;
779     int i;
780
781     /* if they have registers in common */
782     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
783         return FALSE ;
784
785     sym1 = OP_SYMBOL(op1);
786     sym2 = OP_SYMBOL(op2);
787
788     if (sym1->nRegs == 0 || sym2->nRegs == 0)
789         return FALSE ;
790
791     for (i = 0 ; i < sym1->nRegs ; i++) {
792         int j;
793         if (!sym1->regs[i])
794             continue ;
795
796         for (j = 0 ; j < sym2->nRegs ;j++ ) {
797             if (!sym2->regs[j])
798                 continue ;
799
800             if (sym2->regs[j] == sym1->regs[i])
801                 return TRUE ;
802         }
803     }
804
805     return FALSE ;
806 }
807
808 /*-----------------------------------------------------------------*/
809 /* operandsEqu - equivalent                                        */
810 /*-----------------------------------------------------------------*/
811 static bool operandsEqu ( operand *op1, operand *op2)
812 {
813     symbol *sym1, *sym2;
814
815     /* if they not symbols */
816     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
817         return FALSE;
818
819     sym1 = OP_SYMBOL(op1);
820     sym2 = OP_SYMBOL(op2);
821
822     /* if both are itemps & one is spilt
823        and the other is not then false */
824     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
825         sym1->isspilt != sym2->isspilt )
826         return FALSE ;
827
828     /* if they are the same */
829     if (sym1 == sym2)
830         return TRUE ;
831
832     if (strcmp(sym1->rname,sym2->rname) == 0)
833         return TRUE;
834
835
836     /* if left is a tmp & right is not */
837     if (IS_ITEMP(op1)  && 
838         !IS_ITEMP(op2) &&
839         sym1->isspilt  &&
840         (sym1->usl.spillLoc == sym2))
841         return TRUE;
842
843     if (IS_ITEMP(op2)  && 
844         !IS_ITEMP(op1) &&
845         sym2->isspilt  &&
846         sym1->level > 0 &&
847         (sym2->usl.spillLoc == sym1))
848         return TRUE ;
849
850     return FALSE ;
851 }
852
853 /*-----------------------------------------------------------------*/
854 /* pic16_sameRegs - two asmops have the same registers                   */
855 /*-----------------------------------------------------------------*/
856 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
857 {
858     int i;
859
860     if (aop1 == aop2)
861         return TRUE ;
862
863     if (aop1->type != AOP_REG ||
864         aop2->type != AOP_REG )
865         return FALSE ;
866
867     if (aop1->size != aop2->size )
868         return FALSE ;
869
870     for (i = 0 ; i < aop1->size ; i++ )
871         if (aop1->aopu.aop_reg[i] !=
872             aop2->aopu.aop_reg[i] )
873             return FALSE ;
874
875     return TRUE ;
876 }
877
878 /*-----------------------------------------------------------------*/
879 /* pic16_aopOp - allocates an asmop for an operand  :                    */
880 /*-----------------------------------------------------------------*/
881 void pic16_aopOp (operand *op, iCode *ic, bool result)
882 {
883     asmop *aop;
884     symbol *sym;
885     int i;
886
887     if (!op)
888         return ;
889
890 //      DEBUGpic16_emitcode(";","%s %d",__FUNCTION__, __LINE__);
891
892     /* if this a literal */
893     if (IS_OP_LITERAL(op)) {
894         op->aop = aop = newAsmop(AOP_LIT);
895         aop->aopu.aop_lit = op->operand.valOperand;
896         aop->size = getSize(operandType(op));
897         return;
898     }
899
900     {
901       sym_link *type = operandType(op);
902 #if 0
903       if(IS_PTR_CONST(type))
904 #else
905       if(IS_CODEPTR(type))
906 #endif
907         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
908     }
909
910     /* if already has a asmop then continue */
911     if (op->aop)
912         return ;
913
914     /* if the underlying symbol has a aop */
915     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
916       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
917         op->aop = OP_SYMBOL(op)->aop;
918         return;
919     }
920
921     /* if this is a true symbol */
922     if (IS_TRUE_SYMOP(op)) {    
923         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
924       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
925       return ;
926     }
927
928     /* this is a temporary : this has
929     only four choices :
930     a) register
931     b) spillocation
932     c) rematerialize 
933     d) conditional   
934     e) can be a return use only */
935
936     sym = OP_SYMBOL(op);
937
938         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
939     /* if the type is a conditional */
940     if (sym->regType == REG_CND) {
941         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
942         aop->size = 0;
943         return;
944     }
945
946     /* if it is spilt then two situations
947     a) is rematerialize 
948     b) has a spill location */
949     if (sym->isspilt || sym->nRegs == 0) {
950
951       DEBUGpic16_emitcode(";","%d",__LINE__);
952         /* rematerialize it NOW */
953         if (sym->remat) {
954
955             sym->aop = op->aop = aop =
956                                       aopForRemat (op);
957             aop->size = getSize(sym->type);
958             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
959             return;
960         }
961
962 #if 1
963         if (sym->accuse) {
964             int i;
965             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
966             aop->size = getSize(sym->type);
967             for ( i = 0 ; i < 1 ; i++ ) {
968                 aop->aopu.aop_str[i] = accUse[i];
969 //                aop->aopu.pcop = pic16_popRegFromString("WREG", aop->size, sym->usl.spillLoc->offset);
970             }
971             fprintf(stderr, "%s:%d allocating AOP_ACC for sym= %s\n", __FILE__, __LINE__, sym->name);
972             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
973             return;  
974         }
975 #endif
976
977 #if 1
978         if (sym->ruonly ) {
979           /*
980           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
981           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
982           //pic16_allocDirReg (IC_LEFT(ic));
983           aop->size = getSize(sym->type);
984           */
985
986           unsigned i;
987
988           aop = op->aop = sym->aop = newAsmop(AOP_STR);
989           aop->size = getSize(sym->type);
990           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
991             aop->aopu.aop_str[i] = fReturn[i];
992
993           DEBUGpic16_emitcode(";","%d",__LINE__);
994           return;
995         }
996 #endif
997         /* else spill location  */
998         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
999             /* force a new aop if sizes differ */
1000             sym->usl.spillLoc->aop = NULL;
1001         }
1002         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
1003                             __FUNCTION__,__LINE__,
1004                             sym->usl.spillLoc->rname,
1005                             sym->rname, sym->usl.spillLoc->offset);
1006
1007         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
1008         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
1009         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
1010                                           getSize(sym->type), 
1011                                           sym->usl.spillLoc->offset);
1012         aop->size = getSize(sym->type);
1013
1014         return;
1015     }
1016
1017     {
1018       sym_link *type = operandType(op);
1019 #if 0
1020       if(IS_PTR_CONST(type)) 
1021 #else
1022       if(IS_CODEPTR(type)) 
1023 #endif
1024         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
1025     }
1026
1027     /* must be in a register */
1028     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
1029     sym->aop = op->aop = aop = newAsmop(AOP_REG);
1030     aop->size = sym->nRegs;
1031     for ( i = 0 ; i < sym->nRegs ;i++)
1032         aop->aopu.aop_reg[i] = sym->regs[i];
1033 }
1034
1035 /*-----------------------------------------------------------------*/
1036 /* pic16_freeAsmop - free up the asmop given to an operand               */
1037 /*----------------------------------------------------------------*/
1038 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
1039 {   
1040     asmop *aop ;
1041
1042     if (!op)
1043         aop = aaop;
1044     else 
1045         aop = op->aop;
1046
1047     if (!aop)
1048         return ;
1049
1050     if (aop->freed)
1051         goto dealloc; 
1052
1053     aop->freed = 1;
1054
1055     /* depending on the asmop type only three cases need work AOP_RO
1056        , AOP_R1 && AOP_STK */
1057 #if 0
1058     switch (aop->type) {
1059         case AOP_R0 :
1060             if (_G.r0Pushed ) {
1061                 if (pop) {
1062                     pic16_emitcode ("pop","ar0");     
1063                     _G.r0Pushed--;
1064                 }
1065             }
1066             bitVectUnSetBit(ic->rUsed,R0_IDX);
1067             break;
1068
1069         case AOP_R1 :
1070             if (_G.r1Pushed ) {
1071                 if (pop) {
1072                     pic16_emitcode ("pop","ar1");
1073                     _G.r1Pushed--;
1074                 }
1075             }
1076             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1077             break;
1078
1079         case AOP_STK :
1080         {
1081             int sz = aop->size;    
1082             int stk = aop->aopu.aop_stk + aop->size;
1083             bitVectUnSetBit(ic->rUsed,R0_IDX);
1084             bitVectUnSetBit(ic->rUsed,R1_IDX);          
1085
1086             getFreePtr(ic,&aop,FALSE);
1087             
1088             if (options.stack10bit)
1089             {
1090                 /* I'm not sure what to do here yet... */
1091                 /* #STUB */
1092                 fprintf(stderr, 
1093                         "*** Warning: probably generating bad code for "
1094                         "10 bit stack mode.\n");
1095             }
1096             
1097             if (stk) {
1098                 pic16_emitcode ("mov","a,_bp");
1099                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1100                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1101             } else {
1102                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1103             }
1104
1105             while (sz--) {
1106                 pic16_emitcode("pop","acc");
1107                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1108                 if (!sz) break;
1109                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1110             }
1111             op->aop = aop;
1112             pic16_freeAsmop(op,NULL,ic,TRUE);
1113             if (_G.r0Pushed) {
1114                 pic16_emitcode("pop","ar0");
1115                 _G.r0Pushed--;
1116             }
1117
1118             if (_G.r1Pushed) {
1119                 pic16_emitcode("pop","ar1");
1120                 _G.r1Pushed--;
1121             }       
1122         }
1123     }
1124 #endif
1125
1126 dealloc:
1127     /* all other cases just dealloc */
1128     if (op ) {
1129         op->aop = NULL;
1130         if (IS_SYMOP(op)) {
1131             OP_SYMBOL(op)->aop = NULL;    
1132             /* if the symbol has a spill */
1133             if (SPIL_LOC(op))
1134                 SPIL_LOC(op)->aop = NULL;
1135         }
1136     }
1137 }
1138
1139 /*-----------------------------------------------------------------*/
1140 /* pic16_aopGet - for fetching value of the aop                          */
1141 /*-----------------------------------------------------------------*/
1142 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1143 {
1144     char *s = buffer ;
1145     char *rs;
1146
1147     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1148
1149     /* offset is greater than size then zero */
1150     if (offset > (aop->size - 1) &&
1151         aop->type != AOP_LIT)
1152         return zero;
1153
1154     /* depending on type */
1155     switch (aop->type) {
1156         
1157     case AOP_R0:
1158     case AOP_R1:
1159         DEBUGpic16_emitcode(";","%d",__LINE__);
1160         /* if we need to increment it */       
1161         while (offset > aop->coff) {        
1162             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1163             aop->coff++;
1164         }
1165         
1166         while (offset < aop->coff) {
1167             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1168             aop->coff--;
1169         }
1170         
1171         aop->coff = offset ;
1172         if (aop->paged) {
1173             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1174             return (dname ? "acc" : "a");
1175         }       
1176         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1177         rs = Safe_calloc(1,strlen(s)+1);
1178         strcpy(rs,s);   
1179         return rs;
1180         
1181     case AOP_DPTR:
1182     case AOP_DPTR2:
1183         DEBUGpic16_emitcode(";","%d",__LINE__);
1184     if (aop->type == AOP_DPTR2)
1185     {
1186         genSetDPTR(1);
1187     }
1188     
1189         while (offset > aop->coff) {
1190             pic16_emitcode ("inc","dptr");
1191             aop->coff++;
1192         }
1193         
1194         while (offset < aop->coff) {        
1195             pic16_emitcode("lcall","__decdptr");
1196             aop->coff--;
1197         }
1198         
1199         aop->coff = offset;
1200         if (aop->code) {
1201             pic16_emitcode("clr","a");
1202             pic16_emitcode("movc","a,@a+dptr");
1203         }
1204     else {
1205             pic16_emitcode("movx","a,@dptr");
1206     }
1207             
1208     if (aop->type == AOP_DPTR2)
1209     {
1210         genSetDPTR(0);
1211     }
1212             
1213     return (dname ? "acc" : "a");
1214         
1215         
1216     case AOP_IMMD:
1217         if (bit16) 
1218             sprintf (s,"%s",aop->aopu.aop_immd);
1219         else
1220             if (offset) 
1221                 sprintf(s,"(%s >> %d)",
1222                         aop->aopu.aop_immd,
1223                         offset*8);
1224             else
1225                 sprintf(s,"%s",
1226                         aop->aopu.aop_immd);
1227         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1228         rs = Safe_calloc(1,strlen(s)+1);
1229         strcpy(rs,s);   
1230         return rs;
1231         
1232     case AOP_DIR:
1233       if (offset) {
1234         sprintf(s,"(%s + %d)",
1235                 aop->aopu.aop_dir,
1236                 offset);
1237         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1238       } else
1239             sprintf(s,"%s",aop->aopu.aop_dir);
1240         rs = Safe_calloc(1,strlen(s)+1);
1241         strcpy(rs,s);   
1242         return rs;
1243         
1244     case AOP_REG:
1245       //if (dname) 
1246       //    return aop->aopu.aop_reg[offset]->dname;
1247       //else
1248             return aop->aopu.aop_reg[offset]->name;
1249         
1250     case AOP_CRY:
1251       //pic16_emitcode(";","%d",__LINE__);
1252       return aop->aopu.aop_dir;
1253         
1254     case AOP_ACC:
1255         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1256 //        fprintf(stderr, "%s:%d Warning -pic port ignoring get(AOP_ACC)\n",__FILE__, __LINE__);
1257 //        assert( 0 );
1258         return aop->aopu.aop_str[offset];       //->"AOP_accumulator_bug";
1259
1260     case AOP_LIT:
1261         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1262         rs = Safe_calloc(1,strlen(s)+1);
1263         strcpy(rs,s);   
1264         return rs;
1265         
1266     case AOP_STR:
1267         aop->coff = offset ;
1268         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1269             dname)
1270             return "acc";
1271         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1272         
1273         return aop->aopu.aop_str[offset];
1274         
1275     case AOP_PCODE:
1276       {
1277         pCodeOp *pcop = aop->aopu.pcop;
1278         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1279         if(pcop->name) {
1280           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1281           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1282           sprintf(s,"%s", pcop->name);
1283         } else
1284           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1285
1286       }
1287       rs = Safe_calloc(1,strlen(s)+1);
1288       strcpy(rs,s);   
1289       return rs;
1290
1291     }
1292
1293     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1294            "aopget got unsupported aop->type");
1295     exit(0);
1296 }
1297
1298
1299 /*-----------------------------------------------------------------*/
1300 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1301 /*-----------------------------------------------------------------*/
1302 pCodeOp *pic16_popGetTempReg(void)
1303 {
1304   pCodeOp *pcop;
1305   symbol *cfunc;
1306
1307 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1308
1309         cfunc = currFunc;
1310         currFunc = NULL;
1311
1312         pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1313         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1314                 PCOR(pcop)->r->wasUsed=1;
1315                 PCOR(pcop)->r->isFree=0;
1316
1317                 /* push value on stack */
1318                 pic16_pushpCodeOp( pic16_pCodeOpCopy(pcop) );
1319         }
1320
1321         currFunc = cfunc;
1322
1323   return pcop;
1324 }
1325
1326 /*-----------------------------------------------------------------*/
1327 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1328 /*-----------------------------------------------------------------*/
1329 void pic16_popReleaseTempReg(pCodeOp *pcop)
1330 {
1331         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1332
1333         if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1334                 PCOR(pcop)->r->isFree = 1;
1335                 
1336                 pic16_poppCodeOp( pic16_pCodeOpCopy(pcop) );
1337         }
1338 }
1339 /*-----------------------------------------------------------------*/
1340 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1341 /*-----------------------------------------------------------------*/
1342 pCodeOp *pic16_popGetLabel(unsigned int key)
1343 {
1344
1345   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1346
1347   if(key>max_key)
1348     max_key = key;
1349
1350   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1351 }
1352
1353 /*-----------------------------------------------------------------*/
1354 /* pic16_popCopyReg - copy a pcode operator                              */
1355 /*-----------------------------------------------------------------*/
1356 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1357 {
1358   pCodeOpReg *pcor;
1359
1360   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1361   pcor->pcop.type = pc->pcop.type;
1362   if(pc->pcop.name) {
1363     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1364       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1365   } else
1366     pcor->pcop.name = NULL;
1367
1368   pcor->r = pc->r;
1369   pcor->rIdx = pc->rIdx;
1370   pcor->r->wasUsed=1;
1371
1372 //  DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1373
1374   return PCOP(pcor);
1375 }
1376
1377 /*-----------------------------------------------------------------*/
1378 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1379 /*-----------------------------------------------------------------*/
1380 pCodeOp *pic16_popGetLit(unsigned int lit)
1381 {
1382   return pic16_newpCodeOpLit(lit);
1383 }
1384
1385 /*-----------------------------------------------------------------*/
1386 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1387 /*-----------------------------------------------------------------*/
1388 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1389 {
1390   return pic16_newpCodeOpLit2(lit, arg2);
1391 }
1392
1393
1394 /*-----------------------------------------------------------------*/
1395 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1396 /*-----------------------------------------------------------------*/
1397 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1398 {
1399   return pic16_newpCodeOpImmd(name, offset,index, 0);
1400 }
1401
1402
1403 /*-----------------------------------------------------------------*/
1404 /* pic16_popGet - asm operator to pcode operator conversion              */
1405 /*-----------------------------------------------------------------*/
1406 pCodeOp *pic16_popGetWithString(char *str)
1407 {
1408   pCodeOp *pcop;
1409
1410
1411   if(!str) {
1412     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1413     exit (1);
1414   }
1415
1416   pcop = pic16_newpCodeOp(str,PO_STR);
1417
1418   return pcop;
1419 }
1420
1421 /*-----------------------------------------------------------------*/
1422 /* pic16_popRegFromString -                                        */
1423 /*-----------------------------------------------------------------*/
1424 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1425 {
1426
1427   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1428   pcop->type = PO_DIR;
1429
1430   DEBUGpic16_emitcode(";","%d %s %s %d/%d",__LINE__, __FUNCTION__, str, size, offset); // patch 14
1431   // fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1432
1433   if(!str)
1434     str = "BAD_STRING";
1435
1436   pcop->name = Safe_calloc(1,strlen(str)+1);
1437   strcpy(pcop->name,str);
1438
1439   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1440
1441   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1442   if(PCOR(pcop)->r == NULL) {
1443 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1444 //              __FUNCTION__, __LINE__, str, size, offset);
1445     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1446
1447         //fprintf(stderr, "allocating new register -> %s\n", str);
1448
1449 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d - had to alloc by reg name",__LINE__,pcop->name,size,offset);
1450   } else {
1451 //    DEBUGpic16_emitcode(";","%d  %s   size= %d offset=%d",__LINE__,pcop->name,size,offset);
1452   }
1453   PCOR(pcop)->instance = offset;
1454
1455   return pcop;
1456 }
1457
1458 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1459 {
1460   pCodeOp *pcop;
1461
1462 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1463
1464         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1465         PCOR(pcop)->rIdx = rIdx;
1466         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1467         PCOR(pcop)->r->isFree = 0;
1468         PCOR(pcop)->r->wasUsed = 1;
1469
1470         pcop->type = PCOR(pcop)->r->pc_type;
1471
1472   return pcop;
1473 }
1474
1475 /*---------------------------------------------------------------------------------*/
1476 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1477 /*                 VR 030601                                                       */
1478 /*---------------------------------------------------------------------------------*/
1479 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1480 {
1481   pCodeOpReg2 *pcop2;
1482   pCodeOp *temp;
1483   
1484         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1485
1486         /* comment the following check, so errors to throw up */
1487 //      if(!pcop2)return NULL;
1488
1489         temp = pic16_popGet(aop_dst, offset);
1490         pcop2->pcop2 = temp;
1491         
1492   return PCOP(pcop2);
1493 }
1494
1495
1496
1497 /*--------------------------------------------------------------------------------.-*/
1498 /* pic16_popGet2p - a variant of pic16_popGet to handle two memory operand commands */
1499 /*                  VR 030601 , adapted by Hans Dorn                                */
1500 /*--------------------------------------------------------------------------------.-*/
1501 pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst)
1502 {
1503   pCodeOpReg2 *pcop2;
1504  
1505         pcop2 = (pCodeOpReg2 *)src;
1506         pcop2->pcop2 = dst;
1507         
1508         return PCOP(pcop2);
1509 }
1510
1511
1512
1513 /*---------------------------------------------------------------------------------*/
1514 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1515 /*                     movff instruction                                           */
1516 /*---------------------------------------------------------------------------------*/
1517 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1518 {
1519   pCodeOpReg2 *pcop2;
1520
1521         if(!noalloc) {
1522                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1523                 pcop2->pcop2 = pic16_popCopyReg(dst);
1524         } else {
1525                 /* the pCodeOp may be already allocated */
1526                 pcop2 = (pCodeOpReg2 *)(src);
1527                 pcop2->pcop2 = (pCodeOp *)(dst);
1528         }
1529
1530   return PCOP(pcop2);
1531 }
1532
1533
1534 /*-----------------------------------------------------------------*/
1535 /* pic16_popGet - asm operator to pcode operator conversion              */
1536 /*-----------------------------------------------------------------*/
1537 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1538 {
1539   //char *s = buffer ;
1540   char *rs;
1541   pCodeOp *pcop;
1542
1543     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1544     /* offset is greater than
1545     size then zero */
1546
1547 //    if (offset > (aop->size - 1) &&
1548 //        aop->type != AOP_LIT)
1549 //      return NULL;  //zero;
1550
1551     /* depending on type */
1552     switch (aop->type) {
1553         
1554     case AOP_R0:
1555     case AOP_R1:
1556     case AOP_DPTR:
1557     case AOP_DPTR2:
1558         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1559         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1560         assert( 0 );
1561         return NULL;
1562
1563
1564
1565     case AOP_IMMD:
1566       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1567       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1568
1569     case AOP_ACC:
1570       {
1571         int rIdx = IDX_WREG;            //aop->aopu.aop_reg[offset]->rIdx;
1572
1573         fprintf(stderr, "%s:%d returning register AOP_ACC %s\n", __FILE__, __LINE__, aop->aopu.aop_str[offset]);
1574
1575         DEBUGpic16_emitcode(";","%d\tAOP_ACC", __LINE__);
1576         
1577         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1578         PCOR(pcop)->rIdx = rIdx;
1579         PCOR(pcop)->r = pic16_typeRegWithIdx(rIdx, REG_SFR, 1); // pic16_regWithIdx(rIdx);
1580         PCOR(pcop)->r->wasUsed=1;
1581         PCOR(pcop)->r->isFree=0;
1582
1583         PCOR(pcop)->instance = offset;
1584         pcop->type = PCOR(pcop)->r->pc_type;
1585 //      rs = aop->aopu.aop_reg[offset]->name;
1586 //      DEBUGpic16_emitcode(";","%d register idx = %d name =%s",__LINE__,rIdx,rs);
1587         return pcop;
1588
1589
1590 //      return pic16_popRegFromString(aop->aopu.aop_str[offset], aop->size, offset);
1591 //      return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1592
1593 //      assert( 0 );
1594       }
1595         
1596     case AOP_DIR:
1597       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1598       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1599         
1600     case AOP_REG:
1601       {
1602         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1603
1604         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1605         
1606         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1607         PCOR(pcop)->rIdx = rIdx;
1608         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1609         PCOR(pcop)->r->wasUsed=1;
1610         PCOR(pcop)->r->isFree=0;
1611
1612         PCOR(pcop)->instance = offset;
1613         pcop->type = PCOR(pcop)->r->pc_type;
1614         rs = aop->aopu.aop_reg[offset]->name;
1615         DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1616         return pcop;
1617       }
1618
1619     case AOP_CRY:
1620         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1621
1622       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1623       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1624       //if(PCOR(pcop)->r == NULL)
1625       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1626       return pcop;
1627         
1628     case AOP_LIT:
1629         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1630       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1631
1632     case AOP_STR:
1633       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1634       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1635
1636       /*
1637       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1638       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1639       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1640       pcop->type = PCOR(pcop)->r->pc_type;
1641       pcop->name = PCOR(pcop)->r->name;
1642
1643       return pcop;
1644       */
1645
1646     case AOP_PCODE:
1647       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s offset %d",pic16_pCodeOpType(aop->aopu.pcop),
1648                           __LINE__, 
1649                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"), offset);
1650       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1651 #if 1
1652         switch( aop->aopu.pcop->type ) {
1653                 case PO_DIR: PCOR(pcop)->instance += offset; break; // patch 8
1654                 case PO_IMMEDIATE: PCOI(pcop)->offset = offset; break;
1655                 default:
1656                         assert( 0 );    /* should never reach here */;
1657         }
1658 #else
1659       PCOI(pcop)->offset = offset;
1660 #endif
1661       return pcop;
1662     }
1663
1664     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1665            "pic16_popGet got unsupported aop->type");
1666     exit(0);
1667 }
1668 /*-----------------------------------------------------------------*/
1669 /* pic16_aopPut - puts a string for a aop                                */
1670 /*-----------------------------------------------------------------*/
1671 void pic16_aopPut (asmop *aop, char *s, int offset)
1672 {
1673     char *d = buffer ;
1674     symbol *lbl ;
1675
1676     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1677
1678     if (aop->size && offset > ( aop->size - 1)) {
1679         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1680                "pic16_aopPut got offset > aop->size");
1681         exit(0);
1682     }
1683
1684     /* will assign value to value */
1685     /* depending on where it is ofcourse */
1686     switch (aop->type) {
1687     case AOP_DIR:
1688       if (offset) {
1689         sprintf(d,"(%s + %d)",
1690                 aop->aopu.aop_dir,offset);
1691         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1692
1693       } else
1694             sprintf(d,"%s",aop->aopu.aop_dir);
1695         
1696         if (strcmp(d,s)) {
1697           DEBUGpic16_emitcode(";","%d",__LINE__);
1698           if(strcmp(s,"W"))
1699             pic16_emitcode("movf","%s,w",s);
1700           pic16_emitcode("movwf","%s",d);
1701
1702           if(strcmp(s,"W")) {
1703             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1704             if(offset >= aop->size) {
1705               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1706               break;
1707             } else
1708               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1709           }
1710
1711           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1712
1713
1714         }
1715         break;
1716         
1717     case AOP_REG:
1718       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1719         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1720           /*
1721             if (*s == '@'           ||
1722                 strcmp(s,"r0") == 0 ||
1723                 strcmp(s,"r1") == 0 ||
1724                 strcmp(s,"r2") == 0 ||
1725                 strcmp(s,"r3") == 0 ||
1726                 strcmp(s,"r4") == 0 ||
1727                 strcmp(s,"r5") == 0 ||
1728                 strcmp(s,"r6") == 0 || 
1729                 strcmp(s,"r7") == 0 )
1730                 pic16_emitcode("mov","%s,%s  ; %d",
1731                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1732             else
1733           */
1734
1735           if(strcmp(s,"W")==0 )
1736             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1737
1738           pic16_emitcode("movwf","%s",
1739                    aop->aopu.aop_reg[offset]->name);
1740
1741           if(strcmp(s,zero)==0) {
1742             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1743
1744           } else if(strcmp(s,"W")==0) {
1745             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1746             pcop->type = PO_GPR_REGISTER;
1747
1748             PCOR(pcop)->rIdx = -1;
1749             PCOR(pcop)->r = NULL;
1750
1751             DEBUGpic16_emitcode(";","%d",__LINE__);
1752             pcop->name = Safe_strdup(s);
1753             pic16_emitpcode(POC_MOVFW,pcop);
1754             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1755           } else if(strcmp(s,one)==0) {
1756             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1757             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1758           } else {
1759             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1760           }
1761         }
1762         break;
1763         
1764     case AOP_DPTR:
1765     case AOP_DPTR2:
1766     
1767     if (aop->type == AOP_DPTR2)
1768     {
1769         genSetDPTR(1);
1770     }
1771     
1772         if (aop->code) {
1773             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1774                    "pic16_aopPut writting to code space");
1775             exit(0);
1776         }
1777         
1778         while (offset > aop->coff) {
1779             aop->coff++;
1780             pic16_emitcode ("inc","dptr");
1781         }
1782         
1783         while (offset < aop->coff) {
1784             aop->coff-- ;
1785             pic16_emitcode("lcall","__decdptr");
1786         }
1787         
1788         aop->coff = offset;
1789         
1790         /* if not in accumulater */
1791         MOVA(s);        
1792         
1793         pic16_emitcode ("movx","@dptr,a");
1794         
1795     if (aop->type == AOP_DPTR2)
1796     {
1797         genSetDPTR(0);
1798     }
1799         break;
1800         
1801     case AOP_R0:
1802     case AOP_R1:
1803         while (offset > aop->coff) {
1804             aop->coff++;
1805             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1806         }
1807         while (offset < aop->coff) {
1808             aop->coff-- ;
1809             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1810         }
1811         aop->coff = offset;
1812         
1813         if (aop->paged) {
1814             MOVA(s);           
1815             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1816             
1817         } else
1818             if (*s == '@') {
1819                 MOVA(s);
1820                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1821             } else
1822                 if (strcmp(s,"r0") == 0 ||
1823                     strcmp(s,"r1") == 0 ||
1824                     strcmp(s,"r2") == 0 ||
1825                     strcmp(s,"r3") == 0 ||
1826                     strcmp(s,"r4") == 0 ||
1827                     strcmp(s,"r5") == 0 ||
1828                     strcmp(s,"r6") == 0 || 
1829                     strcmp(s,"r7") == 0 ) {
1830                     char buffer[10];
1831                     sprintf(buffer,"a%s",s);
1832                     pic16_emitcode("mov","@%s,%s",
1833                              aop->aopu.aop_ptr->name,buffer);
1834                 } else
1835                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1836         
1837         break;
1838         
1839     case AOP_STK:
1840         if (strcmp(s,"a") == 0)
1841             pic16_emitcode("push","acc");
1842         else
1843             pic16_emitcode("push","%s",s);
1844         
1845         break;
1846         
1847     case AOP_CRY:
1848         /* if bit variable */
1849         if (!aop->aopu.aop_dir) {
1850             pic16_emitcode("clr","a");
1851             pic16_emitcode("rlc","a");
1852         } else {
1853             if (s == zero) 
1854                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1855             else
1856                 if (s == one)
1857                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1858                 else
1859                     if (!strcmp(s,"c"))
1860                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1861                     else {
1862                         lbl = newiTempLabel(NULL);
1863                         
1864                         if (strcmp(s,"a")) {
1865                             MOVA(s);
1866                         }
1867                         pic16_emitcode("clr","c");
1868                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1869                         pic16_emitcode("cpl","c");
1870                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1871                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1872                     }
1873         }
1874         break;
1875         
1876     case AOP_STR:
1877         aop->coff = offset;
1878         if (strcmp(aop->aopu.aop_str[offset],s))
1879             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1880         break;
1881         
1882     case AOP_ACC:
1883         aop->coff = offset;
1884         if (!offset && (strcmp(s,"acc") == 0))
1885             break;
1886         
1887         if (strcmp(aop->aopu.aop_str[offset],s))
1888             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1889         break;
1890
1891     default :
1892         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1893                "pic16_aopPut got unsupported aop->type");
1894         exit(0);    
1895     }    
1896
1897 }
1898
1899 /*-----------------------------------------------------------------*/
1900 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1901 /*-----------------------------------------------------------------*/
1902 static void mov2w (asmop *aop, int offset)
1903 {
1904
1905   if(!aop)
1906     return;
1907
1908   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1909
1910   if ( aop->type == AOP_PCODE ||
1911        aop->type == AOP_LIT )
1912     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1913   else
1914     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1915
1916 }
1917
1918
1919 /* push pcop into stack */
1920 void pic16_pushpCodeOp(pCodeOp *pcop)
1921 {
1922 //      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1923         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg(&pic16_pc_postdec1)));
1924 }
1925
1926 /* pop pcop from stack */
1927 void pic16_poppCodeOp(pCodeOp *pcop)
1928 {
1929         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_preinc1), pcop));
1930 }
1931
1932
1933 /*-----------------------------------------------------------------*/
1934 /* pushw - pushes wreg to stack                                    */
1935 /*-----------------------------------------------------------------*/
1936 void pushw(void)
1937 {
1938         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1939         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1940 }
1941
1942                 
1943 /*-----------------------------------------------------------------*/
1944 /* pushaop - pushes aop to stack                                   */
1945 /*-----------------------------------------------------------------*/
1946 void pushaop(asmop *aop, int offset)
1947 {
1948         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1949         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1950 }
1951
1952 /*-----------------------------------------------------------------*/
1953 /* popaop - pops aop from stack                                    */
1954 /*-----------------------------------------------------------------*/
1955 void popaop(asmop *aop, int offset)
1956 {
1957         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1958         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1959 }
1960
1961 void popaopidx(asmop *aop, int offset, int index)
1962 {
1963   int ofs=1;
1964
1965         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1966
1967         if(STACK_MODEL_LARGE)ofs++;
1968
1969         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1970         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1971 }
1972
1973 /*-----------------------------------------------------------------*/
1974 /* reAdjustPreg - points a register back to where it should        */
1975 /*-----------------------------------------------------------------*/
1976 static void reAdjustPreg (asmop *aop)
1977 {
1978     int size ;
1979
1980     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1981     aop->coff = 0;
1982     if ((size = aop->size) <= 1)
1983         return ;
1984     size-- ;
1985     switch (aop->type) {
1986         case AOP_R0 :
1987         case AOP_R1 :
1988             while (size--)
1989                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1990             break;          
1991         case AOP_DPTR :
1992         case AOP_DPTR2:
1993             if (aop->type == AOP_DPTR2)
1994             {
1995                 genSetDPTR(1);
1996             } 
1997             while (size--)
1998             {
1999                 pic16_emitcode("lcall","__decdptr");
2000             }
2001                 
2002             if (aop->type == AOP_DPTR2)
2003             {
2004                 genSetDPTR(0);
2005             }                
2006             break;  
2007
2008     }   
2009
2010 }
2011
2012
2013 #if 0
2014 /*-----------------------------------------------------------------*/
2015 /* opIsGptr: returns non-zero if the passed operand is             */   
2016 /* a generic pointer type.                                         */
2017 /*-----------------------------------------------------------------*/ 
2018 static int opIsGptr(operand *op)
2019 {
2020     sym_link *type = operandType(op);
2021     
2022     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2023     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
2024     {
2025         return 1;
2026     }
2027     return 0;        
2028 }
2029 #endif
2030
2031 /*-----------------------------------------------------------------*/
2032 /* pic16_getDataSize - get the operand data size                         */
2033 /*-----------------------------------------------------------------*/
2034 int pic16_getDataSize(operand *op)
2035 {
2036     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2037
2038
2039     return AOP_SIZE(op);
2040
2041     // tsd- in the pic port, the genptr size is 1, so this code here
2042     // fails. ( in the 8051 port, the size was 4).
2043 #if 0
2044     int size;
2045     size = AOP_SIZE(op);
2046     if (size == GPTRSIZE)
2047     {
2048         sym_link *type = operandType(op);
2049         if (IS_GENPTR(type))
2050         {
2051             /* generic pointer; arithmetic operations
2052              * should ignore the high byte (pointer type).
2053              */
2054             size--;
2055     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2056         }
2057     }
2058     return size;
2059 #endif
2060 }
2061
2062 /*-----------------------------------------------------------------*/
2063 /* pic16_outAcc - output Acc                                             */
2064 /*-----------------------------------------------------------------*/
2065 void pic16_outAcc(operand *result)
2066 {
2067   int size,offset;
2068   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
2069   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
2070
2071
2072   size = pic16_getDataSize(result);
2073   if(size){
2074     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
2075     size--;
2076     offset = 1;
2077     /* unsigned or positive */
2078     while(size--)
2079       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
2080   }
2081
2082 }
2083
2084 /*-----------------------------------------------------------------*/
2085 /* pic16_outBitC - output a bit C                                        */
2086 /*-----------------------------------------------------------------*/
2087 void pic16_outBitC(operand *result)
2088 {
2089
2090     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2091     /* if the result is bit */
2092     if (AOP_TYPE(result) == AOP_CRY) 
2093         pic16_aopPut(AOP(result),"c",0);
2094     else {
2095         pic16_emitcode("clr","a  ; %d", __LINE__);
2096         pic16_emitcode("rlc","a");
2097         pic16_outAcc(result);
2098     }
2099 }
2100
2101 /*-----------------------------------------------------------------*/
2102 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
2103 /*-----------------------------------------------------------------*/
2104 void pic16_toBoolean(operand *oper)
2105 {
2106     int size = AOP_SIZE(oper) - 1;
2107     int offset = 1;
2108
2109     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2110
2111     if ( AOP_TYPE(oper) != AOP_ACC) {
2112       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
2113     }
2114     while (size--) {
2115       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
2116     }
2117 }
2118
2119
2120 #if !defined(GEN_Not)
2121 /*-----------------------------------------------------------------*/
2122 /* genNot - generate code for ! operation                          */
2123 /*-----------------------------------------------------------------*/
2124 static void pic16_genNot (iCode *ic)
2125 {
2126   symbol *tlbl;
2127   int size;
2128
2129   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2130   /* assign asmOps to operand & result */
2131   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2132   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2133
2134   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
2135   /* if in bit space then a special case */
2136   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
2137     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
2138       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2139       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2140     } else {
2141       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2142       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
2143       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2144     }
2145     goto release;
2146   }
2147
2148   size = AOP_SIZE(IC_LEFT(ic));
2149   if(size == 1) {
2150     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
2151     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
2152     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
2153     goto release;
2154   }
2155   pic16_toBoolean(IC_LEFT(ic));
2156
2157   tlbl = newiTempLabel(NULL);
2158   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
2159   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
2160   pic16_outBitC(IC_RESULT(ic));
2161
2162  release:    
2163   /* release the aops */
2164   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2165   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2166 }
2167 #endif
2168
2169
2170 #if !defined(GEN_Cpl)
2171 /*-----------------------------------------------------------------*/
2172 /* genCpl - generate code for complement                           */
2173 /*-----------------------------------------------------------------*/
2174 static void pic16_genCpl (iCode *ic)
2175 {
2176     int offset = 0;
2177     int size ;
2178
2179
2180     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2181     /* assign asmOps to operand & result */
2182     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2183     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2184
2185     /* if both are in bit space then 
2186     a special case */
2187     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2188         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2189
2190         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2191         pic16_emitcode("cpl","c"); 
2192         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2193         goto release; 
2194     } 
2195
2196     size = AOP_SIZE(IC_RESULT(ic));
2197     while (size--) {
2198 /*
2199         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2200         MOVA(l);       
2201         pic16_emitcode("cpl","a");
2202         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2203 */
2204         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2205               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2206         } else {
2207                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2208                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2209         }
2210         offset++;
2211
2212     }
2213
2214
2215 release:
2216     /* release the aops */
2217     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2218     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2219 }
2220 #endif
2221
2222 /*-----------------------------------------------------------------*/
2223 /* genUminusFloat - unary minus for floating points                */
2224 /*-----------------------------------------------------------------*/
2225 static void genUminusFloat(operand *op,operand *result)
2226 {
2227     int size ,offset =0 ;
2228     char *l;
2229
2230     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2231     /* for this we just need to flip the 
2232     first it then copy the rest in place */
2233     size = AOP_SIZE(op) - 1;
2234     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2235
2236     MOVA(l);    
2237
2238     pic16_emitcode("cpl","acc.7");
2239     pic16_aopPut(AOP(result),"a",3);    
2240
2241     while(size--) {
2242         pic16_aopPut(AOP(result),
2243                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2244                offset);
2245         offset++;
2246     }          
2247 }
2248
2249 /*-----------------------------------------------------------------*/
2250 /* genUminus - unary minus code generation                         */
2251 /*-----------------------------------------------------------------*/
2252 static void genUminus (iCode *ic)
2253 {
2254   int size, i;
2255   sym_link *optype, *rtype;
2256
2257
2258   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2259   /* assign asmops */
2260   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2261   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2262
2263   /* if both in bit space then special
2264      case */
2265   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2266       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2267
2268     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2269     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2270     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2271
2272     goto release; 
2273   } 
2274
2275   optype = operandType(IC_LEFT(ic));
2276   rtype = operandType(IC_RESULT(ic));
2277
2278   /* if float then do float stuff */
2279   if (IS_FLOAT(optype)) {
2280     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2281     goto release;
2282   }
2283
2284   /* otherwise subtract from zero by taking the 2's complement */
2285   size = AOP_SIZE(IC_LEFT(ic));
2286
2287   for(i=0; i<size; i++) {
2288     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2289       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2290     else {
2291       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2292       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2293     }
2294   }
2295
2296   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2297   for(i=1; i<size; i++) {
2298     emitSKPNZ;
2299     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2300   }
2301
2302  release:
2303   /* release the aops */
2304   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2305   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2306 }
2307
2308 /*-----------------------------------------------------------------*/
2309 /* saveRegisters - will look for a call and save the registers     */
2310 /*-----------------------------------------------------------------*/
2311 static void saveRegisters(iCode *lic) 
2312 {
2313     int i;
2314     iCode *ic;
2315     bitVect *rsave;
2316     sym_link *dtype;
2317
2318     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2319     /* look for call */
2320     for (ic = lic ; ic ; ic = ic->next) 
2321         if (ic->op == CALL || ic->op == PCALL)
2322             break;
2323
2324     if (!ic) {
2325         fprintf(stderr,"found parameter push with no function call\n");
2326         return ;
2327     }
2328
2329     /* if the registers have been saved already then
2330     do nothing */
2331     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2332         return ;
2333
2334     /* find the registers in use at this time 
2335     and push them away to safety */
2336     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2337                           ic->rUsed);
2338
2339     ic->regsSaved = 1;
2340     if (options.useXstack) {
2341         if (bitVectBitValue(rsave,R0_IDX))
2342             pic16_emitcode("mov","b,r0");
2343         pic16_emitcode("mov","r0,%s",spname);
2344         for (i = 0 ; i < pic16_nRegs ; i++) {
2345             if (bitVectBitValue(rsave,i)) {
2346                 if (i == R0_IDX)
2347                     pic16_emitcode("mov","a,b");
2348                 else
2349                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2350                 pic16_emitcode("movx","@r0,a");
2351                 pic16_emitcode("inc","r0");
2352             }
2353         }
2354         pic16_emitcode("mov","%s,r0",spname);
2355         if (bitVectBitValue(rsave,R0_IDX))
2356             pic16_emitcode("mov","r0,b");           
2357     }// else
2358     //for (i = 0 ; i < pic16_nRegs ; i++) {
2359     //    if (bitVectBitValue(rsave,i))
2360     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2361     //}
2362
2363     dtype = operandType(IC_LEFT(ic));
2364     if (currFunc && dtype && 
2365         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2366         IFFUNC_ISISR(currFunc->type) &&
2367         !ic->bankSaved) 
2368
2369         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2370
2371 }
2372 /*-----------------------------------------------------------------*/
2373 /* unsaveRegisters - pop the pushed registers                      */
2374 /*-----------------------------------------------------------------*/
2375 static void unsaveRegisters (iCode *ic)
2376 {
2377     int i;
2378     bitVect *rsave;
2379
2380     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2381     /* find the registers in use at this time 
2382     and push them away to safety */
2383     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2384                           ic->rUsed);
2385     
2386     if (options.useXstack) {
2387         pic16_emitcode("mov","r0,%s",spname);   
2388         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2389             if (bitVectBitValue(rsave,i)) {
2390                 pic16_emitcode("dec","r0");
2391                 pic16_emitcode("movx","a,@r0");
2392                 if (i == R0_IDX)
2393                     pic16_emitcode("mov","b,a");
2394                 else
2395                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2396             }       
2397
2398         }
2399         pic16_emitcode("mov","%s,r0",spname);
2400         if (bitVectBitValue(rsave,R0_IDX))
2401             pic16_emitcode("mov","r0,b");
2402     } //else
2403     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2404     //    if (bitVectBitValue(rsave,i))
2405     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2406     //}
2407
2408 }  
2409
2410 #if 0  // patch 14
2411 /*-----------------------------------------------------------------*/
2412 /* pushSide -                                                      */
2413 /*-----------------------------------------------------------------*/
2414 static void pushSide(operand * oper, int size)
2415 {
2416         int offset = 0;
2417     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2418         while (size--) {
2419                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2420                 if (AOP_TYPE(oper) != AOP_REG &&
2421                     AOP_TYPE(oper) != AOP_DIR &&
2422                     strcmp(l,"a") ) {
2423                         pic16_emitcode("mov","a,%s",l);
2424                         pic16_emitcode("push","acc");
2425                 } else
2426                         pic16_emitcode("push","%s",l);
2427         }
2428 }
2429 #endif // patch 14
2430
2431 void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
2432 {
2433 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
2434
2435         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
2436                 pic16_emitpcode(POC_MOVFW, src);
2437                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(op), offset));
2438         } else {
2439                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
2440                         src, pic16_popGet(AOP(op), offset)));
2441         }
2442 }
2443
2444
2445 /*-----------------------------------------------------------------*/
2446 /* assignResultValue - assign results to oper, rescall==1 is       */
2447 /*                     called from genCall() or genPCall()         */
2448 /*-----------------------------------------------------------------*/
2449 static void assignResultValue(operand * oper, int rescall)
2450 {
2451   int size = AOP_SIZE(oper);
2452
2453         DEBUGpic16_emitcode ("; ***","%s  %d rescall:%d size:%d",__FUNCTION__,__LINE__,rescall,size); // patch 14
2454         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2455
2456         if(rescall) {
2457                 /* assign result from a call/pcall function() */
2458                 
2459                 /* function results are stored in a special order,
2460                  * see top of file with Function return policy, or manual */
2461
2462                 if(size <= 4) {
2463                         /* 8-bits, result in WREG */
2464                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
2465                         
2466                         if(size>1) {
2467                                 /* 16-bits, result in PRODL:WREG */
2468                                 pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
2469                         }
2470                         
2471                         if(size>2) {
2472                                 /* 24-bits, result in PRODH:PRODL:WREG */
2473                                 pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
2474                         }
2475                         
2476                         if(size>3) {
2477                                 /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
2478                                 pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
2479                         }
2480                 } else {
2481                         /* >32-bits, result on stack, and FSR0 points to beginning.
2482                          * Fix stack when done */
2483                          
2484                         while (size--) {
2485 //                              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2486 //                              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2487                 
2488                                 popaopidx(AOP(oper), size, GpsuedoStkPtr);
2489                                 GpsuedoStkPtr++;
2490                         }
2491                         
2492                         /* fix stack */
2493                         pic16_emitpcode(POC_MOVLW, pic16_popGetLit( AOP_SIZE(oper) ));
2494                         pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2495                         if(STACK_MODEL_LARGE) {
2496                                 emitSKPNC;
2497                                 pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2498                         }
2499                 }                       
2500         } else {        
2501                 if(!GpsuedoStkPtr) {
2502 //                      DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2503                         /* The last byte in the assignment is in W */
2504                         size--;
2505                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2506                         GpsuedoStkPtr++;
2507                 }
2508
2509                 while (size--) {
2510 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2511 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2512                 
2513                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2514                         GpsuedoStkPtr++;
2515
2516 #if 0
2517 #if STACK_SUPPORT
2518                 if(!USE_STACK)
2519                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2520 #else
2521                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2522 #endif
2523 #endif
2524
2525                 }
2526         }
2527                 
2528 }
2529
2530
2531 /*-----------------------------------------------------------------*/
2532 /* genIpush - genrate code for pushing this gets a little complex  */
2533 /*-----------------------------------------------------------------*/
2534 static void genIpush (iCode *ic)
2535 {
2536
2537   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2538 #if 0
2539     int size, offset = 0 ;
2540     char *l;
2541
2542
2543     /* if this is not a parm push : ie. it is spill push 
2544     and spill push is always done on the local stack */
2545     if (!ic->parmPush) {
2546
2547         /* and the item is spilt then do nothing */
2548         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2549             return ;
2550
2551         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2552         size = AOP_SIZE(IC_LEFT(ic));
2553         /* push it on the stack */
2554         while(size--) {
2555             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2556             if (*l == '#') {
2557                 MOVA(l);
2558                 l = "acc";
2559             }
2560             pic16_emitcode("push","%s",l);
2561         }
2562         return ;        
2563     }
2564
2565     /* this is a paramter push: in this case we call
2566     the routine to find the call and save those
2567     registers that need to be saved */   
2568     saveRegisters(ic);
2569
2570     /* then do the push */
2571     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2572
2573
2574         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2575     size = AOP_SIZE(IC_LEFT(ic));
2576
2577     while (size--) {
2578         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2579         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2580             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2581             strcmp(l,"a") ) {
2582             pic16_emitcode("mov","a,%s",l);
2583             pic16_emitcode("push","acc");
2584         } else
2585             pic16_emitcode("push","%s",l);
2586     }       
2587
2588     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2589 #endif
2590 }
2591
2592 /*-----------------------------------------------------------------*/
2593 /* genIpop - recover the registers: can happen only for spilling   */
2594 /*-----------------------------------------------------------------*/
2595 static void genIpop (iCode *ic)
2596 {
2597   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2598 #if 0
2599     int size,offset ;
2600
2601
2602     /* if the temp was not pushed then */
2603     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2604         return ;
2605
2606     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2607     size = AOP_SIZE(IC_LEFT(ic));
2608     offset = (size-1);
2609     while (size--) 
2610         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2611                                    FALSE,TRUE));
2612
2613     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2614 #endif
2615 }
2616
2617 /*-----------------------------------------------------------------*/
2618 /* unsaverbank - restores the resgister bank from stack            */
2619 /*-----------------------------------------------------------------*/
2620 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2621 {
2622   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2623 #if 0
2624     int i;
2625     asmop *aop ;
2626     regs *r = NULL;
2627
2628     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2629     if (popPsw) {
2630         if (options.useXstack) {
2631             aop = newAsmop(0);
2632             r = getFreePtr(ic,&aop,FALSE);
2633             
2634             
2635             pic16_emitcode("mov","%s,_spx",r->name);
2636             pic16_emitcode("movx","a,@%s",r->name);
2637             pic16_emitcode("mov","psw,a");
2638             pic16_emitcode("dec","%s",r->name);
2639             
2640         }else
2641             pic16_emitcode ("pop","psw");
2642     }
2643
2644     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2645         if (options.useXstack) {       
2646             pic16_emitcode("movx","a,@%s",r->name);
2647             //pic16_emitcode("mov","(%s+%d),a",
2648             //       regspic16[i].base,8*bank+regspic16[i].offset);
2649             pic16_emitcode("dec","%s",r->name);
2650
2651         } else 
2652           pic16_emitcode("pop",""); //"(%s+%d)",
2653         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2654     }
2655
2656     if (options.useXstack) {
2657
2658         pic16_emitcode("mov","_spx,%s",r->name);
2659         pic16_freeAsmop(NULL,aop,ic,TRUE);
2660
2661     }
2662 #endif 
2663 }
2664
2665 /*-----------------------------------------------------------------*/
2666 /* saverbank - saves an entire register bank on the stack          */
2667 /*-----------------------------------------------------------------*/
2668 static void saverbank (int bank, iCode *ic, bool pushPsw)
2669 {
2670   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2671 #if 0
2672     int i;
2673     asmop *aop ;
2674     regs *r = NULL;
2675
2676     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2677     if (options.useXstack) {
2678
2679         aop = newAsmop(0);
2680         r = getFreePtr(ic,&aop,FALSE);  
2681         pic16_emitcode("mov","%s,_spx",r->name);
2682
2683     }
2684
2685     for (i = 0 ; i < pic16_nRegs ;i++) {
2686         if (options.useXstack) {
2687             pic16_emitcode("inc","%s",r->name);
2688             //pic16_emitcode("mov","a,(%s+%d)",
2689             //         regspic16[i].base,8*bank+regspic16[i].offset);
2690             pic16_emitcode("movx","@%s,a",r->name);           
2691         } else 
2692           pic16_emitcode("push","");// "(%s+%d)",
2693                      //regspic16[i].base,8*bank+regspic16[i].offset);
2694     }
2695     
2696     if (pushPsw) {
2697         if (options.useXstack) {
2698             pic16_emitcode("mov","a,psw");
2699             pic16_emitcode("movx","@%s,a",r->name);     
2700             pic16_emitcode("inc","%s",r->name);
2701             pic16_emitcode("mov","_spx,%s",r->name);       
2702             pic16_freeAsmop (NULL,aop,ic,TRUE);
2703             
2704         } else
2705             pic16_emitcode("push","psw");
2706         
2707         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2708     }
2709     ic->bankSaved = 1;
2710 #endif
2711 }
2712
2713
2714
2715 /*-----------------------------------------------------------------*/
2716 /* genCall - generates a call statement                            */
2717 /*-----------------------------------------------------------------*/
2718 static void genCall (iCode *ic)
2719 {
2720   sym_link *dtype;   
2721   int stackParms=0;
2722   
2723         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2724
2725         /* if caller saves & we have not saved then */
2726         if (!ic->regsSaved)
2727                 saveRegisters(ic);
2728
2729         /* if we are calling a function that is not using
2730          * the same register bank then we need to save the
2731          * destination registers on the stack */
2732         dtype = operandType(IC_LEFT(ic));
2733         if (currFunc && dtype && 
2734                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2735                 IFFUNC_ISISR(currFunc->type) &&
2736                 !ic->bankSaved) 
2737
2738                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2739
2740         /* if send set is not empty the assign */
2741         if (_G.sendSet) {
2742           iCode *sic;
2743
2744                 /* For the Pic port, there is no data stack.
2745                  * So parameters passed to functions are stored
2746                  * in registers. (The pCode optimizer will get
2747                  * rid of most of these :). */
2748
2749           int psuedoStkPtr=-1; 
2750           int firstTimeThruLoop = 1;
2751
2752                 _G.sendSet = reverseSet(_G.sendSet);
2753
2754                 /* First figure how many parameters are getting passed */
2755                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2756                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2757                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2758                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2759                 }
2760
2761                 stackParms = psuedoStkPtr;
2762
2763                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2764                   int size, offset = 0;
2765
2766                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2767                         size = AOP_SIZE(IC_LEFT(sic));
2768
2769                         while (size--) {
2770                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2771                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2772                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2773
2774                                 if(!firstTimeThruLoop) {
2775                                         /* If this is not the first time we've been through the loop
2776                                          * then we need to save the parameter in a temporary
2777                                          * register. The last byte of the last parameter is
2778                                          * passed in W. */
2779
2780                                         pushw();
2781                                         --psuedoStkPtr;         // sanity check
2782                                 }
2783                         
2784                                 firstTimeThruLoop=0;
2785
2786                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2787                                 offset++;
2788                         }
2789                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2790                 }
2791                 _G.sendSet = NULL;
2792         }
2793
2794         /* make the call */
2795         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2796                         OP_SYMBOL(IC_LEFT(ic))->rname :
2797                         OP_SYMBOL(IC_LEFT(ic))->name));
2798
2799         GpsuedoStkPtr=0;
2800         /* if we need assign a result value */
2801         if ((IS_ITEMP(IC_RESULT(ic)) && 
2802                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2803                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2804                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2805
2806                 _G.accInUse++;
2807                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2808                 _G.accInUse--;
2809
2810                 assignResultValue(IC_RESULT(ic), 1);
2811
2812                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2813                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2814                 
2815                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2816         }
2817
2818         if(stackParms>0) {
2819                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2820                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2821                 if(STACK_MODEL_LARGE) {
2822                         emitSKPNC;
2823                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2824                 }
2825         }
2826
2827         /* adjust the stack for parameters if required */
2828 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2829
2830         if (ic->parmBytes) {
2831           int i;
2832
2833                 if (ic->parmBytes > 3) {
2834                         pic16_emitcode("mov","a,%s",spname);
2835                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2836                         pic16_emitcode("mov","%s,a",spname);
2837                 } else 
2838                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2839                                 pic16_emitcode("dec","%s",spname);
2840         }
2841
2842 #if 0
2843         /* if register bank was saved then pop them */
2844         if (ic->bankSaved)
2845                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2846
2847         /* if we hade saved some registers then unsave them */
2848         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2849                 unsaveRegisters (ic);
2850 #endif
2851 }
2852
2853
2854
2855 /*-----------------------------------------------------------------*/   // patch 14
2856 /* genPcall - generates a call by pointer statement                */
2857 /*-----------------------------------------------------------------*/
2858
2859 // new version, created from genCall
2860
2861 static void genPcall (iCode *ic)
2862 {
2863   sym_link *dtype;   
2864   int stackParms=0;
2865   symbol *retlbl = newiTempLabel(NULL);
2866   pCodeOp *pcop_lbl = pic16_popGetLabel(retlbl->key);
2867   
2868         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2869
2870         /* if caller saves & we have not saved then */
2871         if (!ic->regsSaved)
2872                 saveRegisters(ic);
2873
2874         /* if we are calling a function that is not using
2875          * the same register bank then we need to save the
2876          * destination registers on the stack */
2877         dtype = operandType(IC_LEFT(ic));
2878         if (currFunc && dtype && 
2879                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2880                 IFFUNC_ISISR(currFunc->type) &&
2881                 !ic->bankSaved) 
2882
2883                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2884
2885         /* if send set is not empty the assign */
2886         if (_G.sendSet) {
2887           iCode *sic;
2888
2889                 /* For the Pic port, there is no data stack.
2890                  * So parameters passed to functions are stored
2891                  * in registers. (The pCode optimizer will get
2892                  * rid of most of these :). */
2893
2894           int psuedoStkPtr=-1; 
2895           int firstTimeThruLoop = 1;
2896
2897                 _G.sendSet = reverseSet(_G.sendSet);
2898
2899                 /* First figure how many parameters are getting passed */
2900                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2901                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2902                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2903                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2904                 }
2905
2906                 stackParms = psuedoStkPtr;
2907
2908                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2909                   int size, offset = 0;
2910
2911                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2912                         size = AOP_SIZE(IC_LEFT(sic));
2913
2914                         while (size--) {
2915                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2916                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2917                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2918
2919                                 if(!firstTimeThruLoop) {
2920                                         /* If this is not the first time we've been through the loop
2921                                          * then we need to save the parameter in a temporary
2922                                          * register. The last byte of the last parameter is
2923                                          * passed in W. */
2924
2925                                         pushw();
2926                                         --psuedoStkPtr;         // sanity check
2927                                 }
2928                         
2929                                 firstTimeThruLoop=0;
2930
2931                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2932                                 offset++;
2933                         }
2934                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2935                 }
2936                 _G.sendSet = NULL;
2937         }
2938
2939         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2940
2941         // push return address
2942         // push $ on return stack, then replace with retlbl
2943
2944         // Note: retlbl is supplied as dummy operand to PUSH
2945         // This has the nice side effect of keeping the label from being optimized out :o)
2946         pic16_emitpcode(POC_PUSH, pic16_popGetLabel(retlbl->key));      
2947
2948         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 0, 0));
2949         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosl));
2950         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 1, 0));
2951         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosh));
2952         pic16_emitpcode(POC_MOVLW, pic16_popGetImmd(pcop_lbl->name, 2, 0));
2953         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_tosu));
2954
2955         /* make the call by writing the pointer into pc */
2956 // FIXME Disabled writes to PCLATU because of gpsim problems
2957 #if 0
2958         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),2), pic16_popCopyReg(&pic16_pc_pclatu)));
2959 #else
2960         fprintf(stderr,
2961 "WARNING: (%s:%d) PCLATU is not written because of gpsim problems\n\
2962 Correct this as soon as gpsim bug is fixed\n", __FILE__, __LINE__);
2963 #endif
2964  
2965         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)),1), pic16_popCopyReg(&pic16_pc_pclath)));
2966         // note: MOVFF to PCL not allowed
2967         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
2968         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
2969
2970         /* return address is here: (X) */
2971         pic16_emitpLabel(retlbl->key);
2972
2973         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
2974
2975         GpsuedoStkPtr=0;
2976         /* if we need assign a result value */
2977         if ((IS_ITEMP(IC_RESULT(ic)) && 
2978                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2979                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2980                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2981
2982                 _G.accInUse++;
2983                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2984                 _G.accInUse--;
2985
2986                 assignResultValue(IC_RESULT(ic), 1);
2987
2988                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2989                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2990                 
2991                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2992         }
2993
2994         if(stackParms>0) {
2995                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2996                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2997                 if(STACK_MODEL_LARGE) {
2998                         emitSKPNC;
2999                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
3000                 }
3001         }
3002
3003         /* adjust the stack for parameters if required */
3004 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
3005
3006         if (ic->parmBytes) {
3007           int i;
3008
3009                 if (ic->parmBytes > 3) {
3010                         pic16_emitcode("mov","a,%s",spname);
3011                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3012                         pic16_emitcode("mov","%s,a",spname);
3013                 } else 
3014                         for ( i = 0 ; i <  ic->parmBytes ;i++)
3015                                 pic16_emitcode("dec","%s",spname);
3016         }
3017
3018         /* if register bank was saved then pop them */
3019         if (ic->bankSaved)
3020                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3021
3022         /* if we hade saved some registers then unsave them */
3023         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
3024                 unsaveRegisters (ic);
3025 }
3026
3027
3028 #if 0                                                                           // patch 14
3029 // old version, kept for reference
3030
3031 /*-----------------------------------------------------------------*/
3032 /* genPcall - generates a call by pointer statement                */
3033 /*-----------------------------------------------------------------*/
3034 static void genPcall (iCode *ic)
3035 {
3036     sym_link *dtype;
3037     symbol *rlbl = newiTempLabel(NULL);
3038
3039
3040     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3041     /* if caller saves & we have not saved then */
3042     if (!ic->regsSaved)
3043         saveRegisters(ic);
3044
3045     /* if we are calling a function that is not using
3046     the same register bank then we need to save the
3047     destination registers on the stack */
3048     dtype = operandType(IC_LEFT(ic));
3049     if (currFunc && dtype && 
3050         IFFUNC_ISISR(currFunc->type) &&
3051         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3052         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
3053
3054
3055     /* push the return address on to the stack */
3056     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
3057     pic16_emitcode("push","acc");    
3058     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
3059     pic16_emitcode("push","acc");
3060     
3061     if (options.model == MODEL_FLAT24)
3062     {
3063         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
3064         pic16_emitcode("push","acc");    
3065     }
3066
3067     /* now push the calling address */
3068     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3069
3070     pushSide(IC_LEFT(ic), FPTRSIZE);
3071
3072     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
3073
3074     /* if send set is not empty the assign */
3075     if (_G.sendSet) {
3076         iCode *sic ;
3077
3078         for (sic = setFirstItem(_G.sendSet) ; sic ; 
3079              sic = setNextItem(_G.sendSet)) {
3080             int size, offset = 0;
3081             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
3082             size = AOP_SIZE(IC_LEFT(sic));
3083             while (size--) {
3084                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
3085                                 FALSE,FALSE);
3086                 if (strcmp(l,fReturn[offset]))
3087                     pic16_emitcode("mov","%s,%s",
3088                              fReturn[offset],
3089                              l);
3090                 offset++;
3091             }
3092             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
3093         }
3094         _G.sendSet = NULL;
3095     }
3096
3097     pic16_emitcode("ret","");
3098     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
3099
3100
3101     /* if we need assign a result value */
3102     if ((IS_ITEMP(IC_RESULT(ic)) &&
3103          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
3104           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
3105         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
3106
3107         _G.accInUse++;
3108         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
3109         _G.accInUse--;
3110         
3111         assignResultValue(IC_RESULT(ic), 1);
3112
3113         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
3114     }
3115
3116     /* adjust the stack for parameters if 
3117     required */
3118     if (ic->parmBytes) {
3119         int i;
3120         if (ic->parmBytes > 3) {
3121             pic16_emitcode("mov","a,%s",spname);
3122             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
3123             pic16_emitcode("mov","%s,a",spname);
3124         } else 
3125             for ( i = 0 ; i <  ic->parmBytes ;i++)
3126                 pic16_emitcode("dec","%s",spname);
3127
3128     }
3129
3130     /* if register bank was saved then unsave them */
3131     if (currFunc && dtype && 
3132         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
3133         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
3134
3135     /* if we hade saved some registers then
3136     unsave them */
3137     if (ic->regsSaved)
3138         unsaveRegisters (ic);
3139
3140 }
3141 #endif                                                                          // patch 14
3142
3143
3144 /*-----------------------------------------------------------------*/
3145 /* resultRemat - result  is rematerializable                       */
3146 /*-----------------------------------------------------------------*/
3147 static int resultRemat (iCode *ic)
3148 {
3149   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3150   if (SKIP_IC(ic) || ic->op == IFX)
3151     return 0;
3152
3153   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
3154     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
3155     if (sym->remat && !POINTER_SET(ic)) 
3156       return 1;
3157   }
3158
3159   return 0;
3160 }
3161
3162 #if defined(__BORLANDC__) || defined(_MSC_VER)
3163 #define STRCASECMP stricmp
3164 #else
3165 #define STRCASECMP strcasecmp
3166 #endif
3167
3168 #if 0
3169 /*-----------------------------------------------------------------*/
3170 /* inExcludeList - return 1 if the string is in exclude Reg list   */
3171 /*-----------------------------------------------------------------*/
3172 static bool inExcludeList(char *s)
3173 {
3174   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
3175     int i =0;
3176     
3177     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3178     if (options.excludeRegs[i] &&
3179     STRCASECMP(options.excludeRegs[i],"none") == 0)
3180         return FALSE ;
3181
3182     for ( i = 0 ; options.excludeRegs[i]; i++) {
3183         if (options.excludeRegs[i] &&
3184         STRCASECMP(s,options.excludeRegs[i]) == 0)
3185             return TRUE;
3186     }
3187     return FALSE ;
3188 }
3189 #endif
3190
3191 /*-----------------------------------------------------------------*/
3192 /* genFunction - generated code for function entry                 */
3193 /*-----------------------------------------------------------------*/
3194 static void genFunction (iCode *ic)
3195 {
3196   symbol *sym;
3197   sym_link *ftype;
3198   
3199         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
3200
3201         labelOffset += (max_key+4);
3202         max_key=0;
3203         GpsuedoStkPtr=0;
3204         _G.nRegsSaved = 0;
3205
3206         ftype = operandType(IC_LEFT(ic));
3207         sym = OP_SYMBOL(IC_LEFT(ic));
3208
3209         if(IFFUNC_ISISR(sym->type /*ftype*/)) {
3210                 /* create an absolute section at the interrupt vector:
3211                  * that is 0x0008 for interrupt 1 (high), 0x0018 interrupt 2 (low) */
3212           symbol *asym;
3213           char asymname[128];
3214           pBlock *apb;
3215
3216                 {
3217                   int i, found=-1;
3218
3219                         sym = OP_SYMBOL( IC_LEFT(ic));
3220                         for(i=0;i<=2;i++) {
3221                                 if(interrupts[i]->name
3222                                         && !STRCASECMP(interrupts[i]->name, sym->name)) {
3223                                         found = i;
3224                                         break;
3225                                 }
3226                         }
3227                         
3228                         if(found == -1) {
3229                                 fprintf(stderr, "PIC16 port: %s:%d: interrupt function but cannot locate symbol (%s)\n",
3230                                         __FILE__, __LINE__, sym->name);
3231                                 assert( 0 );
3232                         }
3233                         _G.interruptvector = found;
3234                 }
3235
3236                 sprintf(asymname, "ivec_%d_%s", _G.interruptvector, sym->name);
3237                 asym = newSymbol(asymname, 0);
3238
3239                 apb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute section"));
3240                 pic16_addpBlock( apb );
3241
3242                 pic16_addpCode2pBlock(apb,
3243                         pic16_newpCodeCharP(";-----------------------------------------"));
3244
3245
3246                 pic16_addpCode2pBlock(apb, pic16_newpCodeFunction(moduleName, asym->name));
3247
3248                 pic16_addpCode2pBlock(apb,
3249                         pic16_newpCode(POC_GOTO, pic16_popGetWithString( sym->rname )));
3250                 
3251                 /* mark the end of this tiny function */
3252                 pic16_addpCode2pBlock(apb,pic16_newpCodeFunction(NULL,NULL));
3253
3254                 {
3255                   absSym *abSym;
3256
3257                         abSym = Safe_calloc(1, sizeof(absSym));
3258                         abSym->name = Safe_strdup( asymname );
3259
3260                         switch( _G.interruptvector ) {
3261                                 case 0: abSym->address = 0x000000; break;
3262                                 case 1: abSym->address = 0x000008; break;
3263                                 case 2: abSym->address = 0x000018; break;
3264                         }
3265
3266                         addSet(&absSymSet, abSym);
3267                 }
3268         }
3269
3270
3271         /* create the function header */
3272         pic16_emitcode(";","-----------------------------------------");
3273         pic16_emitcode(";"," function %s",sym->name);
3274         pic16_emitcode(";","-----------------------------------------");
3275
3276         pic16_emitcode("","%s:",sym->rname);
3277         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
3278
3279
3280         {
3281           absSym *ab;
3282
3283                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
3284                         if(!strcmp(ab->name, sym->name)) {
3285                                 pic16_pBlockConvert2Absolute(pb);
3286                                 break;
3287                         }
3288
3289         }
3290
3291
3292         if(IFFUNC_ISNAKED(ftype)) {
3293                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
3294                 return;
3295         }
3296         
3297         /* if critical function then turn interrupts off */
3298         if (IFFUNC_ISCRITICAL(ftype))
3299                 pic16_emitcode("clr","ea");
3300
3301         /* if this is an interrupt service routine then
3302          * save acc, b, dpl, dph  */
3303         if (IFFUNC_ISISR(sym->type)) {
3304           int i;
3305                 /* an ISR should save: WREG, STATUS, BSR, PRODL, PRODH, FSR0L, FSR0H */
3306                 if(!(_G.interruptvector == 1)) {
3307
3308                         /* do not save WREG,STATUS,BSR for high priority interrupts
3309                          * because they are stored in the hardware shadow registers already */
3310                          
3311                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3312                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3313                         pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3314                 }
3315
3316                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3317                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3318                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l ));
3319                 pic16_pushpCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3320
3321 //                pic16_pBlockConvert2ISR(pb);
3322                 
3323                 /* if any registers used */
3324                 if (sym->regsUsed) {
3325                         /* save the registers used */
3326                         DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3327                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3328                                 if (bitVectBitValue(sym->regsUsed,i)) {
3329 //                                      fprintf(stderr, "%s:%d function %s uses register %s\n",
3330 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3331 //                                                      pic16_regWithIdx(i)->name);
3332
3333                                         pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3334                                         _G.nRegsSaved++;
3335                                 }
3336                         }
3337                 }
3338         } else {
3339                 /* emit code to setup stack frame if user enabled,
3340                  * and function is not main() */
3341          
3342 //              fprintf(stderr, "function name: %s\n", sym->name);
3343                 if(strcmp(sym->name, "main")) {
3344                         if(/*!options.ommitFramePtr || */sym->regsUsed) {
3345                         /* setup the stack frame */
3346                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
3347                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
3348                                 if(STACK_MODEL_LARGE)
3349                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
3350                         }
3351                 }
3352
3353                 /* if callee-save to be used for this function
3354                 * then save the registers being used in this function */
3355 //              if (IFFUNC_CALLEESAVES(sym->type))
3356                 {
3357                   int i;
3358
3359 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %d\n", __FILE__, __LINE__, sym->regsUsed->size);
3360
3361 //                      pic16_emitpcomment("entry regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3362
3363                         /* if any registers used */
3364                         if (sym->regsUsed) {
3365                                 /* save the registers used */
3366                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
3367                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
3368                                         if (bitVectBitValue(sym->regsUsed,i)) {
3369
3370 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3371 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3372 //                                                              pic16_regWithIdx(i)->name);
3373
3374                                                 pic16_pushpCodeOp( pic16_popRegFromIdx(i) );
3375
3376 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3377 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
3378 //                                                      &pic16_pc_postdec1, 0));
3379
3380                                                 _G.nRegsSaved++;
3381                                         }
3382                                 }
3383                         }
3384                 }
3385         }
3386
3387
3388         
3389 #if 0
3390         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
3391
3392                 if (options.useXstack) {
3393                         pic16_emitcode("mov","r0,%s",spname);
3394                         pic16_emitcode("mov","a,_bp");
3395                         pic16_emitcode("movx","@r0,a");
3396                         pic16_emitcode("inc","%s",spname);
3397                 } else {
3398                         /* set up the stack */
3399                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
3400                 }
3401                 pic16_emitcode ("mov","_bp,%s",spname);
3402         }
3403 #endif
3404         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
3405
3406         /* adjust the stack for the function */
3407         if (sym->stack) {
3408           int i = sym->stack;
3409
3410                 if (i > 127 ) 
3411                         werror(W_STACK_OVERFLOW,sym->name);
3412
3413                 if (i > 3 && sym->recvSize < 4) {              
3414                         pic16_emitcode ("mov","a,sp");
3415                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3416                         pic16_emitcode ("mov","sp,a");
3417                 } else
3418                         while(i--)
3419                                 pic16_emitcode("inc","sp");
3420         }
3421
3422         if (sym->xstack) {
3423                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3424
3425                 pic16_emitcode ("mov","a,_spx");
3426                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3427                 pic16_emitcode ("mov","_spx,a");
3428         }
3429     
3430 }
3431
3432 /*-----------------------------------------------------------------*/
3433 /* genEndFunction - generates epilogue for functions               */
3434 /*-----------------------------------------------------------------*/
3435 static void genEndFunction (iCode *ic)
3436 {
3437     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3438
3439     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3440
3441     if(IFFUNC_ISNAKED(sym->type)) {
3442         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3443         return;
3444     }
3445
3446 #if 0
3447     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3448     {
3449         pic16_emitcode ("mov","%s,_bp",spname);
3450     }
3451 #endif
3452
3453     /* if use external stack but some variables were
3454     added to the local stack then decrement the
3455     local stack */
3456     if (options.useXstack && sym->stack) {      
3457         pic16_emitcode("mov","a,sp");
3458         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3459         pic16_emitcode("mov","sp,a");
3460     }
3461
3462
3463 #if 0
3464     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3465         if (options.useXstack) {
3466             pic16_emitcode("mov","r0,%s",spname);
3467             pic16_emitcode("movx","a,@r0");
3468             pic16_emitcode("mov","_bp,a");
3469             pic16_emitcode("dec","%s",spname);
3470         }
3471         else
3472         {
3473             pic16_emitcode ("pop","_bp");
3474         }
3475     }
3476 #endif
3477
3478         if (IFFUNC_ISISR(sym->type)) {
3479                 /* now we need to restore the registers */
3480                 /* if any registers used */
3481                 if (sym->regsUsed) {
3482                   int i;
3483
3484                         /* restore registers used */
3485                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3486                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3487                                 if (bitVectBitValue(sym->regsUsed,i)) {
3488
3489 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3490 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3491 //                                                      pic16_regWithIdx(i)->name);
3492
3493                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3494
3495 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3496 //                                                      &pic16_pc_preinc1,
3497 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3498
3499                                 }
3500                         }
3501                 }
3502         
3503                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0h ));
3504                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_fsr0l));
3505                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodh ));
3506                 pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_prodl ));
3507
3508                 if(!(_G.interruptvector == 1)) {
3509                         /* do not restore interrupt vector for WREG,STATUS,BSR
3510                          * for high priority interrupt, see genFunction */
3511                          
3512                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_bsr ));
3513                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_status ));
3514                         pic16_poppCodeOp( pic16_popCopyReg( &pic16_pc_wreg ));
3515                 }
3516         
3517                 _G.interruptvector = 0;         /* sanity check */
3518
3519 //              pic16_pBlockConvert2ISR(pb);
3520
3521
3522                 /* if debug then send end of function */
3523 /*      if (options.debug && currFunc)  */
3524                 if (currFunc) {
3525                         debugFile->writeEndFunction (currFunc, ic, 1);
3526                 }
3527         
3528                 pic16_emitpcodeNULLop(POC_RETFIE);
3529         } else {
3530                 if (IFFUNC_ISCRITICAL(sym->type))
3531                         pic16_emitcode("setb","ea");
3532         
3533
3534 //              pic16_emitpcomment("exit regsUsed: %d\n", sym->regsUsed?sym->regsUsed->size:-1);
3535
3536                 /* if any registers used */
3537                 if (sym->regsUsed) {
3538                   int i;
3539                         /* save the registers used */
3540                         DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3541                         for ( i = sym->regsUsed->size; i >= 0; i--) {
3542                                 if (bitVectBitValue(sym->regsUsed,i)) {
3543         
3544 //                                      fprintf(stderr, "%s:%d function %s uses register %s (restoring)\n",
3545 //                                                      __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3546 //                                                      pic16_regWithIdx(i)->name);
3547         
3548                                         pic16_poppCodeOp( pic16_popRegFromIdx(i) );
3549                                         
3550 //                                      pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3551 //                                              &pic16_pc_preinc1,
3552 //                                              PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3553
3554                                         _G.nRegsSaved--;
3555                                 }
3556                         }
3557                 }
3558         
3559                 pic16_emitpcomment("%s: _G.nRegsSaved upon exit from function: %d\n", __FUNCTION__, _G.nRegsSaved);
3560                 /* if debug then send end of function */
3561                 if (currFunc) {
3562                         debugFile->writeEndFunction (currFunc, ic, 1);
3563                 }
3564
3565                 /* insert code to restore stack frame, if user enabled it
3566                  * and function is not main() */
3567          
3568
3569                 if(strcmp(sym->name, "main")) {
3570                         if(/*!options.ommitFramePtr ||*/ sym->regsUsed) {
3571                                 /* restore stack frame */
3572                                 if(STACK_MODEL_LARGE)
3573                                         pic16_emitpcode(POC_MOVFF,
3574                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2h, 0));
3575                                 pic16_emitpcode(POC_MOVFF,
3576                                                 pic16_popCombine2( &pic16_pc_preinc1, &pic16_pc_fsr2l, 0));
3577                         }
3578                 }
3579
3580                 pic16_emitcode ("return","");
3581                 pic16_emitpcodeNULLop(POC_RETURN);
3582
3583                 /* Mark the end of a function */
3584                 pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3585         }
3586
3587 }
3588
3589
3590 void pic16_storeForReturn(operand *op, int offset, pCodeOp *dest)
3591 {
3592 //              (AOP(left)->aopu.pcop->type == PO_DIR)?
3593
3594         if(AOP(op)->aopu.pcop->type == PO_IMMEDIATE) {
3595                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(op), offset)); // patch 12
3596                 pic16_emitpcode(POC_MOVWF, dest);
3597         } else {
3598                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3599                         pic16_popGet(AOP(op), offset), dest));
3600         }
3601 }
3602
3603 /*-----------------------------------------------------------------*/
3604 /* genRet - generate code for return statement                     */
3605 /*-----------------------------------------------------------------*/
3606 static void genRet (iCode *ic)
3607 {
3608   int size;
3609   operand *left;
3610
3611         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3612         /* if we have no return value then
3613          * just generate the "ret" */
3614         
3615         if (!IC_LEFT(ic)) 
3616                 goto jumpret;       
3617     
3618         /* we have something to return then
3619          * move the return value into place */
3620         pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
3621         size = AOP_SIZE(IC_LEFT(ic));
3622
3623         if(size <= 4) {
3624                 if(size>3) {
3625                         pic16_storeForReturn(IC_LEFT(ic), 3, pic16_popCopyReg(&pic16_pc_fsr0l));
3626 //                      pic16_emitpcode(POC_MOVFF,
3627 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 3), pic16_popCopyReg(&pic16_pc_fsr0l)));
3628                 }
3629                 if(size>2) {
3630                         pic16_storeForReturn(IC_LEFT(ic), 2, pic16_popCopyReg(&pic16_pc_prodh));
3631 //                      pic16_emitpcode(POC_MOVFF,
3632 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 2), pic16_popCopyReg(&pic16_pc_prodh)));
3633                 }
3634                 if(size>1) {
3635                         pic16_storeForReturn(IC_LEFT(ic), 1, pic16_popCopyReg(&pic16_pc_prodl));
3636 //                      pic16_emitpcode(POC_MOVFF,
3637 //                              pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 1), pic16_popCopyReg(&pic16_pc_prodl)));
3638                 }
3639
3640 //              pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)), 0));  // patch 12
3641
3642                 pic16_storeForReturn(IC_LEFT(ic), 0, pic16_popCopyReg(&pic16_pc_wreg));  // patch 12
3643 //              pic16_emitpcode(POC_MOVFF,
3644 //                      pic16_popGet2p(pic16_popGet(AOP(IC_LEFT(ic)), 0), pic16_popCopyReg(&pic16_pc_wreg)));
3645
3646         } else {
3647                 /* >32-bits, setup stack and FSR0 */
3648                 while (size--) {
3649 //                      DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
3650 //                      DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
3651
3652                         pic16_pushpCodeOp( pic16_popGet( AOP( IC_LEFT(ic) ), size) );
3653
3654 //                      popaopidx(AOP(oper), size, GpseudoStkPtr);
3655                         GpsuedoStkPtr++;
3656                 }
3657                         
3658                 /* setup FSR0 */
3659                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3660                         pic16_popCopyReg(&pic16_pc_fsr1l), pic16_popCopyReg(&pic16_pc_fsr0l)));
3661
3662                 if(STACK_MODEL_LARGE) {
3663                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
3664                                 pic16_popCopyReg(&pic16_pc_fsr1h), pic16_popCopyReg(&pic16_pc_fsr0h)));
3665                 } else {
3666                         pic16_emitpcode(POC_CLRF, pic16_popCopyReg( &pic16_pc_fsr1h ) );
3667                 }
3668         }
3669                                 
3670 #if 0
3671         /* old code, left here for reference -- VR */    
3672         while (size--) {
3673           char *l ;
3674
3675                 if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3676                         /* #NOCHANGE */
3677                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++, FALSE,TRUE);
3678                         pic16_emitpcomment("push %s",l);
3679                         pushed++;
3680                 } else {
3681                         DEBUGpic16_emitcode(";", "%d", __LINE__);
3682                         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset, FALSE,FALSE);
3683                         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3684                         
3685                         if (strcmp(fReturn[offset],l)) {
3686                                 if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD)
3687                                         || ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3688                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3689                                 } else {
3690                                         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3691                                 }
3692                                 
3693                                 if(size) {
3694                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3695                                 }
3696                                 offset++;
3697                         }
3698                 }
3699         }    
3700
3701         if (pushed) {
3702                 while(pushed) {
3703                         pushed--;
3704                         if (strcmp(fReturn[pushed],"a"))
3705                                 pic16_emitcode("pop",fReturn[pushed]);
3706                         else
3707                                 pic16_emitcode("pop","acc");
3708                 }
3709         }
3710 #endif
3711
3712
3713         pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3714     
3715 jumpret:
3716         /* generate a jump to the return label
3717          * if the next is not the return statement */
3718         if (!(ic->next && ic->next->op == LABEL
3719                 && IC_LABEL(ic->next) == returnLabel)) {
3720         
3721                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3722                 pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3723         }
3724 }
3725
3726 /*-----------------------------------------------------------------*/
3727 /* genLabel - generates a label                                    */
3728 /*-----------------------------------------------------------------*/
3729 static void genLabel (iCode *ic)
3730 {
3731
3732
3733     /* special case never generate */
3734     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3735     if (IC_LABEL(ic) == entryLabel)
3736         return ;
3737
3738     pic16_emitpLabel(IC_LABEL(ic)->key);
3739     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3740 }
3741
3742 /*-----------------------------------------------------------------*/
3743 /* genGoto - generates a goto                                      */
3744 /*-----------------------------------------------------------------*/
3745 //tsd
3746 static void genGoto (iCode *ic)
3747 {
3748   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3749   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3750 }
3751
3752
3753 /*-----------------------------------------------------------------*/
3754 /* genMultbits :- multiplication of bits                           */
3755 /*-----------------------------------------------------------------*/
3756 static void genMultbits (operand *left, 
3757                          operand *right, 
3758                          operand *result)
3759 {
3760   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3761
3762   if(!pic16_sameRegs(AOP(result),AOP(right)))
3763     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3764
3765   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3766   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3767   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3768
3769 }
3770
3771
3772 /*-----------------------------------------------------------------*/
3773 /* genMultOneByte : 8 bit multiplication & division                */
3774 /*-----------------------------------------------------------------*/
3775 static void genMultOneByte (operand *left,
3776                             operand *right,
3777                             operand *result)
3778 {
3779
3780   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3781   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3782   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3783
3784   /* (if two literals, the value is computed before) */
3785   /* if one literal, literal on the right */
3786   if (AOP_TYPE(left) == AOP_LIT){
3787     operand *t = right;
3788     right = left;
3789     left = t;
3790   }
3791
3792         /* size is already checked in genMult == 1 */
3793 //      size = AOP_SIZE(result);
3794
3795         if (AOP_TYPE(right) == AOP_LIT){
3796                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3797                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3798                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3799                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3800         } else {
3801                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3802                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3803                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3804                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3805         }
3806         
3807         pic16_genMult8X8_8 (left, right,result);
3808
3809
3810 #if 0
3811     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3812                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3813                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3814                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3815
3816     if (SPEC_USIGN(opetype)){
3817       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3818       pic16_genUMult8X8_16 (left, right, result, NULL);
3819
3820       if (size > 2) {
3821         /* for filling the MSBs */
3822         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3823         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3824       }
3825     }
3826     else{
3827       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3828
3829       pic16_emitcode("mov","a,b");
3830
3831       /* adjust the MSB if left or right neg */
3832
3833       /* if one literal */
3834       if (AOP_TYPE(right) == AOP_LIT){
3835         pic16_emitcode("multiply ","right is a lit");
3836         /* AND literal negative */
3837         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3838           /* adjust MSB (c==0 after mul) */
3839           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3840         }
3841       }
3842       else{
3843         pic16_genSMult8X8_16 (left, right, result, NULL);
3844       }
3845
3846       if(size > 2){
3847         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3848         /* get the sign */
3849         pic16_emitcode("rlc","a");
3850         pic16_emitcode("subb","a,acc");
3851       }
3852     }
3853
3854     size -= 2;   
3855     offset = 2;
3856     if (size > 0)
3857       while (size--)
3858         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3859     //pic16_aopPut(AOP(result),"a",offset++);
3860   }
3861 #endif
3862
3863
3864 }
3865
3866 /*-----------------------------------------------------------------*/
3867 /* genMultOneWord : 16 bit multiplication                          */
3868 /*-----------------------------------------------------------------*/
3869 static void genMultOneWord (operand *left,
3870                             operand *right,
3871                             operand *result)
3872 {
3873
3874         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3875         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3876         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3877
3878         /* (if two literals, the value is computed before)
3879          * if one literal, literal on the right */
3880         if (AOP_TYPE(left) == AOP_LIT){
3881           operand *t = right;
3882                 right = left;
3883                 left = t;
3884         }
3885
3886         /* size is checked already == 2 */
3887 //      size = AOP_SIZE(result);
3888
3889         if (AOP_TYPE(right) == AOP_LIT) {
3890                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3891                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3892                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3893                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3894         } else {
3895                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3896                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3897                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3898                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3899         }
3900         
3901         pic16_genMult16X16_16(left, right,result);
3902 }
3903
3904 /*-----------------------------------------------------------------*/
3905 /* genMultOneLong : 32 bit multiplication                          */
3906 /*-----------------------------------------------------------------*/
3907 static void genMultOneLong (operand *left,
3908                             operand *right,
3909                             operand *result)
3910 {
3911
3912         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3913         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3914         DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3915
3916         /* (if two literals, the value is computed before)
3917          * if one literal, literal on the right */
3918         if (AOP_TYPE(left) == AOP_LIT){
3919           operand *t = right;
3920                 right = left;
3921                 left = t;
3922         }
3923
3924         /* size is checked already == 4 */
3925 //      size = AOP_SIZE(result);
3926
3927         if (AOP_TYPE(right) == AOP_LIT) {
3928                 pic16_emitpcomment("multiply lit val:%s by variable %s and store in %s", 
3929                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3930                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3931                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3932         } else {
3933                 pic16_emitpcomment("multiply variable :%s by variable %s and store in %s", 
3934                                         pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3935                                         pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3936                                         pic16_aopGet(AOP(result),0,FALSE,FALSE));
3937         }
3938         
3939         pic16_genMult32X32_32(left, right,result);
3940 }
3941
3942
3943
3944 /*-----------------------------------------------------------------*/
3945 /* genMult - generates code for multiplication                     */
3946 /*-----------------------------------------------------------------*/
3947 static void genMult (iCode *ic)
3948 {
3949   operand *left = IC_LEFT(ic);
3950   operand *right = IC_RIGHT(ic);
3951   operand *result= IC_RESULT(ic);   
3952
3953         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3954         /* assign the amsops */
3955         pic16_aopOp (left,ic,FALSE);
3956         pic16_aopOp (right,ic,FALSE);
3957         pic16_aopOp (result,ic,TRUE);
3958
3959         DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3960
3961         /* special cases first *
3962         * both are bits */
3963         if (AOP_TYPE(left) == AOP_CRY
3964                 && AOP_TYPE(right)== AOP_CRY) {
3965                 genMultbits(left,right,result);
3966           goto release ;
3967         }
3968
3969         /* if both are of size == 1 */
3970         if(AOP_SIZE(left) == 1
3971                 && AOP_SIZE(right) == 1) {
3972                 genMultOneByte(left,right,result);
3973           goto release ;
3974         }
3975
3976         /* if both are of size == 2 */
3977         if(AOP_SIZE(left) == 2
3978                 && AOP_SIZE(right) == 2) {
3979                 genMultOneWord(left, right, result);
3980           goto release;
3981         }
3982         
3983         /* if both are of size == 4 */
3984         if(AOP_SIZE(left) == 4
3985                 && AOP_SIZE(right) == 4) {
3986                 genMultOneLong(left, right, result);
3987           goto release;
3988         }
3989         
3990         pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
3991
3992
3993         fprintf(stderr, "operand sizes result: %d left: %d right: %d\n", AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
3994         /* should have been converted to function call */
3995         assert(0) ;
3996
3997 release :
3998         pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3999         pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4000         pic16_freeAsmop(result,NULL,ic,TRUE); 
4001 }
4002
4003 /*-----------------------------------------------------------------*/
4004 /* genDivbits :- division of bits                                  */
4005 /*-----------------------------------------------------------------*/
4006 static void genDivbits (operand *left, 
4007                         operand *right, 
4008                         operand *result)
4009 {
4010
4011     char *l;
4012
4013     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4014     /* the result must be bit */    
4015     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4016     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4017
4018     MOVA(l);    
4019
4020     pic16_emitcode("div","ab");
4021     pic16_emitcode("rrc","a");
4022     pic16_aopPut(AOP(result),"c",0);
4023 }
4024
4025 /*-----------------------------------------------------------------*/
4026 /* genDivOneByte : 8 bit division                                  */
4027 /*-----------------------------------------------------------------*/
4028 static void genDivOneByte (operand *left,
4029                            operand *right,
4030                            operand *result)
4031 {
4032     sym_link *opetype = operandType(result);
4033     char *l ;
4034     symbol *lbl ;
4035     int size,offset;
4036
4037     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4038     size = AOP_SIZE(result) - 1;
4039     offset = 1;
4040     /* signed or unsigned */
4041     if (SPEC_USIGN(opetype)) {
4042         /* unsigned is easy */
4043         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4044         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4045         MOVA(l);        
4046         pic16_emitcode("div","ab");
4047         pic16_aopPut(AOP(result),"a",0);
4048         while (size--)
4049             pic16_aopPut(AOP(result),zero,offset++);
4050         return ;
4051     }
4052
4053     /* signed is a little bit more difficult */
4054
4055     /* save the signs of the operands */
4056     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4057     MOVA(l);    
4058     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
4059     pic16_emitcode("push","acc"); /* save it on the stack */
4060
4061     /* now sign adjust for both left & right */
4062     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4063     MOVA(l);       
4064     lbl = newiTempLabel(NULL);
4065     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
4066     pic16_emitcode("cpl","a");   
4067     pic16_emitcode("inc","a");
4068     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4069     pic16_emitcode("mov","b,a");
4070
4071     /* sign adjust left side */
4072     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4073     MOVA(l);
4074
4075     lbl = newiTempLabel(NULL);
4076     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4077     pic16_emitcode("cpl","a");
4078     pic16_emitcode("inc","a");
4079     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4080
4081     /* now the division */
4082     pic16_emitcode("div","ab");
4083     /* we are interested in the lower order
4084     only */
4085     pic16_emitcode("mov","b,a");
4086     lbl = newiTempLabel(NULL);
4087     pic16_emitcode("pop","acc");   
4088     /* if there was an over flow we don't 
4089     adjust the sign of the result */
4090     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4091     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4092     CLRC;
4093     pic16_emitcode("clr","a");
4094     pic16_emitcode("subb","a,b");
4095     pic16_emitcode("mov","b,a");
4096     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4097
4098     /* now we are done */
4099     pic16_aopPut(AOP(result),"b",0);
4100     if(size > 0){
4101         pic16_emitcode("mov","c,b.7");
4102         pic16_emitcode("subb","a,acc");   
4103     }
4104     while (size--)
4105         pic16_aopPut(AOP(result),"a",offset++);
4106
4107 }
4108
4109 /*-----------------------------------------------------------------*/
4110 /* genDiv - generates code for division                            */
4111 /*-----------------------------------------------------------------*/
4112 static void genDiv (iCode *ic)
4113 {
4114     operand *left = IC_LEFT(ic);
4115     operand *right = IC_RIGHT(ic);
4116     operand *result= IC_RESULT(ic);   
4117
4118     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4119     /* assign the amsops */
4120     pic16_aopOp (left,ic,FALSE);
4121     pic16_aopOp (right,ic,FALSE);
4122     pic16_aopOp (result,ic,TRUE);
4123
4124     /* special cases first */
4125     /* both are bits */
4126     if (AOP_TYPE(left) == AOP_CRY &&
4127         AOP_TYPE(right)== AOP_CRY) {
4128         genDivbits(left,right,result);
4129         goto release ;
4130     }
4131
4132     /* if both are of size == 1 */
4133     if (AOP_SIZE(left) == 1 &&
4134         AOP_SIZE(right) == 1 ) {
4135         genDivOneByte(left,right,result);
4136         goto release ;
4137     }
4138
4139     /* should have been converted to function call */
4140     assert(0);
4141 release :
4142     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4143     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4144     pic16_freeAsmop(result,NULL,ic,TRUE); 
4145 }
4146
4147 /*-----------------------------------------------------------------*/
4148 /* genModbits :- modulus of bits                                   */
4149 /*-----------------------------------------------------------------*/
4150 static void genModbits (operand *left, 
4151                         operand *right, 
4152                         operand *result)
4153 {
4154
4155     char *l;
4156
4157     /* the result must be bit */    
4158     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4159     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4160
4161     MOVA(l);       
4162
4163     pic16_emitcode("div","ab");
4164     pic16_emitcode("mov","a,b");
4165     pic16_emitcode("rrc","a");
4166     pic16_aopPut(AOP(result),"c",0);
4167 }
4168
4169 /*-----------------------------------------------------------------*/
4170 /* genModOneByte : 8 bit modulus                                   */
4171 /*-----------------------------------------------------------------*/
4172 static void genModOneByte (operand *left,
4173                            operand *right,
4174                            operand *result)
4175 {
4176     sym_link *opetype = operandType(result);
4177     char *l ;
4178     symbol *lbl ;
4179
4180     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4181     /* signed or unsigned */
4182     if (SPEC_USIGN(opetype)) {
4183         /* unsigned is easy */
4184         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
4185         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
4186         MOVA(l);    
4187         pic16_emitcode("div","ab");
4188         pic16_aopPut(AOP(result),"b",0);
4189         return ;
4190     }
4191
4192     /* signed is a little bit more difficult */
4193
4194     /* save the signs of the operands */
4195     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4196     MOVA(l);
4197
4198     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
4199     pic16_emitcode("push","acc"); /* save it on the stack */
4200
4201     /* now sign adjust for both left & right */
4202     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
4203     MOVA(l);
4204
4205     lbl = newiTempLabel(NULL);
4206     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
4207     pic16_emitcode("cpl","a");   
4208     pic16_emitcode("inc","a");
4209     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4210     pic16_emitcode("mov","b,a"); 
4211
4212     /* sign adjust left side */
4213     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
4214     MOVA(l);
4215
4216     lbl = newiTempLabel(NULL);
4217     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4218     pic16_emitcode("cpl","a");   
4219     pic16_emitcode("inc","a");
4220     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4221
4222     /* now the multiplication */
4223     pic16_emitcode("div","ab");
4224     /* we are interested in the lower order
4225     only */
4226     lbl = newiTempLabel(NULL);
4227     pic16_emitcode("pop","acc");   
4228     /* if there was an over flow we don't 
4229     adjust the sign of the result */
4230     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
4231     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
4232     CLRC ;
4233     pic16_emitcode("clr","a");
4234     pic16_emitcode("subb","a,b");
4235     pic16_emitcode("mov","b,a");
4236     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
4237
4238     /* now we are done */
4239     pic16_aopPut(AOP(result),"b",0);
4240
4241 }
4242
4243 /*-----------------------------------------------------------------*/
4244 /* genMod - generates code for division                            */
4245 /*-----------------------------------------------------------------*/
4246 static void genMod (iCode *ic)
4247 {
4248     operand *left = IC_LEFT(ic);
4249     operand *right = IC_RIGHT(ic);
4250     operand *result= IC_RESULT(ic);  
4251
4252     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4253     /* assign the amsops */
4254     pic16_aopOp (left,ic,FALSE);
4255     pic16_aopOp (right,ic,FALSE);
4256     pic16_aopOp (result,ic,TRUE);
4257
4258     /* special cases first */
4259     /* both are bits */
4260     if (AOP_TYPE(left) == AOP_CRY &&
4261         AOP_TYPE(right)== AOP_CRY) {
4262         genModbits(left,right,result);
4263         goto release ;
4264     }
4265
4266     /* if both are of size == 1 */
4267     if (AOP_SIZE(left) == 1 &&
4268         AOP_SIZE(right) == 1 ) {
4269         genModOneByte(left,right,result);
4270         goto release ;
4271     }
4272
4273     /* should have been converted to function call */
4274     assert(0);
4275
4276 release :
4277     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4278     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4279     pic16_freeAsmop(result,NULL,ic,TRUE); 
4280 }
4281
4282 /*-----------------------------------------------------------------*/
4283 /* genIfxJump :- will create a jump depending on the ifx           */
4284 /*-----------------------------------------------------------------*/
4285 /*
4286   note: May need to add parameter to indicate when a variable is in bit space.
4287 */
4288 static void genIfxJump (iCode *ic, char *jval)
4289 {
4290
4291     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4292     /* if true label then we jump if condition
4293     supplied is true */
4294     if ( IC_TRUE(ic) ) {
4295
4296         if(strcmp(jval,"a") == 0)
4297           emitSKPZ;
4298         else if (strcmp(jval,"c") == 0)
4299           emitSKPC;
4300         else {
4301           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4302           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
4303         }
4304
4305         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
4306         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
4307
4308     }
4309     else {
4310         /* false label is present */
4311         if(strcmp(jval,"a") == 0)
4312           emitSKPNZ;
4313         else if (strcmp(jval,"c") == 0)
4314           emitSKPNC;
4315         else {
4316           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
4317           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
4318         }
4319
4320         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
4321         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
4322
4323     }
4324
4325
4326     /* mark the icode as generated */
4327     ic->generated = 1;
4328 }
4329
4330 #if 0
4331 // not needed ATM
4332
4333 /*-----------------------------------------------------------------*/
4334 /* genSkip                                                         */
4335 /*-----------------------------------------------------------------*/
4336 static void genSkip(iCode *ifx,int status_bit)
4337 {
4338   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4339   if(!ifx)
4340     return;
4341
4342   if ( IC_TRUE(ifx) ) {
4343     switch(status_bit) {
4344     case 'z':
4345       emitSKPNZ;
4346       break;
4347
4348     case 'c':
4349       emitSKPNC;
4350       break;
4351
4352     case 'd':
4353       emitSKPDC;
4354       break;
4355
4356     }
4357
4358     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4359     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4360
4361   } else {
4362
4363     switch(status_bit) {
4364
4365     case 'z':
4366       emitSKPZ;
4367       break;
4368
4369     case 'c':
4370       emitSKPC;
4371       break;
4372
4373     case 'd':
4374       emitSKPDC;
4375       break;
4376     }
4377     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4378     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4379
4380   }
4381
4382 }
4383 #endif
4384
4385 /*-----------------------------------------------------------------*/
4386 /* genSkipc                                                        */
4387 /*-----------------------------------------------------------------*/
4388 static void genSkipc(resolvedIfx *rifx)
4389 {
4390   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4391   
4392   if(!rifx)
4393     return;
4394
4395   if(rifx->condition)
4396     emitSKPC;
4397   else
4398     emitSKPNC;
4399
4400   pic16_emitpcode(POC_GOTO, pic16_popGetLabel(rifx->lbl->key));
4401   rifx->generated = 1;
4402 }
4403
4404 /*-----------------------------------------------------------------*/
4405 /* genSkipz2                                                       */
4406 /*-----------------------------------------------------------------*/
4407 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
4408 {
4409   DEBUGpic16_emitcode ("; ***","%s  %d rifx= %p",__FUNCTION__,__LINE__, rifx);
4410   
4411   if(!rifx)
4412     return;
4413
4414   if( (rifx->condition ^ invert_condition) & 1)
4415     emitSKPZ;
4416   else
4417     emitSKPNZ;
4418
4419   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4420   rifx->generated = 1;
4421 }
4422
4423 #if 0
4424 /*-----------------------------------------------------------------*/
4425 /* genSkipz                                                        */
4426 /*-----------------------------------------------------------------*/
4427 static void genSkipz(iCode *ifx, int condition)
4428 {
4429   if(!ifx)
4430     return;
4431
4432   if(condition)
4433     emitSKPNZ;
4434   else
4435     emitSKPZ;
4436
4437   if ( IC_TRUE(ifx) )
4438     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
4439   else
4440     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
4441
4442   if ( IC_TRUE(ifx) )
4443     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
4444   else
4445     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
4446
4447 }
4448 #endif
4449
4450 /*-----------------------------------------------------------------*/
4451 /* genSkipCond                                                     */
4452 /*-----------------------------------------------------------------*/
4453 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
4454 {
4455   if(!rifx)
4456     return;
4457
4458   if(rifx->condition)
4459     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4460   else
4461     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
4462
4463
4464   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
4465   rifx->generated = 1;
4466 }
4467
4468 #if 0
4469 /*-----------------------------------------------------------------*/
4470 /* genChkZeroes :- greater or less than comparison                 */
4471 /*     For each byte in a literal that is zero, inclusive or the   */
4472 /*     the corresponding byte in the operand with W                */
4473 /*     returns true if any of the bytes are zero                   */
4474 /*-----------------------------------------------------------------*/
4475 static int genChkZeroes(operand *op, int lit,  int size)
4476 {
4477
4478   int i;
4479   int flag =1;
4480
4481   while(size--) {
4482     i = (lit >> (size*8)) & 0xff;
4483
4484     if(i==0) {
4485       if(flag) 
4486         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
4487       else
4488         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
4489       flag = 0;
4490     }
4491   }
4492
4493   return (flag==0);
4494 }
4495 #endif
4496
4497 /*-----------------------------------------------------------------*/
4498 /* genCmp :- greater or less than comparison                       */
4499 /*-----------------------------------------------------------------*/
4500 static void genCmp (operand *left,operand *right,
4501                     operand *result, iCode *ifx, int sign)
4502 {
4503   int size; //, offset = 0 ;
4504   unsigned long lit = 0L,i = 0;
4505   resolvedIfx rFalseIfx;
4506   //  resolvedIfx rTrueIfx;
4507   symbol *truelbl;
4508   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4509 /*
4510   if(ifx) {
4511     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
4512     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
4513   }
4514 */
4515
4516   resolveIfx(&rFalseIfx,ifx);
4517   truelbl  = newiTempLabel(NULL);
4518   size = max(AOP_SIZE(left),AOP_SIZE(right));
4519
4520   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4521
4522 #define _swapp
4523
4524   /* if literal is on the right then swap with left */
4525   if ((AOP_TYPE(right) == AOP_LIT)) {
4526     operand *tmp = right ;
4527     unsigned long mask = (0x100 << (8*(size-1))) - 1;
4528     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4529 #ifdef _swapp
4530
4531     lit = (lit - 1) & mask;
4532     right = left;
4533     left = tmp;
4534     rFalseIfx.condition ^= 1;
4535 #endif
4536
4537   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4538     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4539   }
4540
4541
4542   //if(IC_TRUE(ifx) == NULL)
4543   /* if left & right are bit variables */
4544   if (AOP_TYPE(left) == AOP_CRY &&
4545       AOP_TYPE(right) == AOP_CRY ) {
4546     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4547     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4548   } else {
4549     /* subtract right from left if at the
4550        end the carry flag is set then we know that
4551        left is greater than right */
4552
4553     symbol *lbl  = newiTempLabel(NULL);
4554
4555 #if 0
4556         fprintf(stderr, "%s:%s:%d truelbl: %d\tlbl: %d\n",
4557                 __FILE__, __FUNCTION__, __LINE__, truelbl->key+100+labelOffset, lbl->key+100+labelOffset);
4558 #endif
4559
4560 #ifndef _swapp
4561     if(AOP_TYPE(right) == AOP_LIT) {
4562
4563       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4564
4565       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4566
4567       /* special cases */
4568
4569       if(lit == 0) {
4570
4571         if(sign != 0) 
4572           genSkipCond(&rFalseIfx,left,size-1,7);
4573         else 
4574           /* no need to compare to 0...*/
4575           /* NOTE: this is a de-generate compare that most certainly 
4576            *       creates some dead code. */
4577           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4578
4579         if(ifx) ifx->generated = 1;
4580         return;
4581
4582       }
4583       size--;
4584
4585       if(size == 0) {
4586         //i = (lit >> (size*8)) & 0xff;
4587         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4588         
4589         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4590
4591         i = ((0-lit) & 0xff);
4592         if(sign) {
4593           if( i == 0x81) { 
4594             /* lit is 0x7f, all signed chars are less than
4595              * this except for 0x7f itself */
4596             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4597             genSkipz2(&rFalseIfx,0);
4598           } else {
4599             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4600             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4601             genSkipc(&rFalseIfx);
4602           }
4603
4604         } else {
4605           if(lit == 1) {
4606             genSkipz2(&rFalseIfx,1);
4607           } else {
4608             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4609             genSkipc(&rFalseIfx);
4610           }
4611         }
4612
4613         if(ifx) ifx->generated = 1;
4614         return;
4615       }
4616
4617       /* chars are out of the way. now do ints and longs */
4618
4619
4620       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4621         
4622       /* special cases */
4623
4624       if(sign) {
4625
4626         if(lit == 0) {
4627           genSkipCond(&rFalseIfx,left,size,7);
4628           if(ifx) ifx->generated = 1;
4629           return;
4630         }
4631
4632         if(lit <0x100) {
4633           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4634
4635           //rFalseIfx.condition ^= 1;
4636           //genSkipCond(&rFalseIfx,left,size,7);
4637           //rFalseIfx.condition ^= 1;
4638
4639           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4640           if(rFalseIfx.condition)
4641             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4642           else
4643             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4644
4645           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4646           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4647           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4648
4649           while(size > 1)
4650             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4651
4652           if(rFalseIfx.condition) {
4653             emitSKPZ;
4654             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4655
4656           } else {
4657             emitSKPNZ;
4658           }
4659
4660           genSkipc(&rFalseIfx);
4661           pic16_emitpLabel(truelbl->key);
4662           if(ifx) ifx->generated = 1;
4663           return;
4664
4665         }
4666
4667         if(size == 1) {
4668
4669           if( (lit & 0xff) == 0) {
4670             /* lower byte is zero */
4671             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4672             i = ((lit >> 8) & 0xff) ^0x80;
4673             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4674             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4675             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4676             genSkipc(&rFalseIfx);
4677
4678
4679             if(ifx) ifx->generated = 1;
4680             return;
4681
4682           }
4683         } else {
4684           /* Special cases for signed longs */
4685           if( (lit & 0xffffff) == 0) {
4686             /* lower byte is zero */
4687             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4688             i = ((lit >> 8*3) & 0xff) ^0x80;
4689             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4690             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4691             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4692             genSkipc(&rFalseIfx);
4693
4694
4695             if(ifx) ifx->generated = 1;
4696             return;
4697
4698           }
4699
4700         }
4701
4702
4703         if(lit & (0x80 << (size*8))) {
4704           /* lit is negative */
4705           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4706
4707           //genSkipCond(&rFalseIfx,left,size,7);
4708
4709           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4710
4711           if(rFalseIfx.condition)
4712             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4713           else
4714             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4715
4716
4717         } else {
4718           /* lit is positive */
4719           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4720           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4721           if(rFalseIfx.condition)
4722             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4723           else
4724             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4725
4726         }
4727
4728         /*
4729           This works, but is only good for ints.
4730           It also requires a "known zero" register.
4731           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4732           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4733           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4734           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4735           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4736           genSkipc(&rFalseIfx);
4737
4738           pic16_emitpLabel(truelbl->key);
4739           if(ifx) ifx->generated = 1;
4740           return;
4741         **/
4742           
4743         /* There are no more special cases, so perform a general compare */
4744   
4745         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4746         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4747
4748         while(size--) {
4749
4750           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4751           emitSKPNZ;
4752           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4753         }
4754         //rFalseIfx.condition ^= 1;
4755         genSkipc(&rFalseIfx);
4756
4757         pic16_emitpLabel(truelbl->key);
4758
4759         if(ifx) ifx->generated = 1;
4760         return;
4761
4762
4763       }
4764
4765
4766       /* sign is out of the way. So now do an unsigned compare */
4767       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4768
4769
4770       /* General case - compare to an unsigned literal on the right.*/
4771
4772       i = (lit >> (size*8)) & 0xff;
4773       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4774       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4775       while(size--) {
4776         i = (lit >> (size*8)) & 0xff;
4777
4778         if(i) {
4779           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4780           emitSKPNZ;
4781           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4782         } else {
4783           /* this byte of the lit is zero, 
4784            *if it's not the last then OR in the variable */
4785           if(size)
4786             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4787         }
4788       }
4789
4790
4791       pic16_emitpLabel(lbl->key);
4792 //      pic16_emitpLabel(truelbl->key);
4793       //if(emitFinalCheck)
4794       genSkipc(&rFalseIfx);
4795       if(sign)
4796         pic16_emitpLabel(truelbl->key);
4797
4798       if(ifx) ifx->generated = 1;
4799       return;
4800
4801
4802     }
4803 #endif  // _swapp
4804
4805     if(AOP_TYPE(left) == AOP_LIT) {
4806       //symbol *lbl = newiTempLabel(NULL);
4807
4808       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4809
4810
4811       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4812
4813       /* Special cases */
4814       if((lit == 0) && (sign == 0)){
4815
4816         size--;
4817         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4818         while(size) 
4819           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4820
4821         genSkipz2(&rFalseIfx,0);
4822         if(ifx) ifx->generated = 1;
4823         return;
4824       }
4825
4826       if(size==1) {
4827         /* Special cases */
4828         lit &= 0xff;
4829         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4830           /* degenerate compare can never be true */
4831           if(rFalseIfx.condition == 0)
4832             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4833
4834           if(ifx) ifx->generated = 1;
4835           return;
4836         }
4837
4838         if(sign) {
4839           /* signed comparisons to a literal byte */
4840
4841           int lp1 = (lit+1) & 0xff;
4842
4843           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4844           switch (lp1) {
4845           case 0:
4846             rFalseIfx.condition ^= 1;
4847             genSkipCond(&rFalseIfx,right,0,7);
4848             break;
4849           case 0x7f:
4850             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4851             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4852             genSkipz2(&rFalseIfx,1);
4853             break;
4854           default:
4855             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4856             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4857             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4858             rFalseIfx.condition ^= 1;
4859             genSkipc(&rFalseIfx);
4860             break;
4861           }
4862         } else {
4863           /* unsigned comparisons to a literal byte */
4864
4865           switch(lit & 0xff ) {
4866           case 0:
4867             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4868             genSkipz2(&rFalseIfx,0);
4869             break;
4870           case 0x7f:
4871             rFalseIfx.condition ^= 1;
4872             genSkipCond(&rFalseIfx,right,0,7);
4873             break;
4874
4875           default:
4876             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4877             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4878             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4879             rFalseIfx.condition ^= 1;
4880             if (AOP_TYPE(result) == AOP_CRY)
4881               genSkipc(&rFalseIfx);
4882             else {
4883               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4884               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4885             }         
4886             break;
4887           }
4888         }
4889
4890         if(ifx) ifx->generated = 1;
4891         //goto check_carry;
4892         return;
4893
4894       } else {
4895
4896         /* Size is greater than 1 */
4897
4898         if(sign) {
4899           int lp1 = lit+1;
4900
4901           size--;
4902
4903           if(lp1 == 0) {
4904             /* this means lit = 0xffffffff, or -1 */
4905
4906
4907             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4908             rFalseIfx.condition ^= 1;
4909             genSkipCond(&rFalseIfx,right,size,7);
4910             if(ifx) ifx->generated = 1;
4911             return;
4912           }
4913
4914           if(lit == 0) {
4915             int s = size;
4916
4917             if(rFalseIfx.condition) {
4918               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4919               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4920             }
4921
4922             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4923             while(size--)
4924               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4925
4926
4927             emitSKPZ;
4928             if(rFalseIfx.condition) {
4929               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4930               pic16_emitpLabel(truelbl->key);
4931             }else {
4932               rFalseIfx.condition ^= 1;
4933               genSkipCond(&rFalseIfx,right,s,7);
4934             }
4935
4936             if(ifx) ifx->generated = 1;
4937             return;
4938           }
4939
4940           if((size == 1) &&  (0 == (lp1&0xff))) {
4941             /* lower byte of signed word is zero */
4942             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4943             i = ((lp1 >> 8) & 0xff) ^0x80;
4944             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4945             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4946             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4947             rFalseIfx.condition ^= 1;
4948             genSkipc(&rFalseIfx);
4949
4950
4951             if(ifx) ifx->generated = 1;
4952             return;
4953           }
4954
4955           if(lit & (0x80 << (size*8))) {
4956             /* Lit is less than zero */
4957             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4958             //rFalseIfx.condition ^= 1;
4959             //genSkipCond(&rFalseIfx,left,size,7);
4960             //rFalseIfx.condition ^= 1;
4961             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4962             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4963
4964             if(rFalseIfx.condition)
4965               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4966             else
4967               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4968
4969
4970           } else {
4971             /* Lit is greater than or equal to zero */
4972             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4973             //rFalseIfx.condition ^= 1;
4974             //genSkipCond(&rFalseIfx,right,size,7);
4975             //rFalseIfx.condition ^= 1;
4976
4977             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4978             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4979
4980             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4981             if(rFalseIfx.condition)
4982               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4983             else
4984               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4985
4986           }
4987
4988
4989           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4990           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4991
4992           while(size--) {
4993
4994             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4995             emitSKPNZ;
4996             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4997           }
4998           rFalseIfx.condition ^= 1;
4999           //rFalseIfx.condition = 1;
5000           genSkipc(&rFalseIfx);
5001
5002           pic16_emitpLabel(truelbl->key);
5003
5004           if(ifx) ifx->generated = 1;
5005           return;
5006           // end of if (sign)
5007         } else {
5008
5009           /* compare word or long to an unsigned literal on the right.*/
5010
5011
5012           size--;
5013           if(lit < 0xff) {
5014             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
5015             switch (lit) {
5016             case 0:
5017               break; /* handled above */
5018 /*
5019             case 0xff:
5020               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5021               while(size--)
5022                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5023               genSkipz2(&rFalseIfx,0);
5024               break;
5025 */
5026             default:
5027               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5028               while(--size)
5029                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5030
5031               emitSKPZ;
5032               if(rFalseIfx.condition)
5033                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
5034               else
5035                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
5036
5037
5038               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
5039               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
5040
5041               rFalseIfx.condition ^= 1;
5042               genSkipc(&rFalseIfx);
5043             }
5044
5045             pic16_emitpLabel(truelbl->key);
5046
5047             if(ifx) ifx->generated = 1;
5048             return;
5049           }
5050
5051
5052           lit++;
5053           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
5054           i = (lit >> (size*8)) & 0xff;
5055
5056           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5057           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5058
5059           while(size--) {
5060             i = (lit >> (size*8)) & 0xff;
5061
5062             if(i) {
5063               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
5064               emitSKPNZ;
5065               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
5066             } else {
5067               /* this byte of the lit is zero, 
5068                * if it's not the last then OR in the variable */
5069               if(size)
5070                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
5071             }
5072           }
5073
5074
5075           pic16_emitpLabel(lbl->key);
5076
5077           rFalseIfx.condition ^= 1;
5078
5079           genSkipc(&rFalseIfx);
5080         }
5081
5082         if(sign)
5083           pic16_emitpLabel(truelbl->key);
5084         if(ifx) ifx->generated = 1;
5085         return;
5086       }
5087     }
5088     /* Compare two variables */
5089
5090     DEBUGpic16_emitcode(";sign","%d",sign);
5091
5092     size--;
5093     if(sign) {
5094       /* Sigh. thus sucks... */
5095       if(size) {
5096         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
5097         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5098         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
5099         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5100         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
5101         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
5102       } else {
5103         /* Signed char comparison */
5104         /* Special thanks to Nikolai Golovchenko for this snippet */
5105         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
5106         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
5107         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
5108         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
5109         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
5110         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
5111
5112         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5113         genSkipc(&rFalseIfx);
5114           
5115         if(ifx) ifx->generated = 1;
5116         return;
5117       }
5118
5119     } else {
5120
5121       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5122       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5123     }
5124
5125
5126     /* The rest of the bytes of a multi-byte compare */
5127     while (size) {
5128
5129       emitSKPZ;
5130       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
5131       size--;
5132
5133       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
5134       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
5135
5136
5137     }
5138
5139     pic16_emitpLabel(lbl->key);
5140
5141     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5142     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
5143         (AOP_TYPE(result) == AOP_REG)) {
5144       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
5145       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
5146     } else {
5147       genSkipc(&rFalseIfx);
5148     }         
5149     //genSkipc(&rFalseIfx);
5150     if(ifx) ifx->generated = 1;
5151
5152     return;
5153
5154   }
5155
5156   // check_carry:
5157   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5158     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5159     pic16_outBitC(result);
5160   } else {
5161     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5162     /* if the result is used in the next
5163        ifx conditional branch then generate
5164        code a little differently */
5165     if (ifx )
5166       genIfxJump (ifx,"c");
5167     else
5168       pic16_outBitC(result);
5169     /* leave the result in acc */
5170   }
5171
5172 }
5173
5174 /*-----------------------------------------------------------------*/
5175 /* genCmpGt :- greater than comparison                             */
5176 /*-----------------------------------------------------------------*/
5177 static void genCmpGt (iCode *ic, iCode *ifx)
5178 {
5179     operand *left, *right, *result;
5180     sym_link *letype , *retype;
5181     int sign ;
5182
5183     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5184     left = IC_LEFT(ic);
5185     right= IC_RIGHT(ic);
5186     result = IC_RESULT(ic);
5187
5188     letype = getSpec(operandType(left));
5189     retype =getSpec(operandType(right));
5190     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5191     /* assign the amsops */
5192     pic16_aopOp (left,ic,FALSE);
5193     pic16_aopOp (right,ic,FALSE);
5194     pic16_aopOp (result,ic,TRUE);
5195
5196     genCmp(right, left, result, ifx, sign);
5197
5198     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5199     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5200     pic16_freeAsmop(result,NULL,ic,TRUE); 
5201 }
5202
5203 /*-----------------------------------------------------------------*/
5204 /* genCmpLt - less than comparisons                                */
5205 /*-----------------------------------------------------------------*/
5206 static void genCmpLt (iCode *ic, iCode *ifx)
5207 {
5208     operand *left, *right, *result;
5209     sym_link *letype , *retype;
5210     int sign ;
5211
5212     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5213     left = IC_LEFT(ic);
5214     right= IC_RIGHT(ic);
5215     result = IC_RESULT(ic);
5216
5217     letype = getSpec(operandType(left));
5218     retype =getSpec(operandType(right));
5219     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
5220
5221     /* assign the amsops */
5222     pic16_aopOp (left,ic,FALSE);
5223     pic16_aopOp (right,ic,FALSE);
5224     pic16_aopOp (result,ic,TRUE);
5225
5226     genCmp(left, right, result, ifx, sign);
5227
5228     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5229     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5230     pic16_freeAsmop(result,NULL,ic,TRUE); 
5231 }
5232
5233 #if 0
5234 // not needed ATM
5235 // FIXME reenable literal optimisation when the pic16 port is stable
5236
5237 /*-----------------------------------------------------------------*/
5238 /* genc16bit2lit - compare a 16 bit value to a literal             */
5239 /*-----------------------------------------------------------------*/
5240 static void genc16bit2lit(operand *op, int lit, int offset)
5241 {
5242   int i;
5243
5244   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
5245   if( (lit&0xff) == 0) 
5246     i=1;
5247   else
5248     i=0;
5249
5250   switch( BYTEofLONG(lit,i)) { 
5251   case 0:
5252     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5253     break;
5254   case 1:
5255     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5256     break;
5257   case 0xff:
5258     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5259     break;
5260   default:
5261     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
5262     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5263   }
5264
5265   i ^= 1;
5266
5267   switch( BYTEofLONG(lit,i)) { 
5268   case 0:
5269     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
5270     break;
5271   case 1:
5272     emitSKPNZ;
5273     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
5274     break;
5275   case 0xff:
5276     emitSKPNZ;
5277     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
5278     break;
5279   default:
5280     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
5281     emitSKPNZ;
5282     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
5283
5284   }
5285
5286 }
5287 #endif
5288
5289 #if 0
5290 // not needed ATM
5291 /*-----------------------------------------------------------------*/
5292 /* gencjneshort - compare and jump if not equal                    */
5293 /*-----------------------------------------------------------------*/
5294 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
5295 {
5296   int size = max(AOP_SIZE(left),AOP_SIZE(right));
5297   int offset = 0;
5298   int res_offset = 0;  /* the result may be a different size then left or right */
5299   int res_size = AOP_SIZE(result);
5300   resolvedIfx rIfx;
5301   symbol *lbl, *lbl_done;
5302
5303   unsigned long lit = 0L;
5304   int preserve_result = 0; /* don't touch result before we are done, if left/right == result */
5305
5306   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5307   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5308   if(result)
5309     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
5310   resolveIfx(&rIfx,ifx);
5311   lbl =  newiTempLabel(NULL);
5312   lbl_done =  newiTempLabel(NULL);
5313
5314
5315   /* if the left side is a literal or 
5316      if the right is in a pointer register and left 
5317      is not */
5318   if ((AOP_TYPE(left) == AOP_LIT) || 
5319       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5320     operand *t = right;
5321     right = left;
5322     left = t;
5323   }
5324   if(AOP_TYPE(right) == AOP_LIT)
5325     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5326
5327   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5328     preserve_result = 1;
5329
5330   if(result && !preserve_result)
5331     {
5332       int i;
5333       for(i = 0; i < AOP_SIZE(result); i++)
5334         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5335     }
5336
5337
5338   /* if the right side is a literal then anything goes */
5339   if (AOP_TYPE(right) == AOP_LIT &&
5340       AOP_TYPE(left) != AOP_DIR ) {
5341     switch(size) {
5342     case 2:
5343       genc16bit2lit(left, lit, 0);
5344       emitSKPZ;
5345       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5346       break;
5347     default:
5348       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5349       while (size--) {
5350         if(lit & 0xff) {
5351           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5352           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5353         } else {
5354           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5355         }
5356
5357         emitSKPZ;
5358         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5359         offset++;
5360         if(res_offset < res_size-1)
5361           res_offset++;
5362         lit >>= 8;
5363       }
5364       break;
5365     }
5366   }
5367
5368   /* if the right side is in a register or in direct space or
5369      if the left is a pointer register & right is not */    
5370   else if (AOP_TYPE(right) == AOP_REG ||
5371            AOP_TYPE(right) == AOP_DIR || 
5372            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
5373            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
5374     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
5375     int lbl_key = lbl->key;
5376
5377     if(result) {
5378       // pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
5379       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5380     }else {
5381       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5382       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
5383               __FUNCTION__,__LINE__);
5384       return;
5385     }
5386    
5387 /*     switch(size) { */
5388 /*     case 2: */
5389 /*       genc16bit2lit(left, lit, 0); */
5390 /*       emitSKPNZ; */
5391 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
5392 /*       break; */
5393 /*     default: */
5394     while (size--) {
5395       int emit_skip=1;
5396       if((AOP_TYPE(left) == AOP_DIR) && 
5397          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
5398
5399         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5400         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5401
5402       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
5403             
5404         switch (lit & 0xff) {
5405         case 0:
5406           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5407           break;
5408         case 1:
5409           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5410           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5411           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
5412           emit_skip=0;
5413           break;
5414         case 0xff:
5415           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5416           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5417           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5418           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5419           emit_skip=0;
5420           break;
5421         default:
5422           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5423           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5424         }
5425         lit >>= 8;
5426
5427       } else {
5428         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
5429       }
5430       if(emit_skip) {
5431         if(AOP_TYPE(result) == AOP_CRY) {
5432           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5433           if(rIfx.condition)
5434             emitSKPNZ;
5435           else
5436             emitSKPZ;
5437           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5438         } else {
5439           /* fix me. probably need to check result size too */
5440           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
5441           if(rIfx.condition)
5442             emitSKPZ;
5443           else
5444             emitSKPNZ;
5445           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
5446           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
5447         }
5448         if(ifx)
5449           ifx->generated=1;
5450       }
5451       emit_skip++;
5452       offset++;
5453       if(res_offset < res_size-1)
5454         res_offset++;
5455     }
5456 /*       break; */
5457 /*     } */
5458   } else if(AOP_TYPE(right) == AOP_REG &&
5459             AOP_TYPE(left) != AOP_DIR){
5460
5461     while(size--) {
5462       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5463       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5464       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
5465       if(rIfx.condition)
5466         emitSKPNZ;
5467       else
5468         emitSKPZ;
5469       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5470       offset++;
5471       if(res_offset < res_size-1)
5472         res_offset++;
5473     }
5474       
5475   }else{
5476     /* right is a pointer reg need both a & b */
5477     while(size--) {
5478       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
5479       if(strcmp(l,"b"))
5480         pic16_emitcode("mov","b,%s",l);
5481       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5482       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
5483       offset++;
5484     }
5485   }
5486
5487   if(result && preserve_result)
5488     {
5489       int i;
5490       for(i = 0; i < AOP_SIZE(result); i++)
5491         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5492     }
5493
5494   pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0));
5495
5496   if(result && preserve_result)
5497     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_done->key));
5498
5499   if(!rIfx.condition)
5500     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5501
5502   pic16_emitpLabel(lbl->key);
5503
5504   if(result && preserve_result)
5505     {
5506       int i;
5507       for(i = 0; i < AOP_SIZE(result); i++)
5508         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5509
5510       pic16_emitpLabel(lbl_done->key);
5511    }
5512
5513   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5514
5515   if(ifx)
5516     ifx->generated = 1;
5517 }
5518 #endif
5519
5520 #if 0
5521 /*-----------------------------------------------------------------*/
5522 /* gencjne - compare and jump if not equal                         */
5523 /*-----------------------------------------------------------------*/
5524 static void gencjne(operand *left, operand *right, iCode *ifx)
5525 {
5526     symbol *tlbl  = newiTempLabel(NULL);
5527
5528     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5529     gencjneshort(left, right, lbl);
5530
5531     pic16_emitcode("mov","a,%s",one);
5532     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
5533     pic16_emitcode("","%05d_DS_:",lbl->key+100);
5534     pic16_emitcode("clr","a");
5535     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5536
5537     pic16_emitpLabel(lbl->key);
5538     pic16_emitpLabel(tlbl->key);
5539
5540 }
5541 #endif
5542
5543
5544 /*-----------------------------------------------------------------*/
5545 /* is_LitOp - check if operand has to be treated as literal        */
5546 /*-----------------------------------------------------------------*/
5547 static bool is_LitOp(operand *op)
5548 {
5549   return (AOP_TYPE(op) == AOP_LIT)
5550       || ( (AOP_TYPE(op) == AOP_PCODE)
5551           && ( (AOP(op)->aopu.pcop->type == PO_LITERAL)
5552               || (AOP(op)->aopu.pcop->type == PO_IMMEDIATE) ));  
5553 }
5554
5555
5556 /*-----------------------------------------------------------------*/
5557 /* genCmpEq - generates code for equal to                          */
5558 /*-----------------------------------------------------------------*/
5559 static void genCmpEq (iCode *ic, iCode *ifx)
5560 {
5561   operand *left, *right, *result;
5562   symbol *falselbl = newiTempLabel(NULL);
5563   symbol *donelbl = newiTempLabel(NULL);
5564
5565   int preserve_result = 0;
5566   int generate_result = 0;
5567   int i=0;
5568
5569   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5570   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5571   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5572  
5573   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5574   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5575
5576   if( (AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(left) == AOP_CRY) )
5577     {
5578       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
5579       fprintf(stderr, "%s  %d error - left/right CRY operands not supported\n",__FUNCTION__,__LINE__);
5580       goto release;
5581     }
5582
5583   if (is_LitOp(left) || (AOP_TYPE(right) == AOP_ACC))
5584     {
5585       operand *tmp = right ;
5586       right = left;
5587       left = tmp;
5588     }
5589
5590   if ( regsInCommon(left, result) || regsInCommon(right, result) )
5591     preserve_result = 1;
5592
5593   if(result && AOP_SIZE(result))
5594     generate_result = 1;
5595
5596   if(generate_result && !preserve_result)
5597     {
5598       for(i = 0; i < AOP_SIZE(result); i++)
5599         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5600     }
5601
5602   for(i=0; i < AOP_SIZE(left); i++)
5603     {
5604       if(AOP_TYPE(left) != AOP_ACC)
5605         {
5606           if(is_LitOp(left))
5607             pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left), i));
5608           else
5609             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), i));
5610         }
5611       if(is_LitOp(right))
5612         pic16_emitpcode(POC_XORLW, pic16_popGet(AOP(right), i)); 
5613       else
5614         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right), i)); 
5615
5616       pic16_emitpcode(POC_BNZ,pic16_popGetLabel(falselbl->key));
5617     }
5618
5619   // result == true
5620
5621   if(generate_result && preserve_result)
5622     {
5623       for(i = 0; i < AOP_SIZE(result); i++)
5624         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5625     }
5626
5627   if(generate_result)
5628     pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result), 0)); // result = true
5629
5630   if(generate_result && preserve_result)
5631     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5632
5633   if(ifx && IC_TRUE(ifx))
5634     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5635
5636   if(ifx && IC_FALSE(ifx))
5637     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(donelbl->key));
5638
5639   pic16_emitpLabel(falselbl->key);
5640
5641   // result == false
5642
5643   if(ifx && IC_FALSE(ifx))
5644     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5645
5646   if(generate_result && preserve_result)
5647     {
5648       for(i = 0; i < AOP_SIZE(result); i++)
5649         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),i));
5650     }
5651
5652   pic16_emitpLabel(donelbl->key);
5653
5654   if(ifx)
5655     ifx->generated = 1;
5656
5657 release:
5658   pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5659   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5660   pic16_freeAsmop(result,NULL,ic,TRUE);
5661
5662 }
5663
5664
5665 #if 0
5666 // old version kept for reference
5667
5668 /*-----------------------------------------------------------------*/
5669 /* genCmpEq - generates code for equal to                          */
5670 /*-----------------------------------------------------------------*/
5671 static void genCmpEq (iCode *ic, iCode *ifx)
5672 {
5673     operand *left, *right, *result;
5674     unsigned long lit = 0L;
5675     int size,offset=0;
5676     symbol *falselbl  = newiTempLabel(NULL);
5677
5678
5679     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5680
5681     if(ifx)
5682       DEBUGpic16_emitcode ("; ifx is non-null","");
5683     else
5684       DEBUGpic16_emitcode ("; ifx is null","");
5685
5686     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5687     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5688     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5689
5690     size = max(AOP_SIZE(left),AOP_SIZE(right));
5691
5692     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5693
5694     /* if literal, literal on the right or 
5695     if the right is in a pointer register and left 
5696     is not */
5697     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
5698         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
5699       operand *tmp = right ;
5700       right = left;
5701       left = tmp;
5702     }
5703
5704
5705     if(ifx && !AOP_SIZE(result)){
5706         symbol *tlbl;
5707         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5708         /* if they are both bit variables */
5709         if (AOP_TYPE(left) == AOP_CRY &&
5710             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5711                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5712             if(AOP_TYPE(right) == AOP_LIT){
5713                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5714                 if(lit == 0L){
5715                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5716                     pic16_emitcode("cpl","c");
5717                 } else if(lit == 1L) {
5718                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5719                 } else {
5720                     pic16_emitcode("clr","c");
5721                 }
5722                 /* AOP_TYPE(right) == AOP_CRY */
5723             } else {
5724                 symbol *lbl = newiTempLabel(NULL);
5725                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5726                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5727                 pic16_emitcode("cpl","c");
5728                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5729             }
5730             /* if true label then we jump if condition
5731             supplied is true */
5732             tlbl = newiTempLabel(NULL);
5733             if ( IC_TRUE(ifx) ) {
5734                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5735                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5736             } else {
5737                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5738                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5739             }
5740             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5741
5742                 {
5743                 /* left and right are both bit variables, result is carry */
5744                         resolvedIfx rIfx;
5745               
5746                         resolveIfx(&rIfx,ifx);
5747
5748                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5749                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5750                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5751                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5752                         genSkipz2(&rIfx,0);
5753                 }
5754         } else {
5755
5756                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5757
5758                         /* They're not both bit variables. Is the right a literal? */
5759                         if(AOP_TYPE(right) == AOP_LIT) {
5760                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5761             
5762                         switch(size) {
5763
5764                                 case 1:
5765                                         switch(lit & 0xff) {
5766                                                 case 1:
5767                                                                 if ( IC_TRUE(ifx) ) {
5768                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5769                                                                         emitSKPNZ;
5770                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5771                                                                 } else {
5772                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5773                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5774                                                                 }
5775                                                                 break;
5776                                                 case 0xff:
5777                                                                 if ( IC_TRUE(ifx) ) {
5778                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5779                                                                         emitSKPNZ;
5780                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5781                                                                 } else {
5782                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5783                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5784                                                                 }
5785                                                                 break;
5786                                                 default:
5787                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5788                                                                 if(lit)
5789                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5790                                                                 genSkip(ifx,'z');
5791                                         } // switch lit
5792
5793
5794                                         /* end of size == 1 */
5795                                         break;
5796               
5797                                 case 2:
5798                                         genc16bit2lit(left,lit,offset);
5799                                         genSkip(ifx,'z');
5800                                         break;
5801                                         /* end of size == 2 */
5802
5803                                 default:
5804                                         /* size is 4 */
5805                                         if(lit==0) {
5806                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5807                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5808                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5809                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5810                                                 genSkip(ifx,'z');
5811                                         } else {
5812                                                 /* search for patterns that can be optimized */
5813
5814                                                 genc16bit2lit(left,lit,0);
5815                                                 lit >>= 16;
5816                                                 if(lit) {
5817                                                                 if(IC_TRUE(ifx))
5818                                                                 emitSKPZ; // if hi word unequal
5819                                                                 else
5820                                                                 emitSKPNZ; // if hi word equal
5821                                                                 // fail early
5822                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5823                                                         genc16bit2lit(left,lit,2);
5824                                                         genSkip(ifx,'z');
5825                                                 } else {
5826                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5827                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5828                                                         genSkip(ifx,'z');
5829                                                 }
5830                                         }
5831                                                 pic16_emitpLabel(falselbl->key);
5832                                                 break;
5833
5834                         } // switch size
5835           
5836                         ifx->generated = 1;
5837                         goto release ;
5838             
5839
5840           } else if(AOP_TYPE(right) == AOP_CRY ) {
5841             /* we know the left is not a bit, but that the right is */
5842             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5843             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5844                       pic16_popGet(AOP(right),offset));
5845             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5846
5847             /* if the two are equal, then W will be 0 and the Z bit is set
5848              * we could test Z now, or go ahead and check the high order bytes if
5849              * the variable we're comparing is larger than a byte. */
5850
5851             while(--size)
5852               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5853
5854             if ( IC_TRUE(ifx) ) {
5855               emitSKPNZ;
5856               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5857               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5858             } else {
5859               emitSKPZ;
5860               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5861               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5862             }
5863
5864           } else {
5865             /* They're both variables that are larger than bits */
5866             int s = size;
5867
5868             tlbl = newiTempLabel(NULL);
5869
5870             while(size--) {
5871               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5872               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5873
5874               if ( IC_TRUE(ifx) ) {
5875                 if(size) {
5876                   emitSKPZ;
5877                 
5878                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5879
5880                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5881                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5882                 } else {
5883                   emitSKPNZ;
5884
5885                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5886
5887
5888                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5889                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5890                 }
5891               } else {
5892                 emitSKPZ;
5893
5894                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5895
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               offset++;
5900             }
5901             if(s>1 && IC_TRUE(ifx)) {
5902               pic16_emitpLabel(tlbl->key);
5903               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5904             }
5905           }
5906         }
5907         /* mark the icode as generated */
5908         ifx->generated = 1;
5909         goto release ;
5910     }
5911
5912     /* if they are both bit variables */
5913     if (AOP_TYPE(left) == AOP_CRY &&
5914         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5915         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5916         if(AOP_TYPE(right) == AOP_LIT){
5917             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5918             if(lit == 0L){
5919                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5920                 pic16_emitcode("cpl","c");
5921             } else if(lit == 1L) {
5922                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5923             } else {
5924                 pic16_emitcode("clr","c");
5925             }
5926             /* AOP_TYPE(right) == AOP_CRY */
5927         } else {
5928             symbol *lbl = newiTempLabel(NULL);
5929             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5930             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5931             pic16_emitcode("cpl","c");
5932             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5933         }
5934         /* c = 1 if egal */
5935         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5936             pic16_outBitC(result);
5937             goto release ;
5938         }
5939         if (ifx) {
5940             genIfxJump (ifx,"c");
5941             goto release ;
5942         }
5943         /* if the result is used in an arithmetic operation
5944         then put the result in place */
5945         pic16_outBitC(result);
5946     } else {
5947       
5948       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5949       gencjne(left,right,result,ifx);
5950 /*
5951       if(ifx) 
5952         gencjne(left,right,newiTempLabel(NULL));
5953       else {
5954         if(IC_TRUE(ifx)->key)
5955           gencjne(left,right,IC_TRUE(ifx)->key);
5956         else
5957           gencjne(left,right,IC_FALSE(ifx)->key);
5958         ifx->generated = 1;
5959         goto release ;
5960       }
5961       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5962         pic16_aopPut(AOP(result),"a",0);
5963         goto release ;
5964       }
5965
5966       if (ifx) {
5967         genIfxJump (ifx,"a");
5968         goto release ;
5969       }
5970 */
5971       /* if the result is used in an arithmetic operation
5972          then put the result in place */
5973 /*
5974       if (AOP_TYPE(result) != AOP_CRY) 
5975         pic16_outAcc(result);
5976 */
5977       /* leave the result in acc */
5978     }
5979
5980 release:
5981     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5982     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5983     pic16_freeAsmop(result,NULL,ic,TRUE);
5984 }
5985 #endif
5986
5987 /*-----------------------------------------------------------------*/
5988 /* ifxForOp - returns the icode containing the ifx for operand     */
5989 /*-----------------------------------------------------------------*/
5990 static iCode *ifxForOp ( operand *op, iCode *ic )
5991 {
5992     /* if true symbol then needs to be assigned */
5993     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5994     if (IS_TRUE_SYMOP(op))
5995         return NULL ;
5996
5997     /* if this has register type condition and
5998     the next instruction is ifx with the same operand
5999     and live to of the operand is upto the ifx only then */
6000     if (ic->next &&
6001         ic->next->op == IFX &&
6002         IC_COND(ic->next)->key == op->key &&
6003         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6004         return ic->next;
6005
6006     if (ic->next &&
6007         ic->next->op == IFX &&
6008         IC_COND(ic->next)->key == op->key) {
6009       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6010       return ic->next;
6011     }
6012
6013     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
6014     if (ic->next &&
6015         ic->next->op == IFX)
6016       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
6017
6018     if (ic->next &&
6019         ic->next->op == IFX &&
6020         IC_COND(ic->next)->key == op->key) {
6021       DEBUGpic16_emitcode ("; "," key is okay");
6022       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
6023                            OP_SYMBOL(op)->liveTo,
6024                            ic->next->seq);
6025     }
6026
6027 #if 0
6028     /* the code below is completely untested
6029      * it just allows ulong2fs.c compile -- VR */
6030          
6031     ic = ic->next;
6032     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code\n",
6033                                         __FILE__, __FUNCTION__, __LINE__);
6034         
6035     /* if this has register type condition and
6036     the next instruction is ifx with the same operand
6037     and live to of the operand is upto the ifx only then */
6038     if (ic->next &&
6039         ic->next->op == IFX &&
6040         IC_COND(ic->next)->key == op->key &&
6041         OP_SYMBOL(op)->liveTo <= ic->next->seq )
6042         return ic->next;
6043
6044     if (ic->next &&
6045         ic->next->op == IFX &&
6046         IC_COND(ic->next)->key == op->key) {
6047       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
6048       return ic->next;
6049     }
6050
6051     fprintf(stderr, "WARNING (%s:%s:%d) untested hack might produce wrong code (returning NULL)\n",
6052                                         __FILE__, __FUNCTION__, __LINE__);
6053
6054 //  return ic->next->next;              /* this just might work */ /* FIXME FIXME */
6055 #endif
6056     return NULL;
6057 }
6058 /*-----------------------------------------------------------------*/
6059 /* genAndOp - for && operation                                     */
6060 /*-----------------------------------------------------------------*/
6061 static void genAndOp (iCode *ic)
6062 {
6063     operand *left,*right, *result;
6064 /*     symbol *tlbl; */
6065
6066     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6067     /* note here that && operations that are in an
6068     if statement are taken away by backPatchLabels
6069     only those used in arthmetic operations remain */
6070     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6071     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6072     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6073
6074     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6075
6076     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
6077     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
6078     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
6079
6080     /* if both are bit variables */
6081 /*     if (AOP_TYPE(left) == AOP_CRY && */
6082 /*         AOP_TYPE(right) == AOP_CRY ) { */
6083 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
6084 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
6085 /*         pic16_outBitC(result); */
6086 /*     } else { */
6087 /*         tlbl = newiTempLabel(NULL); */
6088 /*         pic16_toBoolean(left);     */
6089 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
6090 /*         pic16_toBoolean(right); */
6091 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
6092 /*         pic16_outBitAcc(result); */
6093 /*     } */
6094
6095     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6096     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6097     pic16_freeAsmop(result,NULL,ic,TRUE);
6098 }
6099
6100
6101 /*-----------------------------------------------------------------*/
6102 /* genOrOp - for || operation                                      */
6103 /*-----------------------------------------------------------------*/
6104 /*
6105   tsd pic port -
6106   modified this code, but it doesn't appear to ever get called
6107 */
6108
6109 static void genOrOp (iCode *ic)
6110 {
6111     operand *left,*right, *result;
6112     symbol *tlbl;
6113
6114     /* note here that || operations that are in an
6115     if statement are taken away by backPatchLabels
6116     only those used in arthmetic operations remain */
6117     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6118     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
6119     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
6120     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
6121
6122     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6123
6124     /* if both are bit variables */
6125     if (AOP_TYPE(left) == AOP_CRY &&
6126         AOP_TYPE(right) == AOP_CRY ) {
6127       pic16_emitcode("clrc","");
6128       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6129                AOP(left)->aopu.aop_dir,
6130                AOP(left)->aopu.aop_dir);
6131       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6132                AOP(right)->aopu.aop_dir,
6133                AOP(right)->aopu.aop_dir);
6134       pic16_emitcode("setc","");
6135
6136     } else {
6137         tlbl = newiTempLabel(NULL);
6138         pic16_toBoolean(left);
6139         emitSKPZ;
6140         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
6141         pic16_toBoolean(right);
6142         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
6143
6144         pic16_outBitAcc(result);
6145     }
6146
6147     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6148     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6149     pic16_freeAsmop(result,NULL,ic,TRUE);            
6150 }
6151
6152 /*-----------------------------------------------------------------*/
6153 /* isLiteralBit - test if lit == 2^n                               */
6154 /*-----------------------------------------------------------------*/
6155 static int isLiteralBit(unsigned long lit)
6156 {
6157     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
6158     0x100L,0x200L,0x400L,0x800L,
6159     0x1000L,0x2000L,0x4000L,0x8000L,
6160     0x10000L,0x20000L,0x40000L,0x80000L,
6161     0x100000L,0x200000L,0x400000L,0x800000L,
6162     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
6163     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
6164     int idx;
6165     
6166     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6167     for(idx = 0; idx < 32; idx++)
6168         if(lit == pw[idx])
6169             return idx+1;
6170     return 0;
6171 }
6172
6173 /*-----------------------------------------------------------------*/
6174 /* continueIfTrue -                                                */
6175 /*-----------------------------------------------------------------*/
6176 static void continueIfTrue (iCode *ic)
6177 {
6178     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6179     if(IC_TRUE(ic))
6180         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6181     ic->generated = 1;
6182 }
6183
6184 /*-----------------------------------------------------------------*/
6185 /* jmpIfTrue -                                                     */
6186 /*-----------------------------------------------------------------*/
6187 static void jumpIfTrue (iCode *ic)
6188 {
6189     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6190     if(!IC_TRUE(ic))
6191         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6192     ic->generated = 1;
6193 }
6194
6195 /*-----------------------------------------------------------------*/
6196 /* jmpTrueOrFalse -                                                */
6197 /*-----------------------------------------------------------------*/
6198 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
6199 {
6200     // ugly but optimized by peephole
6201     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6202     if(IC_TRUE(ic)){
6203         symbol *nlbl = newiTempLabel(NULL);
6204         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
6205         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6206         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
6207         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
6208     }
6209     else{
6210         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
6211         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6212     }
6213     ic->generated = 1;
6214 }
6215
6216 /*-----------------------------------------------------------------*/
6217 /* genAnd  - code for and                                          */
6218 /*-----------------------------------------------------------------*/
6219 static void genAnd (iCode *ic, iCode *ifx)
6220 {
6221   operand *left, *right, *result;
6222   int size, offset=0;  
6223   unsigned long lit = 0L;
6224   int bytelit = 0;
6225   resolvedIfx rIfx;
6226
6227
6228   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6229   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6230   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6231   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6232
6233   resolveIfx(&rIfx,ifx);
6234
6235   /* if left is a literal & right is not then exchange them */
6236   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6237       AOP_NEEDSACC(left)) {
6238     operand *tmp = right ;
6239     right = left;
6240     left = tmp;
6241   }
6242
6243   /* if result = right then exchange them */
6244   if(pic16_sameRegs(AOP(result),AOP(right))){
6245     operand *tmp = right ;
6246     right = left;
6247     left = tmp;
6248   }
6249
6250   /* if right is bit then exchange them */
6251   if (AOP_TYPE(right) == AOP_CRY &&
6252       AOP_TYPE(left) != AOP_CRY){
6253     operand *tmp = right ;
6254     right = left;
6255     left = tmp;
6256   }
6257   if(AOP_TYPE(right) == AOP_LIT)
6258     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6259
6260   size = AOP_SIZE(result);
6261
6262   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6263
6264   // if(bit & yy)
6265   // result = bit & yy;
6266   if (AOP_TYPE(left) == AOP_CRY){
6267     // c = bit & literal;
6268     if(AOP_TYPE(right) == AOP_LIT){
6269       if(lit & 1) {
6270         if(size && pic16_sameRegs(AOP(result),AOP(left)))
6271           // no change
6272           goto release;
6273         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6274       } else {
6275         // bit(result) = 0;
6276         if(size && (AOP_TYPE(result) == AOP_CRY)){
6277           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
6278           goto release;
6279         }
6280         if((AOP_TYPE(result) == AOP_CRY) && ifx){
6281           jumpIfTrue(ifx);
6282           goto release;
6283         }
6284         pic16_emitcode("clr","c");
6285       }
6286     } else {
6287       if (AOP_TYPE(right) == AOP_CRY){
6288         // c = bit & bit;
6289         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6290         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6291       } else {
6292         // c = bit & val;
6293         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
6294         // c = lsb
6295         pic16_emitcode("rrc","a");
6296         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
6297       }
6298     }
6299     // bit = c
6300     // val = c
6301     if(size)
6302       pic16_outBitC(result);
6303     // if(bit & ...)
6304     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6305       genIfxJump(ifx, "c");           
6306     goto release ;
6307   }
6308
6309   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
6310   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
6311   if((AOP_TYPE(right) == AOP_LIT) &&
6312      (AOP_TYPE(result) == AOP_CRY) &&
6313      (AOP_TYPE(left) != AOP_CRY)){
6314     int posbit = isLiteralBit(lit);
6315     /* left &  2^n */
6316     if(posbit){
6317       posbit--;
6318       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
6319       // bit = left & 2^n
6320       if(size)
6321         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
6322       // if(left &  2^n)
6323       else{
6324         if(ifx){
6325 /*
6326           if(IC_TRUE(ifx)) {
6327             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6328             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
6329           } else {
6330             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6331             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
6332           }
6333 */
6334           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
6335                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
6336           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
6337           
6338           ifx->generated = 1;
6339         }
6340         goto release;
6341       }
6342     } else {
6343       symbol *tlbl = newiTempLabel(NULL);
6344       int sizel = AOP_SIZE(left);
6345       if(size)
6346         pic16_emitcode("setb","c");
6347       while(sizel--){
6348         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
6349           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6350           // byte ==  2^n ?
6351           if((posbit = isLiteralBit(bytelit)) != 0)
6352             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
6353           else{
6354             if(bytelit != 0x0FFL)
6355               pic16_emitcode("anl","a,%s",
6356                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
6357             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6358           }
6359         }
6360         offset++;
6361       }
6362       // bit = left & literal
6363       if(size){
6364         pic16_emitcode("clr","c");
6365         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6366       }
6367       // if(left & literal)
6368       else{
6369         if(ifx)
6370           jmpTrueOrFalse(ifx, tlbl);
6371         goto release ;
6372       }
6373     }
6374     pic16_outBitC(result);
6375     goto release ;
6376   }
6377
6378   /* if left is same as result */
6379   if(pic16_sameRegs(AOP(result),AOP(left))){
6380     int know_W = -1;
6381     for(;size--; offset++,lit>>=8) {
6382       if(AOP_TYPE(right) == AOP_LIT){
6383         switch(lit & 0xff) {
6384         case 0x00:
6385           /*  and'ing with 0 has clears the result */
6386 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6387           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6388           break;
6389         case 0xff:
6390           /* and'ing with 0xff is a nop when the result and left are the same */
6391           break;
6392
6393         default:
6394           {
6395             int p = my_powof2( (~lit) & 0xff );
6396             if(p>=0) {
6397               /* only one bit is set in the literal, so use a bcf instruction */
6398 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
6399               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6400
6401             } else {
6402               pic16_emitcode("movlw","0x%x", (lit & 0xff));
6403               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6404               if(know_W != (lit&0xff))
6405                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6406               know_W = lit &0xff;
6407               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6408             }
6409           }    
6410         }
6411       } else {
6412         if (AOP_TYPE(left) == AOP_ACC) {
6413           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6414         } else {                    
6415           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6416           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
6417
6418         }
6419       }
6420     }
6421
6422   } else {
6423     // left & result in different registers
6424     if(AOP_TYPE(result) == AOP_CRY){
6425       // result = bit
6426       // if(size), result in bit
6427       // if(!size && ifx), conditional oper: if(left & right)
6428       symbol *tlbl = newiTempLabel(NULL);
6429       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
6430       if(size)
6431         pic16_emitcode("setb","c");
6432       while(sizer--){
6433         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6434         pic16_emitcode("anl","a,%s",
6435                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6436         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6437         offset++;
6438       }
6439       if(size){
6440         CLRC;
6441         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6442         pic16_outBitC(result);
6443       } else if(ifx)
6444         jmpTrueOrFalse(ifx, tlbl);
6445     } else {
6446       for(;(size--);offset++) {
6447         // normal case
6448         // result = left & right
6449         if(AOP_TYPE(right) == AOP_LIT){
6450           int t = (lit >> (offset*8)) & 0x0FFL;
6451           switch(t) { 
6452           case 0x00:
6453             pic16_emitcode("clrf","%s",
6454                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6455             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
6456             break;
6457           case 0xff:
6458             pic16_emitcode("movf","%s,w",
6459                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6460             pic16_emitcode("movwf","%s",
6461                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6462             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6463             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6464             break;
6465           default:
6466             pic16_emitcode("movlw","0x%x",t);
6467             pic16_emitcode("andwf","%s,w",
6468                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6469             pic16_emitcode("movwf","%s",
6470                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6471               
6472             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6473             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6474             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6475           }
6476           continue;
6477         }
6478
6479         if (AOP_TYPE(left) == AOP_ACC) {
6480           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6481           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
6482         } else {
6483           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6484           pic16_emitcode("andwf","%s,w",
6485                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6486           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6487           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
6488         }
6489         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6490         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6491       }
6492     }
6493   }
6494
6495   release :
6496     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6497   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6498   pic16_freeAsmop(result,NULL,ic,TRUE);     
6499 }
6500
6501 /*-----------------------------------------------------------------*/
6502 /* genOr  - code for or                                            */
6503 /*-----------------------------------------------------------------*/
6504 static void genOr (iCode *ic, iCode *ifx)
6505 {
6506     operand *left, *right, *result;
6507     int size, offset=0;
6508     unsigned long lit = 0L;
6509
6510     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6511
6512     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6513     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6514     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6515
6516     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6517
6518     /* if left is a literal & right is not then exchange them */
6519     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6520         AOP_NEEDSACC(left)) {
6521         operand *tmp = right ;
6522         right = left;
6523         left = tmp;
6524     }
6525
6526     /* if result = right then exchange them */
6527     if(pic16_sameRegs(AOP(result),AOP(right))){
6528         operand *tmp = right ;
6529         right = left;
6530         left = tmp;
6531     }
6532
6533     /* if right is bit then exchange them */
6534     if (AOP_TYPE(right) == AOP_CRY &&
6535         AOP_TYPE(left) != AOP_CRY){
6536         operand *tmp = right ;
6537         right = left;
6538         left = tmp;
6539     }
6540
6541     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
6542
6543     if(AOP_TYPE(right) == AOP_LIT)
6544         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6545
6546     size = AOP_SIZE(result);
6547
6548     // if(bit | yy)
6549     // xx = bit | yy;
6550     if (AOP_TYPE(left) == AOP_CRY){
6551         if(AOP_TYPE(right) == AOP_LIT){
6552             // c = bit & literal;
6553             if(lit){
6554                 // lit != 0 => result = 1
6555                 if(AOP_TYPE(result) == AOP_CRY){
6556                   if(size)
6557                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
6558                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6559                   //     AOP(result)->aopu.aop_dir,
6560                   //     AOP(result)->aopu.aop_dir);
6561                     else if(ifx)
6562                         continueIfTrue(ifx);
6563                     goto release;
6564                 }
6565             } else {
6566                 // lit == 0 => result = left
6567                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
6568                     goto release;
6569                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
6570             }
6571         } else {
6572             if (AOP_TYPE(right) == AOP_CRY){
6573               if(pic16_sameRegs(AOP(result),AOP(left))){
6574                 // c = bit | bit;
6575                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6576                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
6577                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6578
6579                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6580                          AOP(result)->aopu.aop_dir,
6581                          AOP(result)->aopu.aop_dir);
6582                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6583                          AOP(right)->aopu.aop_dir,
6584                          AOP(right)->aopu.aop_dir);
6585                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6586                          AOP(result)->aopu.aop_dir,
6587                          AOP(result)->aopu.aop_dir);
6588               } else {
6589                 if( AOP_TYPE(result) == AOP_ACC) {
6590                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
6591                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6592                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6593                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
6594
6595                 } else {
6596
6597                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6598                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
6599                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6600                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6601
6602                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
6603                                  AOP(result)->aopu.aop_dir,
6604                                  AOP(result)->aopu.aop_dir);
6605                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
6606                                  AOP(right)->aopu.aop_dir,
6607                                  AOP(right)->aopu.aop_dir);
6608                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
6609                                  AOP(left)->aopu.aop_dir,
6610                                  AOP(left)->aopu.aop_dir);
6611                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
6612                                  AOP(result)->aopu.aop_dir,
6613                                  AOP(result)->aopu.aop_dir);
6614                 }
6615               }
6616             } else {
6617                 // c = bit | val;
6618                 symbol *tlbl = newiTempLabel(NULL);
6619                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6620
6621
6622                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
6623                 if( AOP_TYPE(right) == AOP_ACC) {
6624                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
6625                   emitSKPNZ;
6626                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
6627                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
6628                 }
6629
6630
6631
6632                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
6633                     pic16_emitcode(";XXX setb","c");
6634                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
6635                          AOP(left)->aopu.aop_dir,tlbl->key+100);
6636                 pic16_toBoolean(right);
6637                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6638                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
6639                     jmpTrueOrFalse(ifx, tlbl);
6640                     goto release;
6641                 } else {
6642                     CLRC;
6643                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6644                 }
6645             }
6646         }
6647         // bit = c
6648         // val = c
6649         if(size)
6650             pic16_outBitC(result);
6651         // if(bit | ...)
6652         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6653             genIfxJump(ifx, "c");           
6654         goto release ;
6655     }
6656
6657     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
6658     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
6659     if((AOP_TYPE(right) == AOP_LIT) &&
6660        (AOP_TYPE(result) == AOP_CRY) &&
6661        (AOP_TYPE(left) != AOP_CRY)){
6662         if(lit){
6663           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6664             // result = 1
6665             if(size)
6666                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
6667             else 
6668                 continueIfTrue(ifx);
6669             goto release;
6670         } else {
6671           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6672             // lit = 0, result = boolean(left)
6673             if(size)
6674                 pic16_emitcode(";XXX setb","c");
6675             pic16_toBoolean(right);
6676             if(size){
6677                 symbol *tlbl = newiTempLabel(NULL);
6678                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6679                 CLRC;
6680                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6681             } else {
6682                 genIfxJump (ifx,"a");
6683                 goto release;
6684             }
6685         }
6686         pic16_outBitC(result);
6687         goto release ;
6688     }
6689
6690     /* if left is same as result */
6691     if(pic16_sameRegs(AOP(result),AOP(left))){
6692       int know_W = -1;
6693       for(;size--; offset++,lit>>=8) {
6694         if(AOP_TYPE(right) == AOP_LIT){
6695           if((lit & 0xff) == 0)
6696             /*  or'ing with 0 has no effect */
6697             continue;
6698           else {
6699             int p = my_powof2(lit & 0xff);
6700             if(p>=0) {
6701               /* only one bit is set in the literal, so use a bsf instruction */
6702               pic16_emitpcode(POC_BSF,
6703                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
6704             } else {
6705               if(know_W != (lit & 0xff))
6706                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
6707               know_W = lit & 0xff;
6708               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
6709             }
6710                     
6711           }
6712         } else {
6713           if (AOP_TYPE(left) == AOP_ACC) {
6714             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
6715             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6716           } else {                  
6717             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6718             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
6719
6720             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6721             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6722
6723           }
6724         }
6725       }
6726     } else {
6727         // left & result in different registers
6728         if(AOP_TYPE(result) == AOP_CRY){
6729             // result = bit
6730             // if(size), result in bit
6731             // if(!size && ifx), conditional oper: if(left | right)
6732             symbol *tlbl = newiTempLabel(NULL);
6733             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6734             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
6735
6736
6737             if(size)
6738                 pic16_emitcode(";XXX setb","c");
6739             while(sizer--){
6740                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6741                 pic16_emitcode(";XXX orl","a,%s",
6742                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6743                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6744                 offset++;
6745             }
6746             if(size){
6747                 CLRC;
6748                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6749                 pic16_outBitC(result);
6750             } else if(ifx)
6751                 jmpTrueOrFalse(ifx, tlbl);
6752         } else for(;(size--);offset++){
6753           // normal case
6754           // result = left & right
6755           if(AOP_TYPE(right) == AOP_LIT){
6756             int t = (lit >> (offset*8)) & 0x0FFL;
6757             switch(t) { 
6758             case 0x00:
6759               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6760               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6761
6762               pic16_emitcode("movf","%s,w",
6763                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6764               pic16_emitcode("movwf","%s",
6765                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6766               break;
6767             default:
6768               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6769               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6770               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6771
6772               pic16_emitcode("movlw","0x%x",t);
6773               pic16_emitcode("iorwf","%s,w",
6774                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6775               pic16_emitcode("movwf","%s",
6776                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6777               
6778             }
6779             continue;
6780           }
6781
6782           // faster than result <- left, anl result,right
6783           // and better if result is SFR
6784           if (AOP_TYPE(left) == AOP_ACC) {
6785             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6786             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6787           } else {
6788             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6789             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6790
6791             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6792             pic16_emitcode("iorwf","%s,w",
6793                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6794           }
6795           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6796           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6797         }
6798     }
6799
6800 release :
6801     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6802     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6803     pic16_freeAsmop(result,NULL,ic,TRUE);     
6804 }
6805
6806 /*-----------------------------------------------------------------*/
6807 /* genXor - code for xclusive or                                   */
6808 /*-----------------------------------------------------------------*/
6809 static void genXor (iCode *ic, iCode *ifx)
6810 {
6811   operand *left, *right, *result;
6812   int size, offset=0;
6813   unsigned long lit = 0L;
6814
6815   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6816
6817   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6818   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6819   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6820
6821   /* if left is a literal & right is not ||
6822      if left needs acc & right does not */
6823   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6824       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6825     operand *tmp = right ;
6826     right = left;
6827     left = tmp;
6828   }
6829
6830   /* if result = right then exchange them */
6831   if(pic16_sameRegs(AOP(result),AOP(right))){
6832     operand *tmp = right ;
6833     right = left;
6834     left = tmp;
6835   }
6836
6837   /* if right is bit then exchange them */
6838   if (AOP_TYPE(right) == AOP_CRY &&
6839       AOP_TYPE(left) != AOP_CRY){
6840     operand *tmp = right ;
6841     right = left;
6842     left = tmp;
6843   }
6844   if(AOP_TYPE(right) == AOP_LIT)
6845     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6846
6847   size = AOP_SIZE(result);
6848
6849   // if(bit ^ yy)
6850   // xx = bit ^ yy;
6851   if (AOP_TYPE(left) == AOP_CRY){
6852     if(AOP_TYPE(right) == AOP_LIT){
6853       // c = bit & literal;
6854       if(lit>>1){
6855         // lit>>1  != 0 => result = 1
6856         if(AOP_TYPE(result) == AOP_CRY){
6857           if(size)
6858             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6859             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6860           else if(ifx)
6861             continueIfTrue(ifx);
6862           goto release;
6863         }
6864         pic16_emitcode("setb","c");
6865       } else{
6866         // lit == (0 or 1)
6867         if(lit == 0){
6868           // lit == 0, result = left
6869           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6870             goto release;
6871           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6872         } else{
6873           // lit == 1, result = not(left)
6874           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6875             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6876             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6877             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6878             goto release;
6879           } else {
6880             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6881             pic16_emitcode("cpl","c");
6882           }
6883         }
6884       }
6885
6886     } else {
6887       // right != literal
6888       symbol *tlbl = newiTempLabel(NULL);
6889       if (AOP_TYPE(right) == AOP_CRY){
6890         // c = bit ^ bit;
6891         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6892       }
6893       else{
6894         int sizer = AOP_SIZE(right);
6895         // c = bit ^ val
6896         // if val>>1 != 0, result = 1
6897         pic16_emitcode("setb","c");
6898         while(sizer){
6899           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6900           if(sizer == 1)
6901             // test the msb of the lsb
6902             pic16_emitcode("anl","a,#0xfe");
6903           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6904           sizer--;
6905         }
6906         // val = (0,1)
6907         pic16_emitcode("rrc","a");
6908       }
6909       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6910       pic16_emitcode("cpl","c");
6911       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6912     }
6913     // bit = c
6914     // val = c
6915     if(size)
6916       pic16_outBitC(result);
6917     // if(bit | ...)
6918     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6919       genIfxJump(ifx, "c");           
6920     goto release ;
6921   }
6922
6923   if(pic16_sameRegs(AOP(result),AOP(left))){
6924     /* if left is same as result */
6925     for(;size--; offset++) {
6926       if(AOP_TYPE(right) == AOP_LIT){
6927         int t  = (lit >> (offset*8)) & 0x0FFL;
6928         if(t == 0x00L)
6929           continue;
6930         else
6931           if (IS_AOP_PREG(left)) {
6932             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6933             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6934             pic16_aopPut(AOP(result),"a",offset);
6935           } else {
6936             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6937             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6938             pic16_emitcode("xrl","%s,%s",
6939                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6940                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6941           }
6942       } else {
6943         if (AOP_TYPE(left) == AOP_ACC)
6944           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6945         else {
6946           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6947           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6948 /*
6949           if (IS_AOP_PREG(left)) {
6950             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6951             pic16_aopPut(AOP(result),"a",offset);
6952           } else
6953             pic16_emitcode("xrl","%s,a",
6954                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6955 */
6956         }
6957       }
6958     }
6959   } else {
6960     // left & result in different registers
6961     if(AOP_TYPE(result) == AOP_CRY){
6962       // result = bit
6963       // if(size), result in bit
6964       // if(!size && ifx), conditional oper: if(left ^ right)
6965       symbol *tlbl = newiTempLabel(NULL);
6966       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6967       if(size)
6968         pic16_emitcode("setb","c");
6969       while(sizer--){
6970         if((AOP_TYPE(right) == AOP_LIT) &&
6971            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6972           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6973         } else {
6974           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6975           pic16_emitcode("xrl","a,%s",
6976                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6977         }
6978         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6979         offset++;
6980       }
6981       if(size){
6982         CLRC;
6983         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6984         pic16_outBitC(result);
6985       } else if(ifx)
6986         jmpTrueOrFalse(ifx, tlbl);
6987     } else for(;(size--);offset++){
6988       // normal case
6989       // result = left & right
6990       if(AOP_TYPE(right) == AOP_LIT){
6991         int t = (lit >> (offset*8)) & 0x0FFL;
6992         switch(t) { 
6993         case 0x00:
6994           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6995           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6996           pic16_emitcode("movf","%s,w",
6997                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6998           pic16_emitcode("movwf","%s",
6999                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7000           break;
7001         case 0xff:
7002           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
7003           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7004           pic16_emitcode("comf","%s,w",
7005                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7006           pic16_emitcode("movwf","%s",
7007                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7008           break;
7009         default:
7010           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
7011           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7012           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7013           pic16_emitcode("movlw","0x%x",t);
7014           pic16_emitcode("xorwf","%s,w",
7015                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7016           pic16_emitcode("movwf","%s",
7017                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7018
7019         }
7020         continue;
7021       }
7022
7023       // faster than result <- left, anl result,right
7024       // and better if result is SFR
7025       if (AOP_TYPE(left) == AOP_ACC) {
7026         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
7027         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7028       } else {
7029         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
7030         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
7031         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
7032         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
7033       }
7034       if ( AOP_TYPE(result) != AOP_ACC){
7035         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
7036         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
7037       }
7038     }
7039   }
7040
7041   release :
7042     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7043   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
7044   pic16_freeAsmop(result,NULL,ic,TRUE);     
7045 }
7046
7047 /*-----------------------------------------------------------------*/
7048 /* genInline - write the inline code out                           */
7049 /*-----------------------------------------------------------------*/
7050 static void genInline (iCode *ic)
7051 {
7052   char *buffer, *bp, *bp1;
7053     
7054         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7055
7056         _G.inLine += (!options.asmpeep);
7057
7058         buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
7059         strcpy(buffer,IC_INLINE(ic));
7060
7061 //      fprintf(stderr, "%s:%d inline asm : < %s >\n", __FILE__, __LINE__, buffer);
7062
7063         /* emit each line as a code */
7064         while (*bp) {
7065                 if (*bp == '\n') {
7066                         *bp++ = '\0';
7067
7068                         if(*bp1)
7069                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7070                         bp1 = bp;
7071                 } else {
7072                         if (*bp == ':') {
7073                                 bp++;
7074                                 *bp = '\0';
7075                                 bp++;
7076
7077                                 /* print label, use this special format with NULL directive
7078                                  * to denote that the argument should not be indented with tab */
7079                                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(NULL, bp1)); // inline directly, no process
7080                                 bp1 = bp;
7081                         } else
7082                                 bp++;
7083                 }
7084         }
7085
7086         if ((bp1 != bp) && *bp1)
7087                 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL)); // inline directly, no process
7088
7089
7090     Safe_free(buffer);
7091
7092     _G.inLine -= (!options.asmpeep);
7093 }
7094
7095 /*-----------------------------------------------------------------*/
7096 /* genRRC - rotate right with carry                                */
7097 /*-----------------------------------------------------------------*/
7098 static void genRRC (iCode *ic)
7099 {
7100   operand *left , *result ;
7101   int size, offset = 0, same;
7102
7103   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7104
7105   /* rotate right with carry */
7106   left = IC_LEFT(ic);
7107   result=IC_RESULT(ic);
7108   pic16_aopOp (left,ic,FALSE);
7109   pic16_aopOp (result,ic,FALSE);
7110
7111   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7112
7113   same = pic16_sameRegs(AOP(result),AOP(left));
7114
7115   size = AOP_SIZE(result);    
7116
7117   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
7118
7119   /* get the lsb and put it into the carry */
7120   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
7121
7122   offset = 0 ;
7123
7124   while(size--) {
7125
7126     if(same) {
7127       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
7128     } else {
7129       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
7130       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7131     }
7132
7133     offset++;
7134   }
7135
7136   pic16_freeAsmop(left,NULL,ic,TRUE);
7137   pic16_freeAsmop(result,NULL,ic,TRUE);
7138 }
7139
7140 /*-----------------------------------------------------------------*/
7141 /* genRLC - generate code for rotate left with carry               */
7142 /*-----------------------------------------------------------------*/
7143 static void genRLC (iCode *ic)
7144 {    
7145   operand *left , *result ;
7146   int size, offset = 0;
7147   int same;
7148
7149   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7150   /* rotate right with carry */
7151   left = IC_LEFT(ic);
7152   result=IC_RESULT(ic);
7153   pic16_aopOp (left,ic,FALSE);
7154   pic16_aopOp (result,ic,FALSE);
7155
7156   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
7157
7158   same = pic16_sameRegs(AOP(result),AOP(left));
7159
7160   /* move it to the result */
7161   size = AOP_SIZE(result);    
7162
7163   /* get the msb and put it into the carry */
7164   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
7165
7166   offset = 0 ;
7167
7168   while(size--) {
7169
7170     if(same) {
7171       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
7172     } else {
7173       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
7174       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
7175     }
7176
7177     offset++;
7178   }
7179
7180
7181   pic16_freeAsmop(left,NULL,ic,TRUE);
7182   pic16_freeAsmop(result,NULL,ic,TRUE);
7183 }
7184
7185
7186 /* gpasm can get the highest order bit with HIGH/UPPER
7187  * so the following probably is not needed -- VR */
7188  
7189 /*-----------------------------------------------------------------*/
7190 /* genGetHbit - generates code get highest order bit               */
7191 /*-----------------------------------------------------------------*/
7192 static void genGetHbit (iCode *ic)
7193 {
7194     operand *left, *result;
7195     left = IC_LEFT(ic);
7196     result=IC_RESULT(ic);
7197     pic16_aopOp (left,ic,FALSE);
7198     pic16_aopOp (result,ic,FALSE);
7199
7200     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7201     /* get the highest order byte into a */
7202     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
7203     if(AOP_TYPE(result) == AOP_CRY){
7204         pic16_emitcode("rlc","a");
7205         pic16_outBitC(result);
7206     }
7207     else{
7208         pic16_emitcode("rl","a");
7209         pic16_emitcode("anl","a,#0x01");
7210         pic16_outAcc(result);
7211     }
7212
7213
7214     pic16_freeAsmop(left,NULL,ic,TRUE);
7215     pic16_freeAsmop(result,NULL,ic,TRUE);
7216 }
7217
7218 #if 0
7219 /*-----------------------------------------------------------------*/
7220 /* AccRol - rotate left accumulator by known count                 */
7221 /*-----------------------------------------------------------------*/
7222 static void AccRol (int shCount)
7223 {
7224     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7225     shCount &= 0x0007;              // shCount : 0..7
7226     switch(shCount){
7227         case 0 :
7228             break;
7229         case 1 :
7230             pic16_emitcode("rl","a");
7231             break;
7232         case 2 :
7233             pic16_emitcode("rl","a");
7234             pic16_emitcode("rl","a");
7235             break;
7236         case 3 :
7237             pic16_emitcode("swap","a");
7238             pic16_emitcode("rr","a");
7239             break;
7240         case 4 :
7241             pic16_emitcode("swap","a");
7242             break;
7243         case 5 :
7244             pic16_emitcode("swap","a");
7245             pic16_emitcode("rl","a");
7246             break;
7247         case 6 :
7248             pic16_emitcode("rr","a");
7249             pic16_emitcode("rr","a");
7250             break;
7251         case 7 :
7252             pic16_emitcode("rr","a");
7253             break;
7254     }
7255 }
7256 #endif
7257
7258 /*-----------------------------------------------------------------*/
7259 /* AccLsh - left shift accumulator by known count                  */
7260 /*-----------------------------------------------------------------*/
7261 static void AccLsh (int shCount)
7262 {
7263         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7264         switch(shCount){
7265                 case 0 :
7266                         return;
7267                         break;
7268                 case 1 :
7269                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7270                         break;
7271                 case 2 :
7272                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7273                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7274                         break;
7275                 case 3 :
7276                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7277                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7278                         break;
7279                 case 4 :
7280                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7281                         break;
7282                 case 5 :
7283                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7284                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7285                         break;
7286                 case 6 :
7287                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7288                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7289                         break;
7290                 case 7 :
7291                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7292                         break;
7293         }
7294
7295         pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
7296 }
7297
7298 /*-----------------------------------------------------------------*/
7299 /* AccRsh - right shift accumulator by known count                 */
7300 /*-----------------------------------------------------------------*/
7301 static void AccRsh (int shCount, int andmask)
7302 {
7303         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7304         switch(shCount){
7305                 case 0 :
7306                         return; break;
7307                 case 1 :
7308                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7309 //                      andmask = 0;    /* no need */
7310                         break;
7311                 case 2 :
7312                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7313                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7314 //                      andmask = 0;    /* no need */
7315                         break;
7316                 case 3 :
7317                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7318                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7319                         break;
7320                 case 4 :
7321                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7322                         break;
7323                 case 5 :
7324                         pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
7325                         pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7326                         break;
7327                 case 6 :
7328                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7329                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7330                         break;
7331                 case 7 :
7332                         pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
7333                         break;
7334         }
7335         
7336         if(andmask)
7337                 pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
7338         else
7339                 DEBUGpic16_emitcode("; ***", "%s omitting masking the result", __FUNCTION__);
7340 }
7341
7342 #if 0
7343 /*-----------------------------------------------------------------*/
7344 /* AccSRsh - signed right shift accumulator by known count                 */
7345 /*-----------------------------------------------------------------*/
7346 static void AccSRsh (int shCount)
7347 {
7348     symbol *tlbl ;
7349     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7350     if(shCount != 0){
7351         if(shCount == 1){
7352             pic16_emitcode("mov","c,acc.7");
7353             pic16_emitcode("rrc","a");
7354         } else if(shCount == 2){
7355             pic16_emitcode("mov","c,acc.7");
7356             pic16_emitcode("rrc","a");
7357             pic16_emitcode("mov","c,acc.7");
7358             pic16_emitcode("rrc","a");
7359         } else {
7360             tlbl = newiTempLabel(NULL);
7361             /* rotate right accumulator */
7362             AccRol(8 - shCount);
7363             /* and kill the higher order bits */
7364             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
7365             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
7366             pic16_emitcode("orl","a,#0x%02x",
7367                      (unsigned char)~SRMask[shCount]);
7368             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
7369         }
7370     }
7371 }
7372 #endif
7373 /*-----------------------------------------------------------------*/
7374 /* shiftR1Left2Result - shift right one byte from left to result   */
7375 /*-----------------------------------------------------------------*/
7376 static void shiftR1Left2ResultSigned (operand *left, int offl,
7377                                 operand *result, int offr,
7378                                 int shCount)
7379 {
7380   int same;
7381
7382   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7383
7384   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7385
7386   switch(shCount) {
7387   case 1:
7388     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7389     if(same) 
7390       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7391     else {
7392       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7393       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7394     }
7395
7396     break;
7397   case 2:
7398
7399     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7400     if(same) 
7401       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7402     else {
7403       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7404       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7405     }
7406     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7407     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7408
7409     break;
7410
7411   case 3:
7412     if(same)
7413       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7414     else {
7415       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7416       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7417     }
7418
7419     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7420     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7421     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7422
7423     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7424     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
7425
7426     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7427     break;
7428
7429   case 4:
7430     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7431     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
7432     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7433     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
7434     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7435     break;
7436   case 5:
7437     if(same) {
7438       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
7439     } else {
7440       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
7441       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7442     }
7443     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
7444     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
7445     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
7446     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
7447     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7448     break;
7449
7450   case 6:
7451     if(same) {
7452       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7453       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7454       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
7455       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7456       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
7457       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7458     } else {
7459       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7460       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7461       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7462       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
7463       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
7464     }
7465     break;
7466
7467   case 7:
7468     if(same) {
7469       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
7470       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7471       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7472       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7473     } else {
7474       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
7475       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
7476       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
7477     }
7478
7479   default:
7480     break;
7481   }
7482 }
7483
7484 /*-----------------------------------------------------------------*/
7485 /* shiftR1Left2Result - shift right one byte from left to result   */
7486 /*-----------------------------------------------------------------*/
7487 static void shiftR1Left2Result (operand *left, int offl,
7488                                 operand *result, int offr,
7489                                 int shCount, int sign)
7490 {
7491   int same;
7492
7493   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7494
7495   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7496
7497   /* Copy the msb into the carry if signed. */
7498   if(sign) {
7499     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
7500     return;
7501   }
7502
7503
7504
7505   switch(shCount) {
7506   case 1:
7507     emitCLRC;
7508     if(same) 
7509       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7510     else {
7511       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7512       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7513     }
7514     break;
7515   case 2:
7516     emitCLRC;
7517     if(same) {
7518       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7519     } else {
7520       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7521       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7522     }
7523     emitCLRC;
7524     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7525
7526     break;
7527   case 3:
7528     if(same)
7529       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7530     else {
7531       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7532       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7533     }
7534
7535     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7536     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
7537     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
7538     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7539     break;
7540       
7541   case 4:
7542     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7543     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7544     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7545     break;
7546
7547   case 5:
7548     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
7549     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7550     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7551     emitCLRC;
7552     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7553
7554     break;
7555   case 6:
7556
7557     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
7558     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
7559     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7560     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7561     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
7562     break;
7563
7564   case 7:
7565
7566     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7567     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7568     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7569
7570     break;
7571
7572   default:
7573     break;
7574   }
7575 }
7576
7577 /*-----------------------------------------------------------------*/
7578 /* shiftL1Left2Result - shift left one byte from left to result    */
7579 /*-----------------------------------------------------------------*/
7580 static void shiftL1Left2Result (operand *left, int offl,
7581                                 operand *result, int offr, int shCount)
7582 {
7583   int same;
7584
7585   //    char *l;
7586   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7587
7588   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
7589   DEBUGpic16_emitcode ("; ***","same =  %d",same);
7590     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7591     //    MOVA(l);
7592     /* shift left accumulator */
7593     //AccLsh(shCount); // don't comment out just yet...
7594   //    pic16_aopPut(AOP(result),"a",offr);
7595
7596   switch(shCount) {
7597   case 1:
7598     /* Shift left 1 bit position */
7599     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7600     if(same) {
7601       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
7602     } else {
7603       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
7604       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7605     }
7606     break;
7607   case 2:
7608     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7609     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
7610     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7611     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7612     break;
7613   case 3:
7614     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7615     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
7616     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7617     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7618     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7619     break;
7620   case 4:
7621     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7622     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7623     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7624     break;
7625   case 5:
7626     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7627     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7628     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7629     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7630     break;
7631   case 6:
7632     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7633     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
7634     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7635     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7636     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7637     break;
7638   case 7:
7639     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7640     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7641     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7642     break;
7643
7644   default:
7645     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
7646   }
7647
7648 }
7649
7650 /*-----------------------------------------------------------------*/
7651 /* movLeft2Result - move byte from left to result                  */
7652 /*-----------------------------------------------------------------*/
7653 static void movLeft2Result (operand *left, int offl,
7654                             operand *result, int offr)
7655 {
7656   char *l;
7657   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7658   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
7659     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
7660
7661     if (*l == '@' && (IS_AOP_PREG(result))) {
7662       pic16_emitcode("mov","a,%s",l);
7663       pic16_aopPut(AOP(result),"a",offr);
7664     } else {
7665       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7666       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7667     }
7668   }
7669 }
7670
7671 /*-----------------------------------------------------------------*/
7672 /* shiftL2Left2Result - shift left two bytes from left to result   */
7673 /*-----------------------------------------------------------------*/
7674 static void shiftL2Left2Result (operand *left, int offl,
7675                                 operand *result, int offr, int shCount)
7676 {
7677   int same = pic16_sameRegs(AOP(result), AOP(left));
7678   int i;
7679
7680   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
7681
7682   if (same && (offl != offr)) { // shift bytes
7683     if (offr > offl) {
7684        for(i=1;i>-1;i--) {
7685          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7686          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7687        }
7688     } else { // just treat as different later on
7689                 same = 0;
7690     }
7691   }
7692
7693   if(same) {
7694     switch(shCount) {
7695     case 0:
7696       break;
7697     case 1:
7698     case 2:
7699     case 3:
7700
7701       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
7702       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
7703       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7704
7705       while(--shCount) {
7706                 emitCLRC;
7707                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7708                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7709       }
7710
7711       break;
7712     case 4:
7713     case 5:
7714       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
7715       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
7716       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7717       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7718       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
7719       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7720       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7721       if(shCount >=5) {
7722                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7723                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7724       }
7725       break;
7726     case 6:
7727       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7728       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7729       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7730       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7731       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7732       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7733       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7734       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7735       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7736       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7737       break;
7738     case 7:
7739       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7740       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
7741       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7742       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7743       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7744     }
7745
7746   } else {
7747     switch(shCount) {
7748     case 0:
7749       break;
7750     case 1:
7751     case 2:
7752     case 3:
7753       /* note, use a mov/add for the shift since the mov has a
7754          chance of getting optimized out */
7755       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7756       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7757       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7758       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7759       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7760
7761       while(--shCount) {
7762                 emitCLRC;
7763                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7764                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7765       }
7766       break;
7767
7768     case 4:
7769     case 5:
7770       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7771       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7772       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7773       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7774       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7775       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7776       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7777       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7778
7779
7780       if(shCount == 5) {
7781                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7782                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7783       }
7784       break;
7785     case 6:
7786       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7787       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7788       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7789       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7790
7791       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7792       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7793       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7794       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7795       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7796       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7797       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7798       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7799       break;
7800     case 7:
7801       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7802       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7803       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7804       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7805       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7806     }
7807   }
7808
7809 }
7810 /*-----------------------------------------------------------------*/
7811 /* shiftR2Left2Result - shift right two bytes from left to result  */
7812 /*-----------------------------------------------------------------*/
7813 static void shiftR2Left2Result (operand *left, int offl,
7814                                 operand *result, int offr,
7815                                 int shCount, int sign)
7816 {
7817   int same = pic16_sameRegs(AOP(result), AOP(left));
7818   int i;
7819   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7820
7821   if (same && (offl != offr)) { // shift right bytes
7822     if (offr < offl) {
7823        for(i=0;i<2;i++) {
7824          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7825          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7826        }
7827     } else { // just treat as different later on
7828                 same = 0;
7829     }
7830   }
7831
7832   switch(shCount) {
7833   case 0:
7834     break;
7835   case 1:
7836   case 2:
7837   case 3:
7838     if(sign)
7839       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7840     else
7841       emitCLRC;
7842
7843     if(same) {
7844       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7845       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7846     } else {
7847       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7848       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7849       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7850       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7851     }
7852
7853     while(--shCount) {
7854       if(sign)
7855                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7856       else
7857                 emitCLRC;
7858       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7859       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7860     }
7861     break;
7862   case 4:
7863   case 5:
7864     if(same) {
7865
7866       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7867       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7868       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7869
7870       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7871       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7872       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7873       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7874     } else {
7875       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7876       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7877       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7878
7879       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7880       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7881       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7882       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7883       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7884     }
7885
7886     if(shCount >=5) {
7887       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7888       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7889     }
7890
7891     if(sign) {
7892       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7893       pic16_emitpcode(POC_BTFSC, 
7894                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7895       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7896     }
7897
7898     break;
7899
7900   case 6:
7901     if(same) {
7902
7903       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7904       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7905
7906       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7907       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7908       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7909       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7910       if(sign) {
7911         pic16_emitpcode(POC_BTFSC, 
7912                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7913         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7914       }
7915       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7916       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7917       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7918       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7919     } else {
7920       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7921       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7922       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7923       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7924       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7925       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7926       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7927       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7928       if(sign) {
7929         pic16_emitpcode(POC_BTFSC, 
7930                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7931         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7932       }
7933       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7934       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7935
7936         
7937     }
7938
7939     break;
7940   case 7:
7941     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7942     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7943     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7944     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7945     if(sign) {
7946       emitSKPNC;
7947       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7948     } else 
7949       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7950   }
7951 }
7952
7953
7954 /*-----------------------------------------------------------------*/
7955 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7956 /*-----------------------------------------------------------------*/
7957 static void shiftLLeftOrResult (operand *left, int offl,
7958                                 operand *result, int offr, int shCount)
7959 {
7960     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7961
7962     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7963     /* shift left accumulator */
7964     AccLsh(shCount);
7965     /* or with result */
7966     /* back to result */
7967     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7968 }
7969
7970 /*-----------------------------------------------------------------*/
7971 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7972 /*-----------------------------------------------------------------*/
7973 static void shiftRLeftOrResult (operand *left, int offl,
7974                                 operand *result, int offr, int shCount)
7975 {
7976     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7977     
7978     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7979     /* shift right accumulator */
7980     AccRsh(shCount, 1);
7981     /* or with result */
7982     /* back to result */
7983     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7984 }
7985
7986 /*-----------------------------------------------------------------*/
7987 /* genlshOne - left shift a one byte quantity by known count       */
7988 /*-----------------------------------------------------------------*/
7989 static void genlshOne (operand *result, operand *left, int shCount)
7990 {       
7991     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7992     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7993 }
7994
7995 /*-----------------------------------------------------------------*/
7996 /* genlshTwo - left shift two bytes by known amount != 0           */
7997 /*-----------------------------------------------------------------*/
7998 static void genlshTwo (operand *result,operand *left, int shCount)
7999 {
8000     int size;
8001     
8002     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8003     size = pic16_getDataSize(result);
8004
8005     /* if shCount >= 8 */
8006     if (shCount >= 8) {
8007         shCount -= 8 ;
8008
8009         if (size > 1){
8010             if (shCount)
8011                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8012             else 
8013                 movLeft2Result(left, LSB, result, MSB16);
8014         }
8015         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8016     }
8017
8018     /*  1 <= shCount <= 7 */
8019     else {  
8020         if(size == 1)
8021             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
8022         else 
8023             shiftL2Left2Result(left, LSB, result, LSB, shCount);
8024     }
8025 }
8026
8027 /*-----------------------------------------------------------------*/
8028 /* shiftLLong - shift left one long from left to result            */
8029 /* offr = LSB or MSB16                                             */
8030 /*-----------------------------------------------------------------*/
8031 static void shiftLLong (operand *left, operand *result, int offr )
8032 {
8033     int size = AOP_SIZE(result);
8034     int same = pic16_sameRegs(AOP(left),AOP(result));
8035         int i;
8036
8037     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
8038
8039         if (same && (offr == MSB16)) { //shift one byte
8040                 for(i=size-1;i>=MSB16;i--) {
8041                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
8042                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
8043                 }
8044         } else {
8045                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
8046         }
8047         
8048     if (size >= LSB+offr ){
8049                 if (same) {
8050                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
8051                 } else {
8052                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
8053                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
8054                 }
8055          }
8056
8057     if(size >= MSB16+offr){
8058                 if (same) {
8059                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
8060                 } else {
8061                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
8062                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
8063                 }
8064     }
8065
8066     if(size >= MSB24+offr){
8067                 if (same) {
8068                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
8069                 } else {
8070                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
8071                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
8072                 }
8073     }
8074
8075     if(size > MSB32+offr){
8076                 if (same) {
8077                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
8078                 } else {
8079                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
8080                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
8081                 }
8082     }
8083     if(offr != LSB)
8084                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8085
8086 }
8087
8088 /*-----------------------------------------------------------------*/
8089 /* genlshFour - shift four byte by a known amount != 0             */
8090 /*-----------------------------------------------------------------*/
8091 static void genlshFour (operand *result, operand *left, int shCount)
8092 {
8093     int size;
8094
8095     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8096     size = AOP_SIZE(result);
8097
8098     /* if shifting more that 3 bytes */
8099     if (shCount >= 24 ) {
8100         shCount -= 24;
8101         if (shCount)
8102             /* lowest order of left goes to the highest
8103             order of the destination */
8104             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
8105         else
8106             movLeft2Result(left, LSB, result, MSB32);
8107
8108                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8109                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8110                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
8111
8112         return;
8113     }
8114
8115     /* more than two bytes */
8116     else if ( shCount >= 16 ) {
8117         /* lower order two bytes goes to higher order two bytes */
8118         shCount -= 16;
8119         /* if some more remaining */
8120         if (shCount)
8121             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
8122         else {
8123             movLeft2Result(left, MSB16, result, MSB32);
8124             movLeft2Result(left, LSB, result, MSB24);
8125         }
8126                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8127                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8128         return;
8129     }    
8130
8131     /* if more than 1 byte */
8132     else if ( shCount >= 8 ) {
8133         /* lower order three bytes goes to higher order  three bytes */
8134         shCount -= 8;
8135         if(size == 2){
8136             if(shCount)
8137                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8138             else
8139                 movLeft2Result(left, LSB, result, MSB16);
8140         }
8141         else{   /* size = 4 */
8142             if(shCount == 0){
8143                 movLeft2Result(left, MSB24, result, MSB32);
8144                 movLeft2Result(left, MSB16, result, MSB24);
8145                 movLeft2Result(left, LSB, result, MSB16);
8146                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8147             }
8148             else if(shCount == 1)
8149                 shiftLLong(left, result, MSB16);
8150             else{
8151                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
8152                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
8153                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
8154                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
8155             }
8156         }
8157     }
8158
8159     /* 1 <= shCount <= 7 */
8160     else if(shCount <= 3)
8161     { 
8162         shiftLLong(left, result, LSB);
8163         while(--shCount >= 1)
8164             shiftLLong(result, result, LSB);
8165     }
8166     /* 3 <= shCount <= 7, optimize */
8167     else{
8168         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
8169         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
8170         shiftL2Left2Result(left, LSB, result, LSB, shCount);
8171     }
8172 }
8173
8174 /*-----------------------------------------------------------------*/
8175 /* genLeftShiftLiteral - left shifting by known count              */
8176 /*-----------------------------------------------------------------*/
8177 static void genLeftShiftLiteral (operand *left,
8178                                  operand *right,
8179                                  operand *result,
8180                                  iCode *ic)
8181 {    
8182     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8183     int size;
8184
8185     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8186     pic16_freeAsmop(right,NULL,ic,TRUE);
8187
8188     pic16_aopOp(left,ic,FALSE);
8189     pic16_aopOp(result,ic,FALSE);
8190
8191     size = getSize(operandType(result));
8192
8193 #if VIEW_SIZE
8194     pic16_emitcode("; shift left ","result %d, left %d",size,
8195              AOP_SIZE(left));
8196 #endif
8197
8198     /* I suppose that the left size >= result size */
8199     if(shCount == 0){
8200         while(size--){
8201             movLeft2Result(left, size, result, size);
8202         }
8203     }
8204
8205     else if(shCount >= (size * 8))
8206         while(size--)
8207             pic16_aopPut(AOP(result),zero,size);
8208     else{
8209         switch (size) {
8210             case 1:
8211                 genlshOne (result,left,shCount);
8212                 break;
8213
8214             case 2:
8215             case 3:
8216                 genlshTwo (result,left,shCount);
8217                 break;
8218
8219             case 4:
8220                 genlshFour (result,left,shCount);
8221                 break;
8222         }
8223     }
8224     pic16_freeAsmop(left,NULL,ic,TRUE);
8225     pic16_freeAsmop(result,NULL,ic,TRUE);
8226 }
8227
8228 /*-----------------------------------------------------------------*
8229  * genMultiAsm - repeat assembly instruction for size of register.
8230  * if endian == 1, then the high byte (i.e base address + size of 
8231  * register) is used first else the low byte is used first;
8232  *-----------------------------------------------------------------*/
8233 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
8234 {
8235
8236   int offset = 0;
8237
8238   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8239
8240   if(!reg)
8241     return;
8242
8243   if(!endian) {
8244     endian = 1;
8245   } else {
8246     endian = -1;
8247     offset = size-1;
8248   }
8249
8250   while(size--) {
8251     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
8252     offset += endian;
8253   }
8254
8255 }
8256 /*-----------------------------------------------------------------*/
8257 /* genLeftShift - generates code for left shifting                 */
8258 /*-----------------------------------------------------------------*/
8259 static void genLeftShift (iCode *ic)
8260 {
8261   operand *left,*right, *result;
8262   int size, offset;
8263   char *l;
8264   symbol *tlbl , *tlbl1;
8265   pCodeOp *pctemp;
8266
8267   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8268
8269   right = IC_RIGHT(ic);
8270   left  = IC_LEFT(ic);
8271   result = IC_RESULT(ic);
8272
8273   pic16_aopOp(right,ic,FALSE);
8274
8275   /* if the shift count is known then do it 
8276      as efficiently as possible */
8277   if (AOP_TYPE(right) == AOP_LIT) {
8278     genLeftShiftLiteral (left,right,result,ic);
8279     return ;
8280   }
8281
8282   /* shift count is unknown then we have to form 
8283      a loop get the loop count in B : Note: we take
8284      only the lower order byte since shifting
8285      more that 32 bits make no sense anyway, ( the
8286      largest size of an object can be only 32 bits ) */  
8287
8288     
8289   pic16_aopOp(left,ic,FALSE);
8290   pic16_aopOp(result,ic,FALSE);
8291
8292   /* now move the left to the result if they are not the
8293      same */
8294   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8295       AOP_SIZE(result) > 1) {
8296
8297     size = AOP_SIZE(result);
8298     offset=0;
8299     while (size--) {
8300       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8301       if (*l == '@' && (IS_AOP_PREG(result))) {
8302
8303         pic16_emitcode("mov","a,%s",l);
8304         pic16_aopPut(AOP(result),"a",offset);
8305       } else {
8306         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8307         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8308         //pic16_aopPut(AOP(result),l,offset);
8309       }
8310       offset++;
8311     }
8312   }
8313
8314   size = AOP_SIZE(result);
8315
8316   /* if it is only one byte then */
8317   if (size == 1) {
8318     if(optimized_for_speed) {
8319       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
8320       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
8321       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
8322       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8323       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8324       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
8325       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8326       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
8327       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
8328       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
8329       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
8330       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
8331     } else {
8332
8333       tlbl = newiTempLabel(NULL);
8334       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8335                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8336                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8337       }
8338
8339       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8340       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8341       pic16_emitpLabel(tlbl->key);
8342       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8343       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8344       emitSKPC;
8345       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8346     }
8347     goto release ;
8348   }
8349     
8350   if (pic16_sameRegs(AOP(left),AOP(result))) {
8351
8352     tlbl = newiTempLabel(NULL);
8353     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8354     genMultiAsm(POC_RRCF, result, size,1);
8355     pic16_emitpLabel(tlbl->key);
8356     genMultiAsm(POC_RLCF, result, size,0);
8357     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8358     emitSKPC;
8359     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8360     goto release;
8361   }
8362
8363   //tlbl = newiTempLabel(NULL);
8364   //offset = 0 ;   
8365   //tlbl1 = newiTempLabel(NULL);
8366
8367   //reAdjustPreg(AOP(result));    
8368     
8369   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
8370   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8371   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8372   //MOVA(l);
8373   //pic16_emitcode("add","a,acc");         
8374   //pic16_aopPut(AOP(result),"a",offset++);
8375   //while (--size) {
8376   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8377   //  MOVA(l);
8378   //  pic16_emitcode("rlc","a");         
8379   //  pic16_aopPut(AOP(result),"a",offset++);
8380   //}
8381   //reAdjustPreg(AOP(result));
8382
8383   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8384   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8385
8386
8387   tlbl = newiTempLabel(NULL);
8388   tlbl1= newiTempLabel(NULL);
8389
8390   size = AOP_SIZE(result);
8391   offset = 1;
8392
8393   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8394
8395   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8396
8397   /* offset should be 0, 1 or 3 */
8398   
8399   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
8400   emitSKPNZ;
8401   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8402
8403   pic16_emitpcode(POC_MOVWF, pctemp);
8404
8405
8406   pic16_emitpLabel(tlbl->key);
8407
8408   emitCLRC;
8409   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
8410   while(--size)
8411     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
8412
8413   pic16_emitpcode(POC_DECFSZ,  pctemp);
8414   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8415   pic16_emitpLabel(tlbl1->key);
8416
8417   pic16_popReleaseTempReg(pctemp);
8418
8419
8420  release:
8421   pic16_freeAsmop (right,NULL,ic,TRUE);
8422   pic16_freeAsmop(left,NULL,ic,TRUE);
8423   pic16_freeAsmop(result,NULL,ic,TRUE);
8424 }
8425
8426 /*-----------------------------------------------------------------*/
8427 /* genrshOne - right shift a one byte quantity by known count      */
8428 /*-----------------------------------------------------------------*/
8429 static void genrshOne (operand *result, operand *left,
8430                        int shCount, int sign)
8431 {
8432     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8433     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
8434 }
8435
8436 /*-----------------------------------------------------------------*/
8437 /* genrshTwo - right shift two bytes by known amount != 0          */
8438 /*-----------------------------------------------------------------*/
8439 static void genrshTwo (operand *result,operand *left,
8440                        int shCount, int sign)
8441 {
8442   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
8443   /* if shCount >= 8 */
8444   if (shCount >= 8) {
8445     shCount -= 8 ;
8446     if (shCount)
8447       shiftR1Left2Result(left, MSB16, result, LSB,
8448                          shCount, sign);
8449     else
8450       movLeft2Result(left, MSB16, result, LSB);
8451
8452     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
8453
8454     if(sign) {
8455       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
8456       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
8457     }
8458   }
8459
8460   /*  1 <= shCount <= 7 */
8461   else
8462     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
8463 }
8464
8465 /*-----------------------------------------------------------------*/
8466 /* shiftRLong - shift right one long from left to result           */
8467 /* offl = LSB or MSB16                                             */
8468 /*-----------------------------------------------------------------*/
8469 static void shiftRLong (operand *left, int offl,
8470                         operand *result, int sign)
8471 {
8472     int size = AOP_SIZE(result);
8473     int same = pic16_sameRegs(AOP(left),AOP(result));
8474     int i;
8475     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
8476
8477         if (same && (offl == MSB16)) { //shift one byte right
8478                 for(i=MSB16;i<size;i++) {
8479                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
8480                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
8481                 }
8482         }
8483
8484     if(sign)
8485                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
8486         else
8487                 emitCLRC;
8488
8489         if (same) {
8490                 if (offl == LSB)
8491                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
8492         } else {
8493         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
8494         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
8495         }
8496
8497     if(offl == MSB16) {
8498         /* add sign of "a" */
8499         pic16_addSign(result, MSB32, sign);
8500         }
8501
8502         if (same) {
8503         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
8504         } else {
8505         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
8506         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
8507         }
8508         
8509         if (same) {
8510         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
8511         } else {
8512         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
8513         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
8514         }
8515
8516         if (same) {
8517         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
8518         } else {
8519         if(offl == LSB){
8520                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
8521                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
8522         }
8523         }
8524 }
8525
8526 /*-----------------------------------------------------------------*/
8527 /* genrshFour - shift four byte by a known amount != 0             */
8528 /*-----------------------------------------------------------------*/
8529 static void genrshFour (operand *result, operand *left,
8530                         int shCount, int sign)
8531 {
8532   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8533   /* if shifting more that 3 bytes */
8534   if(shCount >= 24 ) {
8535     shCount -= 24;
8536     if(shCount)
8537       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
8538     else
8539       movLeft2Result(left, MSB32, result, LSB);
8540
8541     pic16_addSign(result, MSB16, sign);
8542   }
8543   else if(shCount >= 16){
8544     shCount -= 16;
8545     if(shCount)
8546       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
8547     else{
8548       movLeft2Result(left, MSB24, result, LSB);
8549       movLeft2Result(left, MSB32, result, MSB16);
8550     }
8551     pic16_addSign(result, MSB24, sign);
8552   }
8553   else if(shCount >= 8){
8554     shCount -= 8;
8555     if(shCount == 1)
8556       shiftRLong(left, MSB16, result, sign);
8557     else if(shCount == 0){
8558       movLeft2Result(left, MSB16, result, LSB);
8559       movLeft2Result(left, MSB24, result, MSB16);
8560       movLeft2Result(left, MSB32, result, MSB24);
8561       pic16_addSign(result, MSB32, sign);
8562     }
8563     else{ //shcount >= 2
8564       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
8565       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
8566       /* the last shift is signed */
8567       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
8568       pic16_addSign(result, MSB32, sign);
8569     }
8570   }
8571   else{   /* 1 <= shCount <= 7 */
8572     if(shCount <= 2){
8573       shiftRLong(left, LSB, result, sign);
8574       if(shCount == 2)
8575         shiftRLong(result, LSB, result, sign);
8576     }
8577     else{
8578       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
8579       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
8580       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
8581     }
8582   }
8583 }
8584
8585 /*-----------------------------------------------------------------*/
8586 /* genRightShiftLiteral - right shifting by known count            */
8587 /*-----------------------------------------------------------------*/
8588 static void genRightShiftLiteral (operand *left,
8589                                   operand *right,
8590                                   operand *result,
8591                                   iCode *ic,
8592                                   int sign)
8593 {    
8594   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
8595   int lsize,res_size;
8596
8597   pic16_freeAsmop(right,NULL,ic,TRUE);
8598
8599   pic16_aopOp(left,ic,FALSE);
8600   pic16_aopOp(result,ic,FALSE);
8601
8602   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
8603
8604 #if VIEW_SIZE
8605   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
8606                  AOP_SIZE(left));
8607 #endif
8608
8609   lsize = pic16_getDataSize(left);
8610   res_size = pic16_getDataSize(result);
8611   /* test the LEFT size !!! */
8612
8613   /* I suppose that the left size >= result size */
8614   if(shCount == 0){
8615     while(res_size--)
8616       movLeft2Result(left, lsize, result, res_size);
8617   }
8618
8619   else if(shCount >= (lsize * 8)){
8620
8621     if(res_size == 1) {
8622       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
8623       if(sign) {
8624         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8625         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
8626       }
8627     } else {
8628
8629       if(sign) {
8630         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
8631         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
8632         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
8633         while(res_size--)
8634           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
8635
8636       } else {
8637
8638         while(res_size--)
8639           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
8640       }
8641     }
8642   } else {
8643
8644     switch (res_size) {
8645     case 1:
8646       genrshOne (result,left,shCount,sign);
8647       break;
8648
8649     case 2:
8650       genrshTwo (result,left,shCount,sign);
8651       break;
8652
8653     case 4:
8654       genrshFour (result,left,shCount,sign);
8655       break;
8656     default :
8657       break;
8658     }
8659
8660   }
8661
8662   pic16_freeAsmop(left,NULL,ic,TRUE);
8663   pic16_freeAsmop(result,NULL,ic,TRUE);
8664 }
8665
8666 /*-----------------------------------------------------------------*/
8667 /* genSignedRightShift - right shift of signed number              */
8668 /*-----------------------------------------------------------------*/
8669 static void genSignedRightShift (iCode *ic)
8670 {
8671   operand *right, *left, *result;
8672   int size, offset;
8673   //  char *l;
8674   symbol *tlbl, *tlbl1 ;
8675   pCodeOp *pctemp;
8676
8677   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
8678
8679   /* we do it the hard way put the shift count in b
8680      and loop thru preserving the sign */
8681   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8682
8683   right = IC_RIGHT(ic);
8684   left  = IC_LEFT(ic);
8685   result = IC_RESULT(ic);
8686
8687   pic16_aopOp(right,ic,FALSE);  
8688   pic16_aopOp(left,ic,FALSE);
8689   pic16_aopOp(result,ic,FALSE);
8690
8691
8692   if ( AOP_TYPE(right) == AOP_LIT) {
8693     genRightShiftLiteral (left,right,result,ic,1);
8694     return ;
8695   }
8696   /* shift count is unknown then we have to form 
8697      a loop get the loop count in B : Note: we take
8698      only the lower order byte since shifting
8699      more that 32 bits make no sense anyway, ( the
8700      largest size of an object can be only 32 bits ) */  
8701
8702   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8703   //pic16_emitcode("inc","b");
8704   //pic16_freeAsmop (right,NULL,ic,TRUE);
8705   //pic16_aopOp(left,ic,FALSE);
8706   //pic16_aopOp(result,ic,FALSE);
8707
8708   /* now move the left to the result if they are not the
8709      same */
8710   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8711       AOP_SIZE(result) > 1) {
8712
8713     size = AOP_SIZE(result);
8714     offset=0;
8715     while (size--) { 
8716       /*
8717         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8718         if (*l == '@' && IS_AOP_PREG(result)) {
8719
8720         pic16_emitcode("mov","a,%s",l);
8721         pic16_aopPut(AOP(result),"a",offset);
8722         } else
8723         pic16_aopPut(AOP(result),l,offset);
8724       */
8725       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
8726       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
8727
8728       offset++;
8729     }
8730   }
8731
8732   /* mov the highest order bit to OVR */    
8733   tlbl = newiTempLabel(NULL);
8734   tlbl1= newiTempLabel(NULL);
8735
8736   size = AOP_SIZE(result);
8737   offset = size - 1;
8738
8739   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
8740
8741   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
8742
8743   /* offset should be 0, 1 or 3 */
8744   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
8745   emitSKPNZ;
8746   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
8747
8748   pic16_emitpcode(POC_MOVWF, pctemp);
8749
8750
8751   pic16_emitpLabel(tlbl->key);
8752
8753   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8754   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8755
8756   while(--size) {
8757     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8758   }
8759
8760   pic16_emitpcode(POC_DECFSZ,  pctemp);
8761   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8762   pic16_emitpLabel(tlbl1->key);
8763
8764   pic16_popReleaseTempReg(pctemp);
8765 #if 0
8766   size = AOP_SIZE(result);
8767   offset = size - 1;
8768   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8769   pic16_emitcode("rlc","a");
8770   pic16_emitcode("mov","ov,c");
8771   /* if it is only one byte then */
8772   if (size == 1) {
8773     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8774     MOVA(l);
8775     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8776     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8777     pic16_emitcode("mov","c,ov");
8778     pic16_emitcode("rrc","a");
8779     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8780     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8781     pic16_aopPut(AOP(result),"a",0);
8782     goto release ;
8783   }
8784
8785   reAdjustPreg(AOP(result));
8786   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8787   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8788   pic16_emitcode("mov","c,ov");
8789   while (size--) {
8790     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8791     MOVA(l);
8792     pic16_emitcode("rrc","a");         
8793     pic16_aopPut(AOP(result),"a",offset--);
8794   }
8795   reAdjustPreg(AOP(result));
8796   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8797   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8798
8799  release:
8800 #endif
8801
8802   pic16_freeAsmop(left,NULL,ic,TRUE);
8803   pic16_freeAsmop(result,NULL,ic,TRUE);
8804   pic16_freeAsmop(right,NULL,ic,TRUE);
8805 }
8806
8807 /*-----------------------------------------------------------------*/
8808 /* genRightShift - generate code for right shifting                */
8809 /*-----------------------------------------------------------------*/
8810 static void genRightShift (iCode *ic)
8811 {
8812     operand *right, *left, *result;
8813     sym_link *letype ;
8814     int size, offset;
8815     char *l;
8816     symbol *tlbl, *tlbl1 ;
8817
8818     /* if signed then we do it the hard way preserve the
8819     sign bit moving it inwards */
8820     letype = getSpec(operandType(IC_LEFT(ic)));
8821     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8822
8823     if (!SPEC_USIGN(letype)) {
8824         genSignedRightShift (ic);
8825         return ;
8826     }
8827
8828     /* signed & unsigned types are treated the same : i.e. the
8829     signed is NOT propagated inwards : quoting from the
8830     ANSI - standard : "for E1 >> E2, is equivalent to division
8831     by 2**E2 if unsigned or if it has a non-negative value,
8832     otherwise the result is implementation defined ", MY definition
8833     is that the sign does not get propagated */
8834
8835     right = IC_RIGHT(ic);
8836     left  = IC_LEFT(ic);
8837     result = IC_RESULT(ic);
8838
8839     pic16_aopOp(right,ic,FALSE);
8840
8841     /* if the shift count is known then do it 
8842     as efficiently as possible */
8843     if (AOP_TYPE(right) == AOP_LIT) {
8844         genRightShiftLiteral (left,right,result,ic, 0);
8845         return ;
8846     }
8847
8848     /* shift count is unknown then we have to form 
8849     a loop get the loop count in B : Note: we take
8850     only the lower order byte since shifting
8851     more that 32 bits make no sense anyway, ( the
8852     largest size of an object can be only 32 bits ) */  
8853
8854     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8855     pic16_emitcode("inc","b");
8856     pic16_aopOp(left,ic,FALSE);
8857     pic16_aopOp(result,ic,FALSE);
8858
8859     /* now move the left to the result if they are not the
8860     same */
8861     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8862         AOP_SIZE(result) > 1) {
8863
8864         size = AOP_SIZE(result);
8865         offset=0;
8866         while (size--) {
8867             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8868             if (*l == '@' && IS_AOP_PREG(result)) {
8869
8870                 pic16_emitcode("mov","a,%s",l);
8871                 pic16_aopPut(AOP(result),"a",offset);
8872             } else
8873                 pic16_aopPut(AOP(result),l,offset);
8874             offset++;
8875         }
8876     }
8877
8878     tlbl = newiTempLabel(NULL);
8879     tlbl1= newiTempLabel(NULL);
8880     size = AOP_SIZE(result);
8881     offset = size - 1;
8882
8883     /* if it is only one byte then */
8884     if (size == 1) {
8885
8886       tlbl = newiTempLabel(NULL);
8887       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8888         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8889         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8890       }
8891
8892       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8893       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8894       pic16_emitpLabel(tlbl->key);
8895       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8896       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8897       emitSKPC;
8898       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8899
8900       goto release ;
8901     }
8902
8903     reAdjustPreg(AOP(result));
8904     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8905     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8906     CLRC;
8907     while (size--) {
8908         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8909         MOVA(l);
8910         pic16_emitcode("rrc","a");         
8911         pic16_aopPut(AOP(result),"a",offset--);
8912     }
8913     reAdjustPreg(AOP(result));
8914
8915     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8916     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8917
8918 release:
8919     pic16_freeAsmop(left,NULL,ic,TRUE);
8920     pic16_freeAsmop (right,NULL,ic,TRUE);
8921     pic16_freeAsmop(result,NULL,ic,TRUE);
8922 }
8923
8924 /*-----------------------------------------------------------------*/
8925 /* genUnpackBits - generates code for unpacking bits               */
8926 /*-----------------------------------------------------------------*/
8927 static void genUnpackBits (operand *result, char *rname, int ptype)
8928 {    
8929     int shCnt ;
8930     int rlen = 0 ;
8931     sym_link *etype;
8932     int offset = 0 ;
8933
8934         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8935         etype = getSpec(operandType(result));
8936
8937         /* read the first byte  */
8938         switch (ptype) {
8939                 case POINTER:
8940                 case IPOINTER:
8941                 case PPOINTER:
8942                 case FPOINTER:
8943                 case GPOINTER:
8944                         pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
8945                         break;
8946                 case CPOINTER:
8947                         pic16_emitcode("clr","a");
8948                         pic16_emitcode("movc","a","@a+dptr");
8949                         break;
8950         }
8951         
8952
8953         /* if we have bitdisplacement then it fits   */
8954         /* into this byte completely or if length is */
8955         /* less than a byte                          */
8956         if ((shCnt = SPEC_BSTR(etype)) || 
8957                 (SPEC_BLEN(etype) <= 8))  {
8958
8959                 /* shift right acc */
8960                 AccRsh(shCnt, 0);
8961
8962                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
8963                         (((unsigned char) -1)>>(8 - SPEC_BLEN(etype))) & SRMask[ shCnt ]));
8964
8965 /* VR -- normally I would use the following, but since we use the hack,
8966  * to avoid the masking from AccRsh, why not mask it right now? */
8967
8968 /*
8969                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(((unsigned char) -1)>>(8 - SPEC_BLEN(etype))));
8970 */
8971
8972                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
8973           return ;
8974         }
8975
8976
8977
8978         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
8979         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
8980         exit(-1);
8981
8982     /* bit field did not fit in a byte  */
8983     rlen = SPEC_BLEN(etype) - 8;
8984     pic16_aopPut(AOP(result),"a",offset++);
8985
8986     while (1)  {
8987
8988         switch (ptype) {
8989         case POINTER:
8990         case IPOINTER:
8991             pic16_emitcode("inc","%s",rname);
8992             pic16_emitcode("mov","a,@%s",rname);
8993             break;
8994             
8995         case PPOINTER:
8996             pic16_emitcode("inc","%s",rname);
8997             pic16_emitcode("movx","a,@%s",rname);
8998             break;
8999
9000         case FPOINTER:
9001             pic16_emitcode("inc","dptr");
9002             pic16_emitcode("movx","a,@dptr");
9003             break;
9004             
9005         case CPOINTER:
9006             pic16_emitcode("clr","a");
9007             pic16_emitcode("inc","dptr");
9008             pic16_emitcode("movc","a","@a+dptr");
9009             break;
9010             
9011         case GPOINTER:
9012             pic16_emitcode("inc","dptr");
9013             pic16_emitcode("lcall","__gptrget");
9014             break;
9015         }
9016
9017         rlen -= 8;            
9018         /* if we are done */
9019         if ( rlen <= 0 )
9020             break ;
9021         
9022         pic16_aopPut(AOP(result),"a",offset++);
9023                               
9024     }
9025     
9026     if (rlen) {
9027         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
9028         pic16_aopPut(AOP(result),"a",offset);          
9029     }
9030     
9031     return ;
9032 }
9033
9034
9035 static void genDataPointerGet(operand *left,
9036                               operand *result,
9037                               iCode *ic)
9038 {
9039   int size, offset = 0, leoffset=0 ;
9040
9041         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9042         pic16_aopOp(result, ic, FALSE);
9043
9044         size = AOP_SIZE(result);
9045 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9046
9047
9048 #if 0
9049         /* The following tests may save a redudant movff instruction when
9050          * accessing unions */
9051          
9052         /* if they are the same */
9053         if (operandsEqu (left, result)) {
9054                 DEBUGpic16_emitcode("; ***", "left and result operands are equ/same");
9055                 goto release;
9056         }
9057 #endif
9058
9059 #if 0
9060         /* if they are the same registers */
9061         if (pic16_sameRegs(AOP(left),AOP(result))) {
9062                 DEBUGpic16_emitcode("; ***", "left and result registers are same");
9063                 goto release;
9064         }
9065 #endif
9066
9067 #if 0
9068         if ( AOP_TYPE(left) == AOP_PCODE) {
9069                 fprintf(stderr,"genDataPointerGet   %s, %d\n",
9070                                 AOP(left)->aopu.pcop->name,
9071                                 (AOP(left)->aopu.pcop->type == PO_DIR)?
9072                                 PCOR(AOP(left)->aopu.pcop)->instance:
9073                                 PCOI(AOP(left)->aopu.pcop)->offset);
9074         }
9075 #endif
9076
9077         if(AOP(left)->aopu.pcop->type == PO_DIR)
9078                 leoffset=PCOR(AOP(left)->aopu.pcop)->instance;
9079
9080         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9081
9082         while (size--) {
9083                 DEBUGpic16_emitcode("; ***", "%s loop offset=%d leoffset=%d", __FUNCTION__, offset, leoffset);
9084                 
9085                 if(AOP(result)->aopu.pcop->type == PO_IMMEDIATE
9086                         || AOP(left)->aopu.pcop->type == PO_IMMEDIATE) {
9087                         mov2w(AOP(left), offset); // patch 8
9088                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
9089                 } else {
9090                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
9091                                 pic16_popGet(AOP(left), offset), //patch 8
9092                                 pic16_popGet(AOP(result), offset)));
9093                 }
9094
9095                 offset++;
9096                 leoffset++;
9097         }
9098
9099 //release:
9100     pic16_freeAsmop(result,NULL,ic,TRUE);
9101 }
9102
9103 void pic16_loadFSR0(operand *op)
9104 {
9105         pic16_emitpcode(POC_LFSR, pic16_popGetLit2(0, pic16_popGet(AOP(op), 0)));
9106 }
9107
9108
9109 /*-----------------------------------------------------------------*/
9110 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
9111 /*-----------------------------------------------------------------*/
9112 static void genNearPointerGet (operand *left, 
9113                                operand *result, 
9114                                iCode *ic)
9115 {
9116     asmop *aop = NULL;
9117     //regs *preg = NULL ;
9118     sym_link *rtype, *retype;
9119     sym_link *ltype = operandType(left);    
9120
9121         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9122         rtype = operandType(result);
9123         retype= getSpec(rtype);
9124     
9125         pic16_aopOp(left,ic,FALSE);
9126
9127         pic16_DumpOp("(left)",left);
9128         pic16_DumpOp("(result)",result);
9129
9130         /* if left is rematerialisable and
9131          * result is not bit variable type and
9132          * the left is pointer to data space i.e
9133          * lower 128 bytes of space */
9134         if (AOP_TYPE(left) == AOP_PCODE
9135                 && !IS_BITFIELD(retype)
9136                 && DCL_TYPE(ltype) == POINTER) {
9137
9138                 genDataPointerGet (left,result,ic);
9139                 pic16_freeAsmop(left, NULL, ic, TRUE);
9140           return ;
9141         }
9142     
9143         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9144
9145         /* if the value is already in a pointer register
9146          * then don't need anything more */
9147         if (!AOP_INPREG(AOP(left))) {
9148                 /* otherwise get a free pointer register */
9149                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9150                 
9151                 /* VR -- the whole concept is to load FSR0 with the address of the symbol */
9152                 if( (AOP_TYPE(left) == AOP_PCODE) 
9153                         && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9154                                 || (AOP(left)->aopu.pcop->type == PO_DIR))) // patch 10
9155                 {
9156                         pic16_loadFSR0( left );  // patch 10
9157                 } else {
9158                         // set up FSR0 with address from left
9159                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9160                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9161                 }
9162         }
9163 //       else
9164 //      rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9165     
9166         pic16_aopOp (result,ic,FALSE);
9167     
9168       /* if bitfield then unpack the bits */
9169     if (IS_BITFIELD(retype)) 
9170         genUnpackBits (result, NULL, POINTER);
9171     else {
9172         /* we have can just get the values */
9173       int size = AOP_SIZE(result);
9174       int offset = 0;   
9175         
9176       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9177
9178
9179         /* fsr0 is loaded already -- VR */
9180 //      pic16_loadFSR0( left );
9181
9182 //      pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
9183 //      pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9184       while(size--) {
9185
9186         if(size) {
9187                 pic16_emitpcode(POC_MOVFF,
9188                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0),
9189                                 pic16_popGet(AOP(result), offset++)));
9190         } else {
9191                 pic16_emitpcode(POC_MOVFF,
9192                         pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0),
9193                                 pic16_popGet(AOP(result), offset++)));
9194         }
9195       }
9196 #if 0
9197 //      pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_postinc0));
9198 //      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
9199         if(size)
9200           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9201 #endif
9202 /*
9203         while (size--) {
9204             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
9205
9206                 pic16_emitcode("mov","a,@%s",rname);
9207                 pic16_aopPut(AOP(result),"a",offset);
9208             } else {
9209                 sprintf(buffer,"@%s",rname);
9210                 pic16_aopPut(AOP(result),buffer,offset);
9211             }
9212             offset++ ;
9213             if (size)
9214                 pic16_emitcode("inc","%s",rname);
9215         }
9216 */
9217     }
9218
9219     /* now some housekeeping stuff */
9220     if (aop) {
9221         /* we had to allocate for this iCode */
9222     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9223         pic16_freeAsmop(NULL,aop,ic,TRUE);
9224     } else { 
9225         /* we did not allocate which means left
9226            already in a pointer register, then
9227            if size > 0 && this could be used again
9228            we have to point it back to where it 
9229            belongs */
9230     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9231         if (AOP_SIZE(result) > 1 &&
9232             !OP_SYMBOL(left)->remat &&
9233             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9234               ic->depth )) {
9235 //          int size = AOP_SIZE(result) - 1;
9236 //          while (size--)
9237 //              pic16_emitcode("dec","%s",rname);
9238         }
9239     }
9240
9241     /* done */
9242     pic16_freeAsmop(left,NULL,ic,TRUE);
9243     pic16_freeAsmop(result,NULL,ic,TRUE);
9244      
9245 }
9246
9247 /*-----------------------------------------------------------------*/
9248 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
9249 /*-----------------------------------------------------------------*/
9250 static void genPagedPointerGet (operand *left, 
9251                                operand *result, 
9252                                iCode *ic)
9253 {
9254     asmop *aop = NULL;
9255     regs *preg = NULL ;
9256     char *rname ;
9257     sym_link *rtype, *retype;    
9258
9259     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9260
9261     rtype = operandType(result);
9262     retype= getSpec(rtype);
9263     
9264     pic16_aopOp(left,ic,FALSE);
9265
9266   /* if the value is already in a pointer register
9267        then don't need anything more */
9268     if (!AOP_INPREG(AOP(left))) {
9269         /* otherwise get a free pointer register */
9270         aop = newAsmop(0);
9271         preg = getFreePtr(ic,&aop,FALSE);
9272         pic16_emitcode("mov","%s,%s",
9273                 preg->name,
9274                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
9275         rname = preg->name ;
9276     } else
9277         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
9278     
9279     pic16_freeAsmop(left,NULL,ic,TRUE);
9280     pic16_aopOp (result,ic,FALSE);
9281
9282     /* if bitfield then unpack the bits */
9283     if (IS_BITFIELD(retype)) 
9284         genUnpackBits (result,rname,PPOINTER);
9285     else {
9286         /* we have can just get the values */
9287         int size = AOP_SIZE(result);
9288         int offset = 0 ;        
9289         
9290         while (size--) {
9291             
9292             pic16_emitcode("movx","a,@%s",rname);
9293             pic16_aopPut(AOP(result),"a",offset);
9294             
9295             offset++ ;
9296             
9297             if (size)
9298                 pic16_emitcode("inc","%s",rname);
9299         }
9300     }
9301
9302     /* now some housekeeping stuff */
9303     if (aop) {
9304         /* we had to allocate for this iCode */
9305         pic16_freeAsmop(NULL,aop,ic,TRUE);
9306     } else { 
9307         /* we did not allocate which means left
9308            already in a pointer register, then
9309            if size > 0 && this could be used again
9310            we have to point it back to where it 
9311            belongs */
9312         if (AOP_SIZE(result) > 1 &&
9313             !OP_SYMBOL(left)->remat &&
9314             ( OP_SYMBOL(left)->liveTo > ic->seq ||
9315               ic->depth )) {
9316             int size = AOP_SIZE(result) - 1;
9317             while (size--)
9318                 pic16_emitcode("dec","%s",rname);
9319         }
9320     }
9321
9322     /* done */
9323     pic16_freeAsmop(result,NULL,ic,TRUE);
9324     
9325         
9326 }
9327
9328 /*-----------------------------------------------------------------*/
9329 /* genFarPointerGet - gget value from far space                    */
9330 /*-----------------------------------------------------------------*/
9331 static void genFarPointerGet (operand *left,
9332                               operand *result, iCode *ic)
9333 {
9334     int size, offset ;
9335     sym_link *retype = getSpec(operandType(result));
9336
9337     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9338
9339     pic16_aopOp(left,ic,FALSE);
9340
9341     /* if the operand is already in dptr 
9342     then we do nothing else we move the value to dptr */
9343     if (AOP_TYPE(left) != AOP_STR) {
9344         /* if this is remateriazable */
9345         if (AOP_TYPE(left) == AOP_IMMD)
9346             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9347         else { /* we need to get it byte by byte */
9348             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9349             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9350             if (options.model == MODEL_FLAT24)
9351             {
9352                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9353             }
9354         }
9355     }
9356     /* so dptr know contains the address */
9357     pic16_freeAsmop(left,NULL,ic,TRUE);
9358     pic16_aopOp(result,ic,FALSE);
9359
9360     /* if bit then unpack */
9361     if (IS_BITFIELD(retype)) 
9362         genUnpackBits(result,"dptr",FPOINTER);
9363     else {
9364         size = AOP_SIZE(result);
9365         offset = 0 ;
9366
9367         while (size--) {
9368             pic16_emitcode("movx","a,@dptr");
9369             pic16_aopPut(AOP(result),"a",offset++);
9370             if (size)
9371                 pic16_emitcode("inc","dptr");
9372         }
9373     }
9374
9375     pic16_freeAsmop(result,NULL,ic,TRUE);
9376 }
9377 #if 0
9378 /*-----------------------------------------------------------------*/
9379 /* genCodePointerGet - get value from code space                  */
9380 /*-----------------------------------------------------------------*/
9381 static void genCodePointerGet (operand *left,
9382                                 operand *result, iCode *ic)
9383 {
9384     int size, offset ;
9385     sym_link *retype = getSpec(operandType(result));
9386
9387     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9388
9389     pic16_aopOp(left,ic,FALSE);
9390
9391     /* if the operand is already in dptr 
9392     then we do nothing else we move the value to dptr */
9393     if (AOP_TYPE(left) != AOP_STR) {
9394         /* if this is remateriazable */
9395         if (AOP_TYPE(left) == AOP_IMMD)
9396             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
9397         else { /* we need to get it byte by byte */
9398             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
9399             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
9400             if (options.model == MODEL_FLAT24)
9401             {
9402                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
9403             }
9404         }
9405     }
9406     /* so dptr know contains the address */
9407     pic16_freeAsmop(left,NULL,ic,TRUE);
9408     pic16_aopOp(result,ic,FALSE);
9409
9410     /* if bit then unpack */
9411     if (IS_BITFIELD(retype)) 
9412         genUnpackBits(result,"dptr",CPOINTER);
9413     else {
9414         size = AOP_SIZE(result);
9415         offset = 0 ;
9416
9417         while (size--) {
9418             pic16_emitcode("clr","a");
9419             pic16_emitcode("movc","a,@a+dptr");
9420             pic16_aopPut(AOP(result),"a",offset++);
9421             if (size)
9422                 pic16_emitcode("inc","dptr");
9423         }
9424     }
9425
9426     pic16_freeAsmop(result,NULL,ic,TRUE);
9427 }
9428 #endif
9429 /*-----------------------------------------------------------------*/
9430 /* genGenPointerGet - gget value from generic pointer space        */
9431 /*-----------------------------------------------------------------*/
9432 static void genGenPointerGet (operand *left,
9433                               operand *result, iCode *ic)
9434 {
9435   int size, offset, lit;
9436   sym_link *retype = getSpec(operandType(result));
9437
9438         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9439         pic16_aopOp(left,ic,FALSE);
9440         pic16_aopOp(result,ic,FALSE);
9441         size = AOP_SIZE(result);
9442
9443         DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9444
9445         if (AOP_TYPE(left) == AOP_IMMD) { // do we ever get here? (untested!)
9446
9447                 lit = (unsigned)floatFromVal(AOP(left)->aopu.aop_lit);
9448                 // load FSR0 from immediate
9449                 pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
9450
9451 //              pic16_loadFSR0( left );
9452
9453                 offset = 0;
9454                 while(size--) {
9455                         if(size) {
9456                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9457                         } else {
9458                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9459                         }
9460                         offset++;
9461                 }
9462                 goto release;
9463
9464         }
9465         else { /* we need to get it byte by byte */
9466                 // set up FSR0 with address from left
9467                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
9468                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
9469
9470                 offset = 0 ;
9471
9472                 while(size--) {
9473                         if(size) {
9474                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_postinc0), pic16_popGet(AOP(result),offset)));
9475                         } else {
9476                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_indf0), pic16_popGet(AOP(result),offset)));
9477                         }
9478                         offset++;
9479                 }
9480                 goto release;
9481         }
9482
9483   /* if bit then unpack */
9484         if (IS_BITFIELD(retype)) 
9485                 genUnpackBits(result,"BAD",GPOINTER);
9486
9487         release:
9488         pic16_freeAsmop(left,NULL,ic,TRUE);
9489         pic16_freeAsmop(result,NULL,ic,TRUE);
9490
9491 }
9492
9493 /*-----------------------------------------------------------------*/
9494 /* genConstPointerGet - get value from const generic pointer space */
9495 /*-----------------------------------------------------------------*/
9496 static void genConstPointerGet (operand *left,
9497                                 operand *result, iCode *ic)
9498 {
9499   //sym_link *retype = getSpec(operandType(result));
9500   // symbol *albl = newiTempLabel(NULL);        // patch 15
9501   // symbol *blbl = newiTempLabel(NULL);        //
9502   // PIC_OPCODE poc;                            // patch 15
9503   int size;
9504   int offset = 0;
9505
9506   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9507   pic16_aopOp(left,ic,FALSE);
9508   pic16_aopOp(result,ic,TRUE);
9509   size = AOP_SIZE(result);
9510
9511   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
9512
9513   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
9514 #if 0                                                                   // patch 15
9515   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
9516   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
9517   pic16_emitpLabel(albl->key);
9518
9519   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
9520     
9521   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
9522   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
9523   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
9524   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
9525   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
9526
9527   pic16_emitpLabel(blbl->key);
9528
9529   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
9530 #endif                                                                  // patch 15
9531
9532
9533   // set up table pointer
9534   if( (AOP_TYPE(left) == AOP_PCODE) 
9535       && ((AOP(left)->aopu.pcop->type == PO_IMMEDIATE)
9536           || (AOP(left)->aopu.pcop->type == PO_DIR)))                   // patch 15 ......
9537     {
9538       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
9539       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrl));
9540       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),1));
9541       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptrh));
9542       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),2));
9543       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_tblptru));
9544     }
9545   else
9546     {
9547       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),0), pic16_popCopyReg(&pic16_pc_tblptrl)));
9548       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),1), pic16_popCopyReg(&pic16_pc_tblptrh)));
9549       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(left),2), pic16_popCopyReg(&pic16_pc_tblptru)));
9550     }
9551
9552
9553   while(size--)
9554     {
9555       pic16_emitpcodeNULLop(POC_TBLRD_POSTINC);
9556       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_tablat), pic16_popGet(AOP(result),offset)));
9557       offset++;
9558     }
9559                                                                         // .... patch 15
9560   pic16_freeAsmop(left,NULL,ic,TRUE);
9561   pic16_freeAsmop(result,NULL,ic,TRUE);
9562
9563 }
9564 /*-----------------------------------------------------------------*/
9565 /* genPointerGet - generate code for pointer get                   */
9566 /*-----------------------------------------------------------------*/
9567 static void genPointerGet (iCode *ic)
9568 {
9569     operand *left, *result ;
9570     sym_link *type, *etype;
9571     int p_type;
9572
9573     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9574
9575     left = IC_LEFT(ic);
9576     result = IC_RESULT(ic) ;
9577
9578     /* depending on the type of pointer we need to
9579     move it to the correct pointer register */
9580     type = operandType(left);
9581     etype = getSpec(type);
9582
9583 #if 0
9584     if (IS_PTR_CONST(type))
9585 #else
9586     if (IS_CODEPTR(type))
9587 #endif
9588       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
9589
9590     /* if left is of type of pointer then it is simple */
9591     if (IS_PTR(type) && !IS_FUNC(type->next)) 
9592         p_type = DCL_TYPE(type);
9593     else {
9594         /* we have to go by the storage class */
9595         p_type = PTR_TYPE(SPEC_OCLS(etype));
9596
9597         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
9598
9599         if (SPEC_OCLS(etype)->codesp ) {
9600           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
9601           //p_type = CPOINTER ; 
9602         }
9603         else
9604             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
9605               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
9606                /*p_type = FPOINTER ;*/ 
9607             else
9608                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
9609                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
9610 /*                  p_type = PPOINTER; */
9611                 else
9612                     if (SPEC_OCLS(etype) == idata )
9613                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
9614 /*                      p_type = IPOINTER; */
9615                     else
9616                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
9617 /*                      p_type = POINTER ; */
9618     }
9619
9620     /* now that we have the pointer type we assign
9621     the pointer values */
9622     switch (p_type) {
9623
9624     case POINTER:       
9625     case IPOINTER:
9626         genNearPointerGet (left,result,ic);
9627         break;
9628
9629     case PPOINTER:
9630         genPagedPointerGet(left,result,ic);
9631         break;
9632
9633     case FPOINTER:
9634         genFarPointerGet (left,result,ic);
9635         break;
9636
9637     case CPOINTER:
9638         genConstPointerGet (left,result,ic);
9639         //pic16_emitcodePointerGet (left,result,ic);
9640         break;
9641
9642     case GPOINTER:
9643 #if 0
9644       if (IS_PTR_CONST(type))
9645         genConstPointerGet (left,result,ic);
9646       else
9647 #endif
9648         genGenPointerGet (left,result,ic);
9649       break;
9650     }
9651
9652 }
9653
9654 /*-----------------------------------------------------------------*/
9655 /* genPackBits - generates code for packed bit storage             */
9656 /*-----------------------------------------------------------------*/
9657 static void genPackBits (sym_link    *etype ,
9658                          operand *right ,
9659                          char *rname, int p_type)
9660 {
9661   int shCnt = 0 ;
9662   int offset = 0  ;
9663   int rLen = 0 ;
9664   int blen, bstr ;   
9665   char *l ;
9666
9667         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9668         blen = SPEC_BLEN(etype);
9669         bstr = SPEC_BSTR(etype);
9670
9671         if(AOP_TYPE(right) == AOP_LIT) {
9672                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right), 0));
9673                 offset++;
9674         } else
9675                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset++));
9676
9677 /*      l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9678         MOVA(l);   
9679 */
9680         /* if the bit lenth is less than or    */
9681         /* it exactly fits a byte then         */
9682         if((shCnt=SPEC_BSTR(etype))
9683                 || SPEC_BLEN(etype) <= 8 )  {
9684
9685                 /* shift left acc */
9686                 AccLsh(shCnt);
9687
9688                 /* using PRODL as a temporary register here */
9689                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_prodl));
9690
9691                 switch (p_type) {
9692                         case FPOINTER:
9693                         case POINTER:
9694                         case GPOINTER:
9695                                 pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_indf0));
9696 //                              pic16_emitcode ("mov","b,a");
9697 //                              pic16_emitcode("mov","a,@%s",rname);
9698                                 break;
9699                 }
9700 #if 1
9701                 pic16_emitpcode(POC_ANDLW, pic16_popGetLit(
9702                         (unsigned char)((unsigned char)(0xff << (blen+bstr)) |
9703                                         (unsigned char)(0xff >> (8-bstr))) ));
9704                 pic16_emitpcode(POC_IORFW, pic16_popCopyReg(&pic16_pc_prodl));
9705                 pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9706 #endif
9707
9708 #if 0
9709                 pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
9710                                         ((unsigned char)(0xFF << (blen+bstr)) | 
9711                                         (unsigned char)(0xFF >> (8-bstr)) ) );
9712                 pic16_emitcode ("orl","a,b");
9713                 if (p_type == GPOINTER)
9714                         pic16_emitcode("pop","b");
9715
9716                 
9717                 switch (p_type) {
9718                         case POINTER:
9719                                 pic16_emitcode("mov","@%s,a",rname);
9720                                 break;
9721                         case FPOINTER:
9722                                 pic16_emitcode("movx","@dptr,a");
9723                                 break;
9724                         case GPOINTER:
9725                                 DEBUGpic16_emitcode(";lcall","__gptrput");
9726                                 break;
9727                 }
9728 #endif
9729
9730           return;
9731         }
9732
9733
9734         fprintf(stderr, "SDCC pic16 port error: the port currently does not support\n");
9735         fprintf(stderr, "bitfields of size >=8. Instead of generating wrong code, bailling out...\n");
9736         exit(-1);
9737
9738
9739     /* if we r done */
9740     if ( SPEC_BLEN(etype) <= 8 )
9741         return ;
9742
9743     pic16_emitcode("inc","%s",rname);
9744     rLen = SPEC_BLEN(etype) ;     
9745
9746
9747
9748     /* now generate for lengths greater than one byte */
9749     while (1) {
9750
9751         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
9752
9753         rLen -= 8 ;
9754         if (rLen <= 0 )
9755             break ;
9756
9757         switch (p_type) {
9758             case POINTER:
9759                 if (*l == '@') {
9760                     MOVA(l);
9761                     pic16_emitcode("mov","@%s,a",rname);
9762                 } else
9763                     pic16_emitcode("mov","@%s,%s",rname,l);
9764                 break;
9765
9766             case FPOINTER:
9767                 MOVA(l);
9768                 pic16_emitcode("movx","@dptr,a");
9769                 break;
9770
9771             case GPOINTER:
9772                 MOVA(l);
9773                 DEBUGpic16_emitcode(";lcall","__gptrput");
9774                 break;  
9775         }   
9776         pic16_emitcode ("inc","%s",rname);
9777     }
9778
9779     MOVA(l);
9780
9781     /* last last was not complete */
9782     if (rLen)   {
9783         /* save the byte & read byte */
9784         switch (p_type) {
9785             case POINTER:
9786                 pic16_emitcode ("mov","b,a");
9787                 pic16_emitcode("mov","a,@%s",rname);
9788                 break;
9789
9790             case FPOINTER:
9791                 pic16_emitcode ("mov","b,a");
9792                 pic16_emitcode("movx","a,@dptr");
9793                 break;
9794
9795             case GPOINTER:
9796                 pic16_emitcode ("push","b");
9797                 pic16_emitcode ("push","acc");
9798                 pic16_emitcode ("lcall","__gptrget");
9799                 pic16_emitcode ("pop","b");
9800                 break;
9801         }
9802
9803         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
9804         pic16_emitcode ("orl","a,b");
9805     }
9806
9807     if (p_type == GPOINTER)
9808         pic16_emitcode("pop","b");
9809
9810     switch (p_type) {
9811
9812     case POINTER:
9813         pic16_emitcode("mov","@%s,a",rname);
9814         break;
9815         
9816     case FPOINTER:
9817         pic16_emitcode("movx","@dptr,a");
9818         break;
9819         
9820     case GPOINTER:
9821         DEBUGpic16_emitcode(";lcall","__gptrput");
9822         break;                  
9823     }
9824 }
9825 /*-----------------------------------------------------------------*/
9826 /* genDataPointerSet - remat pointer to data space                 */
9827 /*-----------------------------------------------------------------*/
9828 static void genDataPointerSet(operand *right,
9829                               operand *result,
9830                               iCode *ic)
9831 {
9832     int size, offset = 0, resoffset=0 ;
9833
9834     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9835     pic16_aopOp(right,ic,FALSE);
9836
9837     size = AOP_SIZE(right);
9838
9839 //      fprintf(stderr, "%s:%d size= %d\n", __FILE__, __LINE__, size);
9840
9841 #if 0
9842     if ( AOP_TYPE(result) == AOP_PCODE) {
9843       fprintf(stderr,"genDataPointerSet   %s, %d\n",
9844               AOP(result)->aopu.pcop->name,
9845                 (AOP(result)->aopu.pcop->type == PO_DIR)?
9846               PCOR(AOP(result)->aopu.pcop)->instance:
9847               PCOI(AOP(result)->aopu.pcop)->offset);
9848     }
9849 #endif
9850
9851         if(AOP(result)->aopu.pcop->type == PO_DIR)
9852                 resoffset=PCOR(AOP(result)->aopu.pcop)->instance;
9853
9854         while (size--) {
9855                 if (AOP_TYPE(right) == AOP_LIT) {
9856                   unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9857
9858                         lit = lit >> (8*offset);
9859                         if(lit&0xff) {
9860                                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
9861                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // pstch 8
9862                         } else {
9863                                 pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset)); // patch 8
9864                         }
9865                 } else {
9866                         mov2w(AOP(right), offset);
9867                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset)); // patch 8
9868                 }
9869                 offset++;
9870                 resoffset++;
9871         }
9872
9873     pic16_freeAsmop(right,NULL,ic,TRUE);
9874 }
9875
9876
9877
9878 /*-----------------------------------------------------------------*/
9879 /* genNearPointerSet - pic16_emitcode for near pointer put         */
9880 /*-----------------------------------------------------------------*/
9881 static void genNearPointerSet (operand *right,
9882                                operand *result, 
9883                                iCode *ic)
9884 {
9885   asmop *aop = NULL;
9886   char *l;
9887   sym_link *retype;
9888   sym_link *ptype = operandType(result);
9889   sym_link *resetype;
9890     
9891         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9892         retype= getSpec(operandType(right));
9893         resetype = getSpec(operandType(result));
9894   
9895         pic16_aopOp(result,ic,FALSE);
9896     
9897         /* if the result is rematerializable &
9898          * in data space & not a bit variable */
9899         
9900         /* and result is not a bit variable */
9901         if (AOP_TYPE(result) == AOP_PCODE
9902 //              && AOP_TYPE(result) == AOP_IMMD
9903                 && DCL_TYPE(ptype) == POINTER
9904                 && !IS_BITFIELD(retype)
9905                 && !IS_BITFIELD(resetype)) {
9906
9907                 genDataPointerSet (right,result,ic);
9908                 pic16_freeAsmop(result,NULL,ic,TRUE);
9909           return;
9910         }
9911
9912         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9913         pic16_aopOp(right,ic,FALSE);
9914         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9915
9916         /* if the value is already in a pointer register
9917          * then don't need anything more */
9918         if (!AOP_INPREG(AOP(result))) {
9919                 /* otherwise get a free pointer register */
9920                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9921
9922                 if( (AOP_TYPE(result) == AOP_PCODE) 
9923                         && ((AOP(result)->aopu.pcop->type == PO_IMMEDIATE)
9924                                 || (AOP(result)->aopu.pcop->type == PO_DIR))) // patch 10
9925                 {
9926                         pic16_loadFSR0( result );  // patch 10
9927                 } else {
9928                         // set up FSR0 with address of result
9929                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l))); // patch 10
9930                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h))); // patch 10
9931                 }
9932
9933         }
9934 //      else
9935 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9936
9937         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9938
9939         /* if bitfield then unpack the bits */
9940         if (IS_BITFIELD(resetype)) {
9941                 genPackBits (resetype, right, NULL, POINTER);
9942         } else {
9943                 /* we have can just get the values */
9944           int size = AOP_SIZE(right);
9945           int offset = 0 ;    
9946
9947                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9948                 while (size--) {
9949                         l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9950                         if (*l == '@' ) {
9951                                 //MOVA(l);
9952                                 //pic16_emitcode("mov","@%s,a",rname);
9953                                 pic16_emitcode("movf","indf0,w ;1");
9954                         } else {
9955
9956                                 if (AOP_TYPE(right) == AOP_LIT) {                                                       // patch 10
9957                                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));                    // 
9958                                         if (size) {                                                                     // 
9959                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));        // 
9960                                         } else {                                                                        // 
9961                                                 pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));           // 
9962                                         }                                                                               // 
9963                                 } else { // no literal                                                                  // 
9964                                         if(size) {                                                                      // 
9965                                                 pic16_emitpcode(POC_MOVFF,                                              // 
9966                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
9967                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));         // 
9968                                         } else {                                                                        // 
9969                                                 pic16_emitpcode(POC_MOVFF,                                              // 
9970                                                                 pic16_popGet2p(pic16_popGet(AOP(right),offset),         // 
9971                                                                         pic16_popCopyReg(&pic16_pc_indf0)));            //
9972                                         }                                                                               //
9973                                 }                                                                                       // patch 10
9974                         }
9975                         offset++;
9976                 }
9977         }
9978
9979         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9980         /* now some housekeeping stuff */
9981         if (aop) {
9982                 /* we had to allocate for this iCode */
9983                 pic16_freeAsmop(NULL,aop,ic,TRUE);
9984         } else { 
9985                 /* we did not allocate which means left
9986                  * already in a pointer register, then
9987                  * if size > 0 && this could be used again
9988                  * we have to point it back to where it 
9989                  * belongs */
9990                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9991                 if (AOP_SIZE(right) > 1
9992                         && !OP_SYMBOL(result)->remat
9993                         && ( OP_SYMBOL(result)->liveTo > ic->seq
9994                                 || ic->depth )) {
9995
9996                   int size = AOP_SIZE(right) - 1;
9997
9998                         while (size--)
9999                                 pic16_emitcode("decf","fsr0,f");
10000                         //pic16_emitcode("dec","%s",rname);
10001                 }
10002         }
10003
10004         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10005         /* done */
10006 //release:
10007         pic16_freeAsmop(right,NULL,ic,TRUE);
10008         pic16_freeAsmop(result,NULL,ic,TRUE);
10009 }
10010
10011 /*-----------------------------------------------------------------*/
10012 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
10013 /*-----------------------------------------------------------------*/
10014 static void genPagedPointerSet (operand *right,
10015                                operand *result, 
10016                                iCode *ic)
10017 {
10018     asmop *aop = NULL;
10019     regs *preg = NULL ;
10020     char *rname , *l;
10021     sym_link *retype;
10022        
10023     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10024
10025     retype= getSpec(operandType(right));
10026     
10027     pic16_aopOp(result,ic,FALSE);
10028     
10029     /* if the value is already in a pointer register
10030        then don't need anything more */
10031     if (!AOP_INPREG(AOP(result))) {
10032         /* otherwise get a free pointer register */
10033         aop = newAsmop(0);
10034         preg = getFreePtr(ic,&aop,FALSE);
10035         pic16_emitcode("mov","%s,%s",
10036                 preg->name,
10037                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
10038         rname = preg->name ;
10039     } else
10040         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10041     
10042     pic16_freeAsmop(result,NULL,ic,TRUE);
10043     pic16_aopOp (right,ic,FALSE);
10044
10045     /* if bitfield then unpack the bits */
10046     if (IS_BITFIELD(retype)) 
10047         genPackBits (retype,right,rname,PPOINTER);
10048     else {
10049         /* we have can just get the values */
10050         int size = AOP_SIZE(right);
10051         int offset = 0 ;        
10052         
10053         while (size--) {
10054             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
10055             
10056             MOVA(l);
10057             pic16_emitcode("movx","@%s,a",rname);
10058
10059             if (size)
10060                 pic16_emitcode("inc","%s",rname);
10061
10062             offset++;
10063         }
10064     }
10065     
10066     /* now some housekeeping stuff */
10067     if (aop) {
10068         /* we had to allocate for this iCode */
10069         pic16_freeAsmop(NULL,aop,ic,TRUE);
10070     } else { 
10071         /* we did not allocate which means left
10072            already in a pointer register, then
10073            if size > 0 && this could be used again
10074            we have to point it back to where it 
10075            belongs */
10076         if (AOP_SIZE(right) > 1 &&
10077             !OP_SYMBOL(result)->remat &&
10078             ( OP_SYMBOL(result)->liveTo > ic->seq ||
10079               ic->depth )) {
10080             int size = AOP_SIZE(right) - 1;
10081             while (size--)
10082                 pic16_emitcode("dec","%s",rname);
10083         }
10084     }
10085
10086     /* done */
10087     pic16_freeAsmop(right,NULL,ic,TRUE);
10088     
10089         
10090 }
10091
10092 /*-----------------------------------------------------------------*/
10093 /* genFarPointerSet - set value from far space                     */
10094 /*-----------------------------------------------------------------*/
10095 static void genFarPointerSet (operand *right,
10096                               operand *result, iCode *ic)
10097 {
10098     int size, offset ;
10099     sym_link *retype = getSpec(operandType(right));
10100
10101     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10102     pic16_aopOp(result,ic,FALSE);
10103
10104     /* if the operand is already in dptr 
10105     then we do nothing else we move the value to dptr */
10106     if (AOP_TYPE(result) != AOP_STR) {
10107         /* if this is remateriazable */
10108         if (AOP_TYPE(result) == AOP_IMMD)
10109             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
10110         else { /* we need to get it byte by byte */
10111             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
10112             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
10113             if (options.model == MODEL_FLAT24)
10114             {
10115                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
10116             }
10117         }
10118     }
10119     /* so dptr know contains the address */
10120     pic16_freeAsmop(result,NULL,ic,TRUE);
10121     pic16_aopOp(right,ic,FALSE);
10122
10123     /* if bit then unpack */
10124     if (IS_BITFIELD(retype)) 
10125         genPackBits(retype,right,"dptr",FPOINTER);
10126     else {
10127         size = AOP_SIZE(right);
10128         offset = 0 ;
10129
10130         while (size--) {
10131             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10132             MOVA(l);
10133             pic16_emitcode("movx","@dptr,a");
10134             if (size)
10135                 pic16_emitcode("inc","dptr");
10136         }
10137     }
10138
10139     pic16_freeAsmop(right,NULL,ic,TRUE);
10140 }
10141
10142 /*-----------------------------------------------------------------*/
10143 /* genGenPointerSet - set value from generic pointer space         */
10144 /*-----------------------------------------------------------------*/
10145 static void genGenPointerSet (operand *right,
10146                               operand *result, iCode *ic)
10147 {
10148         int i, size, offset, lit;
10149         sym_link *retype = getSpec(operandType(right));
10150
10151         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10152
10153         pic16_aopOp(result,ic,FALSE);
10154         pic16_aopOp(right,ic,FALSE);
10155         size = AOP_SIZE(right);
10156         offset = 0;
10157
10158         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10159
10160         /* if the operand is already in dptr 
10161                 then we do nothing else we move the value to dptr */
10162         if (AOP_TYPE(result) != AOP_STR) {
10163                 /* if this is remateriazable */
10164                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10165                 // WARNING: anythig until "else" is untested!
10166                 if (AOP_TYPE(result) == AOP_IMMD) {
10167                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10168                         lit = (unsigned)floatFromVal(AOP(result)->aopu.aop_lit);
10169                         // load FSR0 from immediate
10170                         pic16_emitpcode(POC_LFSR,pic16_popGetLit2(0,pic16_popGetLit(lit)));
10171                         offset = 0;
10172                         while(size--) {
10173                                 if(size) {
10174                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10175                                 } else {
10176                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10177                                 }
10178                                 offset++;
10179                         }
10180                         goto release;
10181                 }
10182                 else { /* we need to get it byte by byte */
10183                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10184                         //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
10185
10186                         // set up FSR0 with address of result
10187                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10188                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10189
10190                         /* hack hack! see if this the FSR. If so don't load W */
10191                         if(AOP_TYPE(right) != AOP_ACC) {
10192
10193                                 DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10194
10195                                 if(AOP_TYPE(right) == AOP_LIT)
10196                                 {
10197                                         // copy literal
10198                                         // note: pic16_popGet handles sign extension
10199                                         for(i=0;i<size;i++) {
10200                                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),i));
10201                                                 if(i < size-1)
10202                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postinc0));
10203                                                 else
10204                                                         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
10205                                         }
10206                                 } else {
10207                                         // copy regs
10208
10209                                         for(i=0;i<size;i++) {
10210                                                 if(i < size-1)
10211                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10212                                                                         pic16_popCopyReg(&pic16_pc_postinc0)));
10213                                                 else
10214                                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),i),
10215                                                                         pic16_popCopyReg(&pic16_pc_indf0)));
10216                                         }
10217                                 }
10218                                 goto release;
10219                         } 
10220                         // right = ACC
10221                         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10222                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10223                         goto release;
10224         } // if (AOP_TYPE(result) != AOP_IMMD)
10225
10226         } // if (AOP_TYPE(result) != AOP_STR)
10227         /* so dptr know contains the address */
10228
10229
10230         /* if bit then unpack */
10231         if (IS_BITFIELD(retype)) 
10232                 genPackBits(retype,right,"dptr",GPOINTER);
10233         else {
10234                 size = AOP_SIZE(right);
10235                 offset = 0 ;
10236
10237                 DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
10238
10239                 // set up FSR0 with address of result
10240                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),0), pic16_popCopyReg(&pic16_pc_fsr0l)));
10241                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(result),1), pic16_popCopyReg(&pic16_pc_fsr0h)));
10242         
10243                 while (size--) {
10244                         if (AOP_TYPE(right) == AOP_LIT) {
10245                                 pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10246                                 if (size) {
10247                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_postinc0));
10248                                 } else {
10249                                         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
10250                                 }
10251                         } else { // no literal
10252                                 if(size) {
10253                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_postinc0)));
10254                                 } else {
10255                                         pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popGet(AOP(right),offset), pic16_popCopyReg(&pic16_pc_indf0)));
10256                                 }
10257                         }
10258                         offset++;
10259                 }
10260         }
10261
10262         release:
10263         pic16_freeAsmop(right,NULL,ic,TRUE);
10264         pic16_freeAsmop(result,NULL,ic,TRUE);
10265 }
10266
10267 /*-----------------------------------------------------------------*/
10268 /* genPointerSet - stores the value into a pointer location        */
10269 /*-----------------------------------------------------------------*/
10270 static void genPointerSet (iCode *ic)
10271 {    
10272     operand *right, *result ;
10273     sym_link *type, *etype;
10274     int p_type;
10275
10276     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10277
10278     right = IC_RIGHT(ic);
10279     result = IC_RESULT(ic) ;
10280
10281     /* depending on the type of pointer we need to
10282     move it to the correct pointer register */
10283     type = operandType(result);
10284     etype = getSpec(type);
10285     /* if left is of type of pointer then it is simple */
10286     if (IS_PTR(type) && !IS_FUNC(type->next)) {
10287         p_type = DCL_TYPE(type);
10288     }
10289     else {
10290         /* we have to go by the storage class */
10291         p_type = PTR_TYPE(SPEC_OCLS(etype));
10292
10293 /*      if (SPEC_OCLS(etype)->codesp ) { */
10294 /*          p_type = CPOINTER ;  */
10295 /*      } */
10296 /*      else */
10297 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10298 /*              p_type = FPOINTER ; */
10299 /*          else */
10300 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10301 /*                  p_type = PPOINTER ; */
10302 /*              else */
10303 /*                  if (SPEC_OCLS(etype) == idata ) */
10304 /*                      p_type = IPOINTER ; */
10305 /*                  else */
10306 /*                      p_type = POINTER ; */
10307     }
10308
10309     /* now that we have the pointer type we assign
10310     the pointer values */
10311     switch (p_type) {
10312
10313     case POINTER:
10314     case IPOINTER:
10315         genNearPointerSet (right,result,ic);
10316         break;
10317
10318     case PPOINTER:
10319         genPagedPointerSet (right,result,ic);
10320         break;
10321
10322     case FPOINTER:
10323         genFarPointerSet (right,result,ic);
10324         break;
10325
10326     case GPOINTER:
10327         genGenPointerSet (right,result,ic);
10328         break;
10329
10330     default:
10331       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
10332               "genPointerSet: illegal pointer type");
10333     }
10334 }
10335
10336 /*-----------------------------------------------------------------*/
10337 /* genIfx - generate code for Ifx statement                        */
10338 /*-----------------------------------------------------------------*/
10339 static void genIfx (iCode *ic, iCode *popIc)
10340 {
10341   operand *cond = IC_COND(ic);
10342   int isbit =0;
10343
10344   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10345
10346   pic16_aopOp(cond,ic,FALSE);
10347
10348   /* get the value into acc */
10349   if (AOP_TYPE(cond) != AOP_CRY)
10350     pic16_toBoolean(cond);
10351   else
10352     isbit = 1;
10353   /* the result is now in the accumulator */
10354   pic16_freeAsmop(cond,NULL,ic,TRUE);
10355
10356   /* if there was something to be popped then do it */
10357   if (popIc)
10358     genIpop(popIc);
10359
10360   /* if the condition is  a bit variable */
10361   if (isbit && IS_ITEMP(cond) && 
10362       SPIL_LOC(cond)) {
10363     genIfxJump(ic,SPIL_LOC(cond)->rname);
10364     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
10365   }
10366   else {
10367     if (isbit && !IS_ITEMP(cond))
10368       genIfxJump(ic,OP_SYMBOL(cond)->rname);
10369     else
10370       genIfxJump(ic,"a");
10371   }
10372   ic->generated = 1;
10373
10374 }
10375
10376 /*-----------------------------------------------------------------*/
10377 /* genAddrOf - generates code for address of                       */
10378 /*-----------------------------------------------------------------*/
10379 static void genAddrOf (iCode *ic)
10380 {
10381   operand *result, *left;
10382   int size;
10383   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
10384   pCodeOp *pcop0, *pcop1, *pcop2;
10385
10386         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10387
10388         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
10389         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
10390
10391         sym = OP_SYMBOL( left );
10392
10393         size = AOP_SIZE(IC_RESULT(ic));
10394
10395         if(pic16_debug_verbose) {
10396                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
10397                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
10398         }
10399         
10400         /* Assume that what we want the address of is in data space
10401          * since there is no stack on the PIC, yet! -- VR */
10402         /* low */
10403         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10404
10405         /* high */
10406         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10407         
10408         /* upper */
10409         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10410         
10411
10412         if (size == 3) {
10413                 pic16_emitpcode(POC_MOVLW, pcop0);
10414                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10415                 pic16_emitpcode(POC_MOVLW, pcop1);
10416                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10417                 pic16_emitpcode(POC_MOVLW, pcop2);
10418                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10419         } else
10420         if (size == 2) {
10421                 pic16_emitpcode(POC_MOVLW, pcop0);
10422                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10423                 pic16_emitpcode(POC_MOVLW, pcop1);
10424                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10425         } else {
10426                 pic16_emitpcode(POC_MOVLW, pcop0);
10427                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10428         }
10429
10430         pic16_freeAsmop(result,NULL,ic,TRUE);
10431         pic16_freeAsmop(left, NULL, ic, FALSE);
10432 }
10433
10434
10435 #if 0
10436 /*-----------------------------------------------------------------*/
10437 /* genFarFarAssign - assignment when both are in far space         */
10438 /*-----------------------------------------------------------------*/
10439 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
10440 {
10441     int size = AOP_SIZE(right);
10442     int offset = 0;
10443     char *l ;
10444     /* first push the right side on to the stack */
10445     while (size--) {
10446         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
10447         MOVA(l);
10448         pic16_emitcode ("push","acc");
10449     }
10450     
10451     pic16_freeAsmop(right,NULL,ic,FALSE);
10452     /* now assign DPTR to result */
10453     pic16_aopOp(result,ic,FALSE);
10454     size = AOP_SIZE(result);
10455     while (size--) {
10456         pic16_emitcode ("pop","acc");
10457         pic16_aopPut(AOP(result),"a",--offset);
10458     }
10459     pic16_freeAsmop(result,NULL,ic,FALSE);
10460         
10461 }
10462 #endif
10463
10464 /*-----------------------------------------------------------------*/
10465 /* genAssign - generate code for assignment                        */
10466 /*-----------------------------------------------------------------*/
10467 static void genAssign (iCode *ic)
10468 {
10469   operand *result, *right;
10470   int size, offset,know_W;
10471   unsigned long lit = 0L;
10472
10473   result = IC_RESULT(ic);
10474   right  = IC_RIGHT(ic) ;
10475
10476   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10477   
10478   /* if they are the same */
10479   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
10480     return ;
10481
10482   pic16_aopOp(right,ic,FALSE);
10483   pic16_aopOp(result,ic,TRUE);
10484
10485   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10486
10487   /* if they are the same registers */
10488   if (pic16_sameRegs(AOP(right),AOP(result)))
10489     goto release;
10490
10491   /* if the result is a bit */
10492   if (AOP_TYPE(result) == AOP_CRY) {
10493     /* if the right size is a literal then
10494        we know what the value is */
10495     if (AOP_TYPE(right) == AOP_LIT) {
10496           
10497       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10498                   pic16_popGet(AOP(result),0));
10499
10500       if (((int) operandLitValue(right))) 
10501         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10502                        AOP(result)->aopu.aop_dir,
10503                        AOP(result)->aopu.aop_dir);
10504       else
10505         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10506                        AOP(result)->aopu.aop_dir,
10507                        AOP(result)->aopu.aop_dir);
10508       goto release;
10509     }
10510
10511     /* the right is also a bit variable */
10512     if (AOP_TYPE(right) == AOP_CRY) {
10513       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10514       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10515       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10516
10517       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
10518                      AOP(result)->aopu.aop_dir,
10519                      AOP(result)->aopu.aop_dir);
10520       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
10521                      AOP(right)->aopu.aop_dir,
10522                      AOP(right)->aopu.aop_dir);
10523       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
10524                      AOP(result)->aopu.aop_dir,
10525                      AOP(result)->aopu.aop_dir);
10526       goto release ;
10527     }
10528
10529     /* we need to or */
10530     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10531     pic16_toBoolean(right);
10532     emitSKPZ;
10533     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10534     //pic16_aopPut(AOP(result),"a",0);
10535     goto release ;
10536   }
10537
10538   /* bit variables done */
10539   /* general case */
10540   size = AOP_SIZE(result);
10541   offset = 0 ;
10542   if(AOP_TYPE(right) == AOP_LIT)
10543     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
10544
10545 /* VR - What is this?! */
10546   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
10547   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10548     if(aopIdx(AOP(result),0) == 4) {
10549   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10550       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10551       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10552       goto release;
10553     } else
10554       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
10555   }
10556
10557   know_W=-1;
10558   while (size--) {
10559   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10560     if(AOP_TYPE(right) == AOP_LIT) {
10561       if(lit&0xff) {
10562         if(know_W != (lit&0xff))
10563           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
10564         know_W = lit&0xff;
10565         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10566       } else
10567         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10568
10569       lit >>= 8;
10570
10571     } else if (AOP_TYPE(right) == AOP_CRY) {
10572       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
10573       if(offset == 0) {
10574         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
10575         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
10576       }
10577     } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
10578         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10579         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10580     } else {
10581   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10582
10583 #if 1
10584         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
10585            normally should work, but mind that the W register live range
10586            is not checked, so if the code generator assumes that the W
10587            is already loaded after such a pair, wrong code will be generated.
10588            
10589            Checking the live range is the next step.
10590            This is experimental code yet and has not been fully tested yet.
10591            USE WITH CARE. Revert to old code by setting 0 to the condition above.
10592            Vangelis Rokas 030603 (vrokas@otenet.gr) */
10593            
10594         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
10595 #else   
10596         /* This is the old code, which is assumed(?!) that works fine(!?) */
10597
10598         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10599         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10600 #endif
10601     }
10602             
10603     offset++;
10604   }
10605
10606     
10607  release:
10608   pic16_freeAsmop (right,NULL,ic,FALSE);
10609   pic16_freeAsmop (result,NULL,ic,TRUE);
10610 }   
10611
10612 /*-----------------------------------------------------------------*/
10613 /* genJumpTab - generates code for jump table                       */
10614 /*-----------------------------------------------------------------*/
10615 static void genJumpTab (iCode *ic)
10616 {
10617     symbol *jtab;
10618     char *l;
10619
10620     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10621
10622     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
10623     /* get the condition into accumulator */
10624     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
10625     MOVA(l);
10626     /* multiply by three */
10627     pic16_emitcode("add","a,acc");
10628     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
10629
10630     jtab = newiTempLabel(NULL);
10631     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
10632     pic16_emitcode("jmp","@a+dptr");
10633     pic16_emitcode("","%05d_DS_:",jtab->key+100);
10634
10635     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
10636     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
10637     emitSKPNC;
10638     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
10639     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
10640     pic16_emitpLabel(jtab->key);
10641
10642     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
10643
10644     /* now generate the jump labels */
10645     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
10646          jtab = setNextItem(IC_JTLABELS(ic))) {
10647         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
10648         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
10649         
10650     }
10651
10652 }
10653
10654 /*-----------------------------------------------------------------*/
10655 /* genMixedOperation - gen code for operators between mixed types  */
10656 /*-----------------------------------------------------------------*/
10657 /*
10658   TSD - Written for the PIC port - but this unfortunately is buggy.
10659   This routine is good in that it is able to efficiently promote 
10660   types to different (larger) sizes. Unfortunately, the temporary
10661   variables that are optimized out by this routine are sometimes
10662   used in other places. So until I know how to really parse the 
10663   iCode tree, I'm going to not be using this routine :(.
10664 */
10665 static int genMixedOperation (iCode *ic)
10666 {
10667 #if 0
10668   operand *result = IC_RESULT(ic);
10669   sym_link *ctype = operandType(IC_LEFT(ic));
10670   operand *right = IC_RIGHT(ic);
10671   int ret = 0;
10672   int big,small;
10673   int offset;
10674
10675   iCode *nextic;
10676   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
10677
10678   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10679
10680   nextic = ic->next;
10681   if(!nextic)
10682     return 0;
10683
10684   nextright = IC_RIGHT(nextic);
10685   nextleft  = IC_LEFT(nextic);
10686   nextresult = IC_RESULT(nextic);
10687
10688   pic16_aopOp(right,ic,FALSE);
10689   pic16_aopOp(result,ic,FALSE);
10690   pic16_aopOp(nextright,  nextic, FALSE);
10691   pic16_aopOp(nextleft,   nextic, FALSE);
10692   pic16_aopOp(nextresult, nextic, FALSE);
10693
10694   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
10695
10696     operand *t = right;
10697     right = nextright;
10698     nextright = t; 
10699
10700     pic16_emitcode(";remove right +","");
10701
10702   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
10703 /*
10704     operand *t = right;
10705     right = nextleft;
10706     nextleft = t; 
10707 */
10708     pic16_emitcode(";remove left +","");
10709   } else
10710     return 0;
10711
10712   big = AOP_SIZE(nextleft);
10713   small = AOP_SIZE(nextright);
10714
10715   switch(nextic->op) {
10716
10717   case '+':
10718     pic16_emitcode(";optimize a +","");
10719     /* if unsigned or not an integral type */
10720     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
10721       pic16_emitcode(";add a bit to something","");
10722     } else {
10723
10724       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
10725
10726       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
10727         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
10728         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
10729       } else
10730         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
10731
10732       offset = 0;
10733       while(--big) {
10734
10735         offset++;
10736
10737         if(--small) {
10738           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10739             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10740             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10741           }
10742
10743           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10744           emitSKPNC;
10745           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10746                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
10747                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
10748           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10749           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
10750
10751         } else {
10752           pic16_emitcode("rlf","known_zero,w");
10753
10754           /*
10755             if right is signed
10756               btfsc  right,7
10757                addlw ff
10758           */
10759           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
10760             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
10761             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10762           } else {
10763             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
10764           }
10765         }
10766       }
10767       ret = 1;
10768     }
10769   }
10770   ret = 1;
10771
10772 release:
10773   pic16_freeAsmop(right,NULL,ic,TRUE);
10774   pic16_freeAsmop(result,NULL,ic,TRUE);
10775   pic16_freeAsmop(nextright,NULL,ic,TRUE);
10776   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
10777   if(ret)
10778     nextic->generated = 1;
10779
10780   return ret;
10781 #else
10782   return 0;
10783 #endif
10784 }
10785 /*-----------------------------------------------------------------*/
10786 /* genCast - gen code for casting                                  */
10787 /*-----------------------------------------------------------------*/
10788 static void genCast (iCode *ic)
10789 {
10790   operand *result = IC_RESULT(ic);
10791   sym_link *ctype = operandType(IC_LEFT(ic));
10792   sym_link *rtype = operandType(IC_RIGHT(ic));
10793   operand *right = IC_RIGHT(ic);
10794   int size, offset ;
10795
10796         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10797         /* if they are equivalent then do nothing */
10798         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
10799                 return ;
10800
10801         pic16_aopOp(right,ic,FALSE) ;
10802         pic16_aopOp(result,ic,FALSE);
10803
10804         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
10805
10806         /* if the result is a bit */
10807         if (AOP_TYPE(result) == AOP_CRY) {
10808         
10809                 /* if the right size is a literal then
10810                  * we know what the value is */
10811                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10812
10813                 if (AOP_TYPE(right) == AOP_LIT) {
10814                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
10815                                 pic16_popGet(AOP(result),0));
10816
10817                         if (((int) operandLitValue(right))) 
10818                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
10819                                         AOP(result)->aopu.aop_dir,
10820                                         AOP(result)->aopu.aop_dir);
10821                         else
10822                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
10823                                         AOP(result)->aopu.aop_dir,
10824                                         AOP(result)->aopu.aop_dir);
10825                         goto release;
10826                 }
10827
10828                 /* the right is also a bit variable */
10829                 if (AOP_TYPE(right) == AOP_CRY) {
10830                         emitCLRC;
10831                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10832
10833                         pic16_emitcode("clrc","");
10834                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
10835                                 AOP(right)->aopu.aop_dir,
10836                                 AOP(right)->aopu.aop_dir);
10837                         pic16_aopPut(AOP(result),"c",0);
10838                         goto release ;
10839                 }
10840
10841                 /* we need to or */
10842                 if (AOP_TYPE(right) == AOP_REG) {
10843                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
10844                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
10845                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
10846                 }
10847                 pic16_toBoolean(right);
10848                 pic16_aopPut(AOP(result),"a",0);
10849                 goto release ;
10850         }
10851
10852         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10853           int offset = 1;
10854
10855                 size = AOP_SIZE(result);
10856
10857                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10858
10859                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10860                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10861                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10862
10863                 while (size--)
10864                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10865
10866                 goto release;
10867         }
10868
10869         /* if they are the same size : or less */
10870         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10871
10872                 /* if they are in the same place */
10873                 if (pic16_sameRegs(AOP(right),AOP(result)))
10874                         goto release;
10875
10876                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10877 #if 0
10878                 if (IS_PTR_CONST(rtype))
10879 #else
10880                 if (IS_CODEPTR(rtype))
10881 #endif
10882                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10883
10884 #if 0
10885                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10886 #else
10887                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10888 #endif
10889                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10890
10891 #if 0
10892                 if(AOP_TYPE(right) == AOP_IMMD) {
10893                   pCodeOp *pcop0, *pcop1, *pcop2;
10894                   symbol *sym = OP_SYMBOL( right );
10895
10896                         size = AOP_SIZE(result);
10897                         /* low */
10898                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10899                         /* high */
10900                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10901                         /* upper */
10902                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10903         
10904                         if (size == 3) {
10905                                 pic16_emitpcode(POC_MOVLW, pcop0);
10906                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10907                                 pic16_emitpcode(POC_MOVLW, pcop1);
10908                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10909                                 pic16_emitpcode(POC_MOVLW, pcop2);
10910                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10911                         } else
10912                         if (size == 2) {
10913                                 pic16_emitpcode(POC_MOVLW, pcop0);
10914                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10915                                 pic16_emitpcode(POC_MOVLW, pcop1);
10916                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10917                         } else {
10918                                 pic16_emitpcode(POC_MOVLW, pcop0);
10919                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10920                         }
10921                 } else
10922 #endif
10923                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10924                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10925                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10926                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10927                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10928                         if(AOP_SIZE(result) <2)
10929                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10930                 } else {
10931                         /* if they in different places then copy */
10932                         size = AOP_SIZE(result);
10933                         offset = 0 ;
10934                         while (size--) {
10935                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10936                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10937                                 offset++;
10938                         }
10939                 }
10940                 goto release;
10941         }
10942
10943         /* if the result is of type pointer */
10944         if (IS_PTR(ctype)) {
10945           int p_type;
10946           sym_link *type = operandType(right);
10947           sym_link *etype = getSpec(type);
10948
10949                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10950
10951                 /* pointer to generic pointer */
10952                 if (IS_GENPTR(ctype)) {
10953                   char *l = zero;
10954             
10955                         if (IS_PTR(type)) 
10956                                 p_type = DCL_TYPE(type);
10957                         else {
10958                 /* we have to go by the storage class */
10959                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10960
10961 /*              if (SPEC_OCLS(etype)->codesp )  */
10962 /*                  p_type = CPOINTER ;  */
10963 /*              else */
10964 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10965 /*                      p_type = FPOINTER ; */
10966 /*                  else */
10967 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10968 /*                          p_type = PPOINTER; */
10969 /*                      else */
10970 /*                          if (SPEC_OCLS(etype) == idata ) */
10971 /*                              p_type = IPOINTER ; */
10972 /*                          else */
10973 /*                              p_type = POINTER ; */
10974             }
10975                 
10976             /* the first two bytes are known */
10977       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10978             size = GPTRSIZE - 1; 
10979             offset = 0 ;
10980             while (size--) {
10981               if(offset < AOP_SIZE(right)) {
10982       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10983                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10984                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10985                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10986                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10987                 } else { 
10988                   pic16_aopPut(AOP(result),
10989                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10990                          offset);
10991                 }
10992               } else 
10993                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10994               offset++;
10995             }
10996             /* the last byte depending on type */
10997             switch (p_type) {
10998             case IPOINTER:
10999             case POINTER:
11000                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
11001                 break;
11002             case FPOINTER:
11003               pic16_emitcode(";BUG!? ","%d",__LINE__);
11004                 l = one;
11005                 break;
11006             case CPOINTER:
11007               pic16_emitcode(";BUG!? ","%d",__LINE__);
11008                 l = "#0x02";
11009                 break;                          
11010             case PPOINTER:
11011               pic16_emitcode(";BUG!? ","%d",__LINE__);
11012                 l = "#0x03";
11013                 break;
11014                 
11015             default:
11016                 /* this should never happen */
11017                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11018                        "got unknown pointer type");
11019                 exit(1);
11020             }
11021             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
11022             goto release ;
11023         }
11024         
11025         /* just copy the pointers */
11026         size = AOP_SIZE(result);
11027         offset = 0 ;
11028         while (size--) {
11029             pic16_aopPut(AOP(result),
11030                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
11031                    offset);
11032             offset++;
11033         }
11034         goto release ;
11035     }
11036     
11037
11038
11039     /* so we now know that the size of destination is greater
11040     than the size of the source.
11041     Now, if the next iCode is an operator then we might be
11042     able to optimize the operation without performing a cast.
11043     */
11044     if(genMixedOperation(ic))
11045       goto release;
11046
11047     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
11048     
11049     /* we move to result for the size of source */
11050     size = AOP_SIZE(right);
11051     offset = 0 ;
11052     while (size--) {
11053       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
11054       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
11055       offset++;
11056     }
11057
11058     /* now depending on the sign of the destination */
11059     size = AOP_SIZE(result) - AOP_SIZE(right);
11060     /* if unsigned or not an integral type */
11061     if (SPEC_USIGN( getSpec(rtype) ) || !IS_SPEC(rtype)) {
11062       while (size--)
11063         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
11064     } else {
11065       /* we need to extend the sign :( */
11066
11067       if(size == 1) {
11068         /* Save one instruction of casting char to int */
11069         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
11070         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11071         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
11072       } else {
11073         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
11074
11075         if(offset)
11076           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
11077         else
11078           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
11079         
11080         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
11081
11082         while (size--)
11083           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
11084       }
11085     }
11086
11087 release:
11088     pic16_freeAsmop(right,NULL,ic,TRUE);
11089     pic16_freeAsmop(result,NULL,ic,TRUE);
11090
11091 }
11092
11093 /*-----------------------------------------------------------------*/
11094 /* genDjnz - generate decrement & jump if not zero instrucion      */
11095 /*-----------------------------------------------------------------*/
11096 static int genDjnz (iCode *ic, iCode *ifx)
11097 {
11098     symbol *lbl, *lbl1;
11099     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11100
11101     if (!ifx)
11102         return 0;
11103     
11104     /* if the if condition has a false label
11105        then we cannot save */
11106     if (IC_FALSE(ifx))
11107         return 0;
11108
11109     /* if the minus is not of the form 
11110        a = a - 1 */
11111     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
11112         !IS_OP_LITERAL(IC_RIGHT(ic)))
11113         return 0;
11114
11115     if (operandLitValue(IC_RIGHT(ic)) != 1)
11116         return 0;
11117
11118     /* if the size of this greater than one then no
11119        saving */
11120     if (getSize(operandType(IC_RESULT(ic))) > 1)
11121         return 0;
11122
11123     /* otherwise we can save BIG */
11124     lbl = newiTempLabel(NULL);
11125     lbl1= newiTempLabel(NULL);
11126
11127     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
11128     
11129     if (IS_AOP_PREG(IC_RESULT(ic))) {
11130         pic16_emitcode("dec","%s",
11131                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11132         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11133         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
11134     } else {    
11135
11136
11137       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
11138       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
11139
11140       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
11141       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
11142
11143     }
11144 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
11145 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
11146 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
11147 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
11148
11149     
11150     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11151     ifx->generated = 1;
11152     return 1;
11153 }
11154
11155 /*-----------------------------------------------------------------*/
11156 /* genReceive - generate code for a receive iCode                  */
11157 /*-----------------------------------------------------------------*/
11158 static void genReceive (iCode *ic)
11159 {    
11160         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
11161
11162         if (isOperandInFarSpace(IC_RESULT(ic)) &&
11163                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
11164                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
11165
11166           int size = getSize(operandType(IC_RESULT(ic)));
11167           int offset =  pic16_fReturnSizePic - size;
11168
11169                 while (size--) {
11170                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
11171                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
11172                         offset++;
11173                 }
11174
11175                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
11176
11177                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11178                 size = AOP_SIZE(IC_RESULT(ic));
11179                 offset = 0;
11180                 while (size--) {
11181                         pic16_emitcode ("pop","acc");
11182                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
11183                 }
11184         } else {
11185                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
11186
11187                 _G.accInUse++;
11188                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
11189                 _G.accInUse--;
11190                 assignResultValue(IC_RESULT(ic), 0);
11191         }
11192
11193         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
11194 }
11195
11196 /*-----------------------------------------------------------------*/
11197 /* genDummyRead - generate code for dummy read of volatiles        */
11198 /*-----------------------------------------------------------------*/
11199 static void
11200 genDummyRead (iCode * ic)
11201 {
11202   pic16_emitcode ("; genDummyRead","");
11203   pic16_emitcode ("; not implemented","");
11204
11205   ic = ic;
11206 }
11207
11208 /*-----------------------------------------------------------------*/
11209 /* genpic16Code - generate code for pic16 based controllers        */
11210 /*-----------------------------------------------------------------*/
11211 /*
11212  * At this point, ralloc.c has gone through the iCode and attempted
11213  * to optimize in a way suitable for a PIC. Now we've got to generate
11214  * PIC instructions that correspond to the iCode.
11215  *
11216  * Once the instructions are generated, we'll pass through both the
11217  * peep hole optimizer and the pCode optimizer.
11218  *-----------------------------------------------------------------*/
11219
11220 void genpic16Code (iCode *lic)
11221 {
11222     iCode *ic;
11223     int cln = 0;
11224
11225     lineHead = lineCurr = NULL;
11226
11227     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
11228     pic16_addpBlock(pb);
11229
11230 #if 0
11231     /* if debug information required */
11232     if (options.debug && currFunc) {
11233       if (currFunc) {
11234         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
11235       }
11236     }
11237 #endif
11238
11239     for (ic = lic ; ic ; ic = ic->next ) {
11240
11241       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
11242         if ( cln != ic->lineno ) {
11243             if ( options.debug ) {
11244               debugFile->writeCLine (ic);
11245             }
11246             
11247             if(!options.noCcodeInAsm) {
11248                 pic16_addpCode2pBlock(pb,
11249                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
11250                                 printCLine(ic->filename, ic->lineno)));
11251             }
11252
11253             cln = ic->lineno ;
11254         }
11255         
11256         if(options.iCodeInAsm) {
11257                 char *l;
11258                 /* insert here code to print iCode as comment */
11259                 l = Safe_strdup(printILine(ic));
11260                 pic16_emitpcomment("ic:%d: %s", ic->seq, l);
11261         }
11262         
11263         /* if the result is marked as
11264            spilt and rematerializable or code for
11265            this has already been generated then
11266            do nothing */
11267         if (resultRemat(ic) || ic->generated ) 
11268             continue ;
11269         
11270         /* depending on the operation */
11271         switch (ic->op) {
11272         case '!' :
11273             pic16_genNot(ic);
11274             break;
11275             
11276         case '~' :
11277             pic16_genCpl(ic);
11278             break;
11279             
11280         case UNARYMINUS:
11281             genUminus (ic);
11282             break;
11283             
11284         case IPUSH:
11285             genIpush (ic);
11286             break;
11287             
11288         case IPOP:
11289             /* IPOP happens only when trying to restore a 
11290                spilt live range, if there is an ifx statement
11291                following this pop then the if statement might
11292                be using some of the registers being popped which
11293                would destroy the contents of the register so
11294                we need to check for this condition and handle it */
11295             if (ic->next            && 
11296                 ic->next->op == IFX &&
11297                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
11298                 genIfx (ic->next,ic);
11299             else
11300                 genIpop (ic);
11301             break; 
11302             
11303         case CALL:
11304             genCall (ic);
11305             break;
11306             
11307         case PCALL:
11308             genPcall (ic);
11309             break;
11310             
11311         case FUNCTION:
11312             genFunction (ic);
11313             break;
11314             
11315         case ENDFUNCTION:
11316             genEndFunction (ic);
11317             break;
11318             
11319         case RETURN:
11320             genRet (ic);
11321             break;
11322             
11323         case LABEL:
11324             genLabel (ic);
11325             break;
11326             
11327         case GOTO:
11328             genGoto (ic);
11329             break;
11330             
11331         case '+' :
11332             pic16_genPlus (ic) ;
11333             break;
11334             
11335         case '-' :
11336             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
11337                 pic16_genMinus (ic);
11338             break;
11339             
11340         case '*' :
11341             genMult (ic);
11342             break;
11343             
11344         case '/' :
11345             genDiv (ic) ;
11346             break;
11347             
11348         case '%' :
11349             genMod (ic);
11350             break;
11351             
11352         case '>' :
11353             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
11354             break;
11355             
11356         case '<' :
11357             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
11358             break;
11359             
11360         case LE_OP:
11361         case GE_OP:
11362         case NE_OP:
11363             
11364             /* note these two are xlated by algebraic equivalence
11365                during parsing SDCC.y */
11366             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
11367                    "got '>=' or '<=' shouldn't have come here");
11368             break;      
11369             
11370         case EQ_OP:
11371             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
11372             break;          
11373             
11374         case AND_OP:
11375             genAndOp (ic);
11376             break;
11377             
11378         case OR_OP:
11379             genOrOp (ic);
11380             break;
11381             
11382         case '^' :
11383             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
11384             break;
11385             
11386         case '|' :
11387                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
11388             break;
11389             
11390         case BITWISEAND:
11391             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
11392             break;
11393             
11394         case INLINEASM:
11395             genInline (ic);
11396             break;
11397             
11398         case RRC:
11399             genRRC (ic);
11400             break;
11401             
11402         case RLC:
11403             genRLC (ic);
11404             break;
11405             
11406         case GETHBIT:
11407             genGetHbit (ic);
11408             break;
11409             
11410         case LEFT_OP:
11411             genLeftShift (ic);
11412             break;
11413             
11414         case RIGHT_OP:
11415             genRightShift (ic);
11416             break;
11417             
11418         case GET_VALUE_AT_ADDRESS:
11419             genPointerGet(ic);
11420             break;
11421             
11422         case '=' :
11423             if (POINTER_SET(ic))
11424                 genPointerSet(ic);
11425             else
11426                 genAssign(ic);
11427             break;
11428             
11429         case IFX:
11430             genIfx (ic,NULL);
11431             break;
11432             
11433         case ADDRESS_OF:
11434             genAddrOf (ic);
11435             break;
11436             
11437         case JUMPTABLE:
11438             genJumpTab (ic);
11439             break;
11440             
11441         case CAST:
11442             genCast (ic);
11443             break;
11444             
11445         case RECEIVE:
11446             genReceive(ic);
11447             break;
11448             
11449         case SEND:
11450             addSet(&_G.sendSet,ic);
11451             break;
11452
11453         case DUMMY_READ_VOLATILE:
11454           genDummyRead (ic);
11455           break;
11456
11457         default :
11458             ic = ic;
11459         }
11460     }
11461
11462
11463     /* now we are ready to call the
11464        peep hole optimizer */
11465     if (!options.nopeep) {
11466       peepHole (&lineHead);
11467     }
11468     /* now do the actual printing */
11469     printLine (lineHead,codeOutFile);
11470
11471 #ifdef PCODE_DEBUG
11472     DFPRINTF((stderr,"printing pBlock\n\n"));
11473     pic16_printpBlock(stdout,pb);
11474 #endif
11475
11476     return;
11477 }
11478