2004-02-06 Vangelis Rokas <vrokas AT otenet.gr>
[fw/sdcc] / src / pic16 / gen.c
1 /*-------------------------------------------------------------------------
2  gen.c - source file for code generation for pic16
3
4   Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
5          and -  Jean-Louis VERN.jlvern@writeme.com (1999)
6   Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
7   PIC port   -  Scott Dattalo scott@dattalo.com (2000)
8   PIC16 port -  Martin Dubuc m.dubuc@rogers.com (2002)
9   
10   This program is free software; you can redistribute it and/or modify it
11   under the terms of the GNU General Public License as published by the
12   Free Software Foundation; either version 2, or (at your option) any
13   later version.
14   
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19   
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23   
24   In other words, you are welcome to use, share and improve this program.
25   You are forbidden to forbid anyone else to use, share and improve
26   what you give them.   Help stamp out software-hoarding!
27   
28   Notes:
29   000123 mlh    Moved aopLiteral to SDCCglue.c to help the split
30                 Made everything static
31 -------------------------------------------------------------------------*/
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <ctype.h>
37 #include "SDCCglobl.h"
38 #include "newalloc.h"
39
40 #include "common.h"
41 #include "SDCCpeeph.h"
42 #include "ralloc.h"
43 #include "pcode.h"
44 #include "gen.h"
45 #include "genutils.h"
46 #include "device.h"
47 #include "main.h"
48
49 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
50 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
51 void pic16_genMult8X8_8 (operand *, operand *,operand *);
52 pCode *pic16_AssembleLine(char *line, int peeps);
53 extern void pic16_printpBlock(FILE *of, pBlock *pb);
54 static asmop *newAsmop (short type);
55 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset);
56 extern pCode *pic16_newpCodeAsmDir(char *asdir, char *argfmt, ...);
57 static void mov2w (asmop *aop, int offset);
58 static int aopIdx (asmop *aop, int offset);
59
60 static int labelOffset=0;
61 extern int pic16_debug_verbose;
62 static int optimized_for_speed = 0;
63 /*
64   hack hack
65
66 */
67
68 /* max_key keeps track of the largest label number used in 
69    a function. This is then used to adjust the label offset
70    for the next function.
71 */
72 static int max_key=0;
73 static int GpsuedoStkPtr=0;
74
75 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index);
76 unsigned int pic16aopLiteral (value *val, int offset);
77 const char *pic16_AopType(short type);
78 static iCode *ifxForOp ( operand *op, iCode *ic );
79
80 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
81
82 /* this is the down and dirty file with all kinds of 
83    kludgy & hacky stuff. This is what it is all about
84    CODE GENERATION for a specific MCU . some of the
85    routines may be reusable, will have to see */
86
87 static char *zero = "#0x00";
88 static char *one  = "#0x01";
89 static char *spname = "sp";
90
91 char *fReturnpic16[] = {"temp1","temp2","temp3","temp4" };
92 //char *fReturn390[] = {"dpl","dph","dpx", "b","a" };
93 unsigned pic16_fReturnSizePic = 4; /* shared with ralloc.c */
94 static char **fReturn = fReturnpic16;
95
96 static char *accUse[] = {"a","b"};
97
98 //static short rbank = -1;
99
100 static struct {
101     short r0Pushed;
102     short r1Pushed;
103     short accInUse;
104     short inLine;
105     short debugLine;
106     short nRegsSaved;
107     set *sendSet;
108 } _G;
109
110 /* Resolved ifx structure. This structure stores information
111    about an iCode ifx that makes it easier to generate code.
112 */
113 typedef struct resolvedIfx {
114   symbol *lbl;     /* pointer to a label */
115   int condition;   /* true or false ifx */
116   int generated;   /* set true when the code associated with the ifx
117                     * is generated */
118 } resolvedIfx;
119
120 extern int pic16_ptrRegReq ;
121 extern int pic16_nRegs;
122 extern FILE *codeOutFile;
123 static void saverbank (int, iCode *,bool);
124
125 static lineNode *lineHead = NULL;
126 static lineNode *lineCurr = NULL;
127
128 static unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
129 0xE0, 0xC0, 0x80, 0x00};
130 static unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
131 0x07, 0x03, 0x01, 0x00};
132
133 static  pBlock *pb;
134
135 /*-----------------------------------------------------------------*/
136 /*  my_powof2(n) - If `n' is an integaer power of 2, then the      */
137 /*                 exponent of 2 is returned, otherwise -1 is      */
138 /*                 returned.                                       */
139 /* note that this is similar to the function `powof2' in SDCCsymt  */
140 /* if(n == 2^y)                                                    */
141 /*   return y;                                                     */
142 /* return -1;                                                      */
143 /*-----------------------------------------------------------------*/
144 static int my_powof2 (unsigned long num)
145 {
146   if(num) {
147     if( (num & (num-1)) == 0) {
148       int nshifts = -1;
149       while(num) {
150         num>>=1;
151         nshifts++;
152       }
153       return nshifts;
154     }
155   }
156
157   return -1;
158 }
159
160 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result)
161 {
162
163   DEBUGpic16_emitcode ("; ","line = %d result %s=%s, left %s=%s, right %s=%s, size = %d",
164                        line_no,
165                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
166                        ((result) ? pic16_aopGet(AOP(result),0,TRUE,FALSE) : "-"),
167                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
168                        ((left)   ? pic16_aopGet(AOP(left),0,TRUE,FALSE) : "-"),
169                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
170                        ((right)  ? pic16_aopGet(AOP(right),0,FALSE,FALSE) : "-"),
171                        ((result) ? AOP_SIZE(result) : 0));
172
173 }
174
175 void DEBUGpic16_pic16_AopTypeSign(int line_no, operand *left, operand *right, operand *result)
176 {
177
178   DEBUGpic16_emitcode ("; ","line = %d, signs: result %s=%c, left %s=%c, right %s=%c",
179                        line_no,
180                        ((result) ? pic16_AopType(AOP_TYPE(result)) : "-"),
181                        ((result) ? (SPEC_USIGN(operandType(result)) ? 'u' : 's') : '-'),
182                        ((left)   ? pic16_AopType(AOP_TYPE(left)) : "-"),
183                        ((left)   ? (SPEC_USIGN(operandType(left))   ? 'u' : 's') : '-'),
184                        ((right)  ? pic16_AopType(AOP_TYPE(right)) : "-"),
185                        ((right)  ? (SPEC_USIGN(operandType(right))  ? 'u' : 's') : '-'));
186
187 }
188
189 void pic16_emitcomment (char *fmt, ...)
190 {
191     va_list ap;
192     char lb[INITIAL_INLINEASM];  
193     char *lbp = lb;
194
195     if(!pic16_debug_verbose)
196       return;
197
198     va_start(ap,fmt);   
199
200     lb[0] = ';';
201     vsprintf(lb+1,fmt,ap);
202
203     while (isspace(*lbp)) lbp++;
204
205     if (lbp && *lbp) 
206         lineCurr = (lineCurr ?
207                     connectLine(lineCurr,newLineNode(lb)) :
208                     (lineHead = newLineNode(lb)));
209     lineCurr->isInline = _G.inLine;
210     lineCurr->isDebug  = _G.debugLine;
211
212     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
213     va_end(ap);
214
215 //      fprintf(stderr, "%s\n", lb);
216 }
217
218 void DEBUGpic16_emitcode (char *inst,char *fmt, ...)
219 {
220     va_list ap;
221     char lb[INITIAL_INLINEASM];  
222     char *lbp = lb;
223
224     if(!pic16_debug_verbose)
225       return;
226
227     va_start(ap,fmt);   
228
229     if (inst && *inst) {
230         if (fmt && *fmt)
231             sprintf(lb,"%s\t",inst);
232         else
233             sprintf(lb,"%s",inst);
234         vsprintf(lb+(strlen(lb)),fmt,ap);
235     }  else
236         vsprintf(lb,fmt,ap);
237
238     while (isspace(*lbp)) lbp++;
239
240     if (lbp && *lbp) 
241         lineCurr = (lineCurr ?
242                     connectLine(lineCurr,newLineNode(lb)) :
243                     (lineHead = newLineNode(lb)));
244     lineCurr->isInline = _G.inLine;
245     lineCurr->isDebug  = _G.debugLine;
246
247     pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
248     va_end(ap);
249
250 //      fprintf(stderr, "%s\n", lb);
251 }
252
253 void pic16_emitpLabel(int key)
254 {
255   pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,key+100+labelOffset));
256 }
257
258 void pic16_emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
259 {
260
261   if(pcop)
262     pic16_addpCode2pBlock(pb,pic16_newpCode(poc,pcop));
263   else
264     DEBUGpic16_emitcode(";","%s  ignoring NULL pcop",__FUNCTION__);
265     
266 //    fprintf(stderr, "%s\n", pcop->name);
267 }
268
269 void pic16_emitpcodeNULLop(PIC_OPCODE poc)
270 {
271
272   pic16_addpCode2pBlock(pb,pic16_newpCode(poc,NULL));
273
274 }
275
276
277 #if 1
278 #define pic16_emitcode  DEBUGpic16_emitcode
279 #else
280 /*-----------------------------------------------------------------*/
281 /* pic16_emitcode - writes the code into a file : for now it is simple    */
282 /*-----------------------------------------------------------------*/
283 void pic16_emitcode (char *inst,char *fmt, ...)
284 {
285     va_list ap;
286     char lb[INITIAL_INLINEASM];  
287     char *lbp = lb;
288
289     va_start(ap,fmt);   
290
291     if (inst && *inst) {
292         if (fmt && *fmt)
293             sprintf(lb,"%s\t",inst);
294         else
295             sprintf(lb,"%s",inst);
296         vsprintf(lb+(strlen(lb)),fmt,ap);
297     }  else
298         vsprintf(lb,fmt,ap);
299
300     while (isspace(*lbp)) lbp++;
301
302     if (lbp && *lbp) 
303         lineCurr = (lineCurr ?
304                     connectLine(lineCurr,newLineNode(lb)) :
305                     (lineHead = newLineNode(lb)));
306     lineCurr->isInline = _G.inLine;
307     lineCurr->isDebug  = _G.debugLine;
308
309 // VR    fprintf(stderr, "lb = <%s>\n", lbp);
310
311 //    if(pic16_debug_verbose)
312 //      pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(lb));
313
314     va_end(ap);
315 }
316 #endif
317
318
319 /*-----------------------------------------------------------------*/
320 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed*/
321 /*-----------------------------------------------------------------*/
322 static regs *getFreePtr (iCode *ic, asmop **aopp, bool result)
323 {
324     bool r0iu = FALSE , r1iu = FALSE;
325     bool r0ou = FALSE , r1ou = FALSE;
326
327         //fprintf(stderr, "%s:%d: getting free ptr from ic = %c\n", __FUNCTION__, __LINE__, ic->op);
328
329     /* the logic: if r0 & r1 used in the instruction
330     then we are in trouble otherwise */
331
332     /* first check if r0 & r1 are used by this
333     instruction, in which case we are in trouble */
334     if ((r0iu = bitVectBitValue(ic->rUsed,R0_IDX)) &&
335         (r1iu = bitVectBitValue(ic->rUsed,R1_IDX))) 
336     {
337         goto endOfWorld;      
338     }
339
340     r0ou = bitVectBitValue(ic->rMask,R0_IDX);
341     r1ou = bitVectBitValue(ic->rMask,R1_IDX);
342
343     /* if no usage of r0 then return it */
344     if (!r0iu && !r0ou) {
345         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
346         (*aopp)->type = AOP_R0;
347         
348         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
349     }
350
351     /* if no usage of r1 then return it */
352     if (!r1iu && !r1ou) {
353         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
354         (*aopp)->type = AOP_R1;
355
356         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R1_IDX);
357     }    
358
359     /* now we know they both have usage */
360     /* if r0 not used in this instruction */
361     if (!r0iu) {
362         /* push it if not already pushed */
363         if (!_G.r0Pushed) {
364           //pic16_emitcode ("push","%s",
365           //          pic16_regWithIdx(R0_IDX)->dname);
366             _G.r0Pushed++ ;
367         }
368         
369         ic->rUsed = bitVectSetBit(ic->rUsed,R0_IDX);
370         (*aopp)->type = AOP_R0;
371
372         return (*aopp)->aopu.aop_ptr = pic16_regWithIdx(R0_IDX);
373     }
374
375     /* if r1 not used then */
376
377     if (!r1iu) {
378         /* push it if not already pushed */
379         if (!_G.r1Pushed) {
380           //pic16_emitcode ("push","%s",
381           //          pic16_regWithIdx(R1_IDX)->dname);
382             _G.r1Pushed++ ;
383         }
384         
385         ic->rUsed = bitVectSetBit(ic->rUsed,R1_IDX);
386         (*aopp)->type = AOP_R1;
387         return pic16_regWithIdx(R1_IDX);
388     }
389
390 endOfWorld :
391     /* I said end of world but not quite end of world yet */
392     /* if this is a result then we can push it on the stack*/
393     if (result) {
394         (*aopp)->type = AOP_STK;    
395         return NULL;
396     }
397
398     /* other wise this is true end of the world */
399     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
400            "getFreePtr should never reach here");
401     exit(0);
402 }
403
404 /*-----------------------------------------------------------------*/
405 /* newAsmop - creates a new asmOp                                  */
406 /*-----------------------------------------------------------------*/
407 static asmop *newAsmop (short type)
408 {
409     asmop *aop;
410
411     aop = Safe_calloc(1,sizeof(asmop));
412     aop->type = type;
413     return aop;
414 }
415
416 static void genSetDPTR(int n)
417 {
418     if (!n)
419     {
420         pic16_emitcode(";", "Select standard DPTR");
421         pic16_emitcode("mov", "dps, #0x00");
422     }
423     else
424     {
425         pic16_emitcode(";", "Select alternate DPTR");
426         pic16_emitcode("mov", "dps, #0x01");
427     }
428 }
429
430 /*-----------------------------------------------------------------*/
431 /* resolveIfx - converts an iCode ifx into a form more useful for  */
432 /*              generating code                                    */
433 /*-----------------------------------------------------------------*/
434 static void resolveIfx(resolvedIfx *resIfx, iCode *ifx)
435 {
436   if(!resIfx) 
437     return;
438
439   //  DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
440
441   resIfx->condition = 1;    /* assume that the ifx is true */
442   resIfx->generated = 0;    /* indicate that the ifx has not been used */
443
444   if(!ifx) {
445     resIfx->lbl = newiTempLabel(NULL);  /* oops, there is no ifx. so create a label */
446 /*
447     DEBUGpic16_emitcode("; ***","%s %d null ifx creating new label key =%d",
448                         __FUNCTION__,__LINE__,resIfx->lbl->key);
449 */
450   } else {
451     if(IC_TRUE(ifx)) {
452       resIfx->lbl = IC_TRUE(ifx);
453     } else {
454       resIfx->lbl = IC_FALSE(ifx);
455       resIfx->condition = 0;
456     }
457 /*
458     if(IC_TRUE(ifx)) 
459       DEBUGpic16_emitcode("; ***","ifx true is non-null");
460     if(IC_FALSE(ifx)) 
461       DEBUGpic16_emitcode("; ***","ifx false is non-null");
462 */
463   }
464
465   //  DEBUGpic16_emitcode("; ***","%s lbl->key=%d, (lab offset=%d)",__FUNCTION__,resIfx->lbl->key,labelOffset);
466
467 }
468 /*-----------------------------------------------------------------*/
469 /* pointerCode - returns the code for a pointer type               */
470 /*-----------------------------------------------------------------*/
471 static int pointerCode (sym_link *etype)
472 {
473
474     return PTR_TYPE(SPEC_OCLS(etype));
475
476 }
477
478 /*-----------------------------------------------------------------*/
479 /* aopForSym - for a true symbol                                   */
480 /*-----------------------------------------------------------------*/
481 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
482 {
483     asmop *aop;
484     memmap *space= SPEC_OCLS(sym->etype);
485
486     DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
487     /* if already has one */
488     if (sym->aop) {
489             DEBUGpic16_emitcode("; ***", "already has sym %s %d", __FUNCTION__, __LINE__);
490         return sym->aop;
491     }
492
493     /* assign depending on the storage class */
494     /* if it is on the stack or indirectly addressable */
495     /* space we need to assign either r0 or r1 to it   */    
496     if ((sym->onStack && !options.stack10bit) || sym->iaccess) {
497         sym->aop = aop = newAsmop(0);
498         aop->aopu.aop_ptr = getFreePtr(ic,&aop,result);
499         aop->size = getSize(sym->type);
500
501         /* now assign the address of the variable to 
502         the pointer register */
503         if (aop->type != AOP_STK) {
504
505             if (sym->onStack) {
506                     if ( _G.accInUse )
507                         pic16_emitcode("push","acc");
508
509                     pic16_emitcode("mov","a,_bp");
510                     pic16_emitcode("add","a,#0x%02x",
511                              ((sym->stack < 0) ?
512                               ((char)(sym->stack - _G.nRegsSaved )) :
513                               ((char)sym->stack)) & 0xff);
514                     pic16_emitcode("mov","%s,a",
515                              aop->aopu.aop_ptr->name);
516
517                     if ( _G.accInUse )
518                         pic16_emitcode("pop","acc");
519             } else
520                 pic16_emitcode("mov","%s,#%s",
521                          aop->aopu.aop_ptr->name,
522                          sym->rname);
523             aop->paged = space->paged;
524         } else
525             aop->aopu.aop_stk = sym->stack;
526         return aop;
527     }
528     
529     if (sym->onStack && options.stack10bit)
530     {
531         /* It's on the 10 bit stack, which is located in
532          * far data space.
533          */
534          
535       //DEBUGpic16_emitcode(";","%d",__LINE__);
536
537         if ( _G.accInUse )
538                 pic16_emitcode("push","acc");
539
540         pic16_emitcode("mov","a,_bp");
541         pic16_emitcode("add","a,#0x%02x",
542                  ((sym->stack < 0) ?
543                    ((char)(sym->stack - _G.nRegsSaved )) :
544                    ((char)sym->stack)) & 0xff);
545         
546         genSetDPTR(1);
547         pic16_emitcode ("mov","dpx1,#0x40");
548         pic16_emitcode ("mov","dph1,#0x00");
549         pic16_emitcode ("mov","dpl1, a");
550         genSetDPTR(0);
551         
552         if ( _G.accInUse )
553             pic16_emitcode("pop","acc");
554             
555         sym->aop = aop = newAsmop(AOP_DPTR2);
556         aop->size = getSize(sym->type); 
557         return aop;
558     }
559
560     //DEBUGpic16_emitcode(";","%d",__LINE__);
561     /* if in bit space */
562     if (IN_BITSPACE(space)) {
563         sym->aop = aop = newAsmop (AOP_CRY);
564         aop->aopu.aop_dir = sym->rname ;
565         aop->size = getSize(sym->type);
566         //DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
567         return aop;
568     }
569     /* if it is in direct space */
570     if (IN_DIRSPACE(space)) {
571         sym->aop = aop = newAsmop (AOP_DIR);
572         aop->aopu.aop_dir = sym->rname ;
573         aop->size = getSize(sym->type);
574         DEBUGpic16_emitcode(";","%d sym->rname = %s, size = %d",__LINE__,sym->rname,aop->size);
575         return aop;
576     }
577
578     /* special case for a function */
579     if (IS_FUNC(sym->type)) {   
580         sym->aop = aop = newAsmop(AOP_IMMD);    
581         //_ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
582         aop->aopu.aop_immd = Safe_calloc(1,strlen(sym->rname)+1);
583         strcpy(aop->aopu.aop_immd,sym->rname);
584         aop->size = FPTRSIZE; 
585         DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
586         return aop;
587     }
588
589
590     /* only remaining is far space */
591     /* in which case DPTR gets the address */
592     sym->aop = aop = newAsmop(AOP_PCODE);
593
594     aop->aopu.pcop = pic16_popGetImmd(sym->rname,0,0);
595     PCOI(aop->aopu.pcop)->_const = IN_CODESPACE(space);
596     PCOI(aop->aopu.pcop)->index = 0;
597
598     DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
599                         __LINE__,sym->rname, 0, PCOI(aop->aopu.pcop)->_const);
600
601     pic16_allocDirReg (IC_LEFT(ic));
602
603     aop->size = FPTRSIZE; 
604 /*
605     DEBUGpic16_emitcode(";","%d size = %d, name =%s",__LINE__,aop->size,sym->rname);
606     sym->aop = aop = newAsmop(AOP_DPTR);
607     pic16_emitcode ("mov","dptr,#%s", sym->rname);
608     aop->size = getSize(sym->type);
609
610     DEBUGpic16_emitcode(";","%d size = %d",__LINE__,aop->size);
611 */
612
613     /* if it is in code space */
614     if (IN_CODESPACE(space))
615         aop->code = 1;
616
617     return aop;     
618 }
619
620 /*-----------------------------------------------------------------*/
621 /* aopForRemat - rematerialzes an object                           */
622 /*-----------------------------------------------------------------*/
623 static asmop *aopForRemat (operand *op) // x symbol *sym)
624 {
625   symbol *sym = OP_SYMBOL(op);
626   iCode *ic = NULL;
627   asmop *aop = newAsmop(AOP_PCODE);
628   int val = 0;
629   int offset = 0;
630
631   ic = sym->rematiCode;
632
633   DEBUGpic16_emitcode(";","%s %d",__FUNCTION__,__LINE__);
634   if(IS_OP_POINTER(op)) {
635     DEBUGpic16_emitcode(";","%s %d IS_OP_POINTER",__FUNCTION__,__LINE__);
636   }
637   for (;;) {
638     if (ic->op == '+') {
639       val += (int) operandLitValue(IC_RIGHT(ic));
640     } else if (ic->op == '-') {
641       val -= (int) operandLitValue(IC_RIGHT(ic));
642     } else
643       break;
644         
645     ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
646   }
647
648   offset = OP_SYMBOL(IC_LEFT(ic))->offset;
649   aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
650 #if 0
651   PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
652 #else
653   PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
654 #endif
655   PCOI(aop->aopu.pcop)->index = val;
656
657   DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
658                       __LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
659 #if 0
660                       val, IS_PTR_CONST(operandType(op)));
661 #else
662                       val, IS_CODEPTR(operandType(op)));
663 #endif
664
665   //    DEBUGpic16_emitcode(";","aop type  %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
666
667   pic16_allocDirReg (IC_LEFT(ic));
668
669   return aop;        
670 }
671
672 static int aopIdx (asmop *aop, int offset)
673 {
674   if(!aop)
675     return -1;
676
677   if(aop->type !=  AOP_REG)
678     return -2;
679         
680   return aop->aopu.aop_reg[offset]->rIdx;
681
682 }
683 /*-----------------------------------------------------------------*/
684 /* regsInCommon - two operands have some registers in common       */
685 /*-----------------------------------------------------------------*/
686 static bool regsInCommon (operand *op1, operand *op2)
687 {
688     symbol *sym1, *sym2;
689     int i;
690
691     /* if they have registers in common */
692     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
693         return FALSE ;
694
695     sym1 = OP_SYMBOL(op1);
696     sym2 = OP_SYMBOL(op2);
697
698     if (sym1->nRegs == 0 || sym2->nRegs == 0)
699         return FALSE ;
700
701     for (i = 0 ; i < sym1->nRegs ; i++) {
702         int j;
703         if (!sym1->regs[i])
704             continue ;
705
706         for (j = 0 ; j < sym2->nRegs ;j++ ) {
707             if (!sym2->regs[j])
708                 continue ;
709
710             if (sym2->regs[j] == sym1->regs[i])
711                 return TRUE ;
712         }
713     }
714
715     return FALSE ;
716 }
717
718 /*-----------------------------------------------------------------*/
719 /* operandsEqu - equivalent                                        */
720 /*-----------------------------------------------------------------*/
721 static bool operandsEqu ( operand *op1, operand *op2)
722 {
723     symbol *sym1, *sym2;
724
725     /* if they not symbols */
726     if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
727         return FALSE;
728
729     sym1 = OP_SYMBOL(op1);
730     sym2 = OP_SYMBOL(op2);
731
732     /* if both are itemps & one is spilt
733        and the other is not then false */
734     if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
735         sym1->isspilt != sym2->isspilt )
736         return FALSE ;
737
738     /* if they are the same */
739     if (sym1 == sym2)
740         return TRUE ;
741
742     if (strcmp(sym1->rname,sym2->rname) == 0)
743         return TRUE;
744
745
746     /* if left is a tmp & right is not */
747     if (IS_ITEMP(op1)  && 
748         !IS_ITEMP(op2) &&
749         sym1->isspilt  &&
750         (sym1->usl.spillLoc == sym2))
751         return TRUE;
752
753     if (IS_ITEMP(op2)  && 
754         !IS_ITEMP(op1) &&
755         sym2->isspilt  &&
756         sym1->level > 0 &&
757         (sym2->usl.spillLoc == sym1))
758         return TRUE ;
759
760     return FALSE ;
761 }
762
763 /*-----------------------------------------------------------------*/
764 /* pic16_sameRegs - two asmops have the same registers                   */
765 /*-----------------------------------------------------------------*/
766 bool pic16_sameRegs (asmop *aop1, asmop *aop2 )
767 {
768     int i;
769
770     if (aop1 == aop2)
771         return TRUE ;
772
773     if (aop1->type != AOP_REG ||
774         aop2->type != AOP_REG )
775         return FALSE ;
776
777     if (aop1->size != aop2->size )
778         return FALSE ;
779
780     for (i = 0 ; i < aop1->size ; i++ )
781         if (aop1->aopu.aop_reg[i] !=
782             aop2->aopu.aop_reg[i] )
783             return FALSE ;
784
785     return TRUE ;
786 }
787
788 /*-----------------------------------------------------------------*/
789 /* pic16_aopOp - allocates an asmop for an operand  :                    */
790 /*-----------------------------------------------------------------*/
791 void pic16_aopOp (operand *op, iCode *ic, bool result)
792 {
793     asmop *aop;
794     symbol *sym;
795     int i;
796
797     if (!op)
798         return ;
799
800 //      DEBUGpic16_emitcode(";","%d",__LINE__);
801
802     /* if this a literal */
803     if (IS_OP_LITERAL(op)) {
804         op->aop = aop = newAsmop(AOP_LIT);
805         aop->aopu.aop_lit = op->operand.valOperand;
806         aop->size = getSize(operandType(op));
807         return;
808     }
809
810     {
811       sym_link *type = operandType(op);
812 #if 0
813       if(IS_PTR_CONST(type))
814 #else
815       if(IS_CODEPTR(type))
816 #endif
817         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
818     }
819
820     /* if already has a asmop then continue */
821     if (op->aop)
822         return ;
823
824     /* if the underlying symbol has a aop */
825     if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
826       DEBUGpic16_emitcode(";","%d has symbol",__LINE__);
827         op->aop = OP_SYMBOL(op)->aop;
828         return;
829     }
830
831     /* if this is a true symbol */
832     if (IS_TRUE_SYMOP(op)) {    
833         DEBUGpic16_emitcode(";","%d - true symop",__LINE__);
834       op->aop = aopForSym(ic,OP_SYMBOL(op),result);
835       return ;
836     }
837
838     /* this is a temporary : this has
839     only four choices :
840     a) register
841     b) spillocation
842     c) rematerialize 
843     d) conditional   
844     e) can be a return use only */
845
846     sym = OP_SYMBOL(op);
847
848         DEBUGpic16_emitcode("; ***", "%d: symbol name = %s", __LINE__, sym->name);
849     /* if the type is a conditional */
850     if (sym->regType == REG_CND) {
851         aop = op->aop = sym->aop = newAsmop(AOP_CRY);
852         aop->size = 0;
853         return;
854     }
855
856     /* if it is spilt then two situations
857     a) is rematerialize 
858     b) has a spill location */
859     if (sym->isspilt || sym->nRegs == 0) {
860
861       DEBUGpic16_emitcode(";","%d",__LINE__);
862         /* rematerialize it NOW */
863         if (sym->remat) {
864
865             sym->aop = op->aop = aop =
866                                       aopForRemat (op);
867             aop->size = getSize(sym->type);
868             //DEBUGpic16_emitcode(";"," %d: size %d, %s\n",__LINE__,aop->size,aop->aopu.aop_immd);
869             return;
870         }
871
872         if (sym->accuse) {
873             int i;
874             aop = op->aop = sym->aop = newAsmop(AOP_ACC);
875             aop->size = getSize(sym->type);
876             for ( i = 0 ; i < 2 ; i++ )
877                 aop->aopu.aop_str[i] = accUse[i];
878             DEBUGpic16_emitcode(";","%d size=%d",__LINE__,aop->size);
879             return;  
880         }
881
882         if (sym->ruonly ) {
883           /*
884           sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
885           aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
886           //pic16_allocDirReg (IC_LEFT(ic));
887           aop->size = getSize(sym->type);
888           */
889
890           unsigned i;
891
892           aop = op->aop = sym->aop = newAsmop(AOP_STR);
893           aop->size = getSize(sym->type);
894           for ( i = 0 ; i < pic16_fReturnSizePic ; i++ )
895             aop->aopu.aop_str[i] = fReturn[i];
896
897           DEBUGpic16_emitcode(";","%d",__LINE__);
898           return;
899         }
900
901         /* else spill location  */
902         if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
903             /* force a new aop if sizes differ */
904             sym->usl.spillLoc->aop = NULL;
905         }
906         DEBUGpic16_emitcode(";","%s %d %s sym->rname = %s, offset %d",
907                             __FUNCTION__,__LINE__,
908                             sym->usl.spillLoc->rname,
909                             sym->rname, sym->usl.spillLoc->offset);
910
911         sym->aop = op->aop = aop = newAsmop(AOP_PCODE);
912         //aop->aopu.pcop = pic16_popGetImmd(sym->usl.spillLoc->rname,0,sym->usl.spillLoc->offset);
913         aop->aopu.pcop = pic16_popRegFromString(sym->usl.spillLoc->rname, 
914                                           getSize(sym->type), 
915                                           sym->usl.spillLoc->offset);
916         aop->size = getSize(sym->type);
917
918         return;
919     }
920
921     {
922       sym_link *type = operandType(op);
923 #if 0
924       if(IS_PTR_CONST(type)) 
925 #else
926       if(IS_CODEPTR(type)) 
927 #endif
928         DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
929     }
930
931     /* must be in a register */
932     DEBUGpic16_emitcode(";","%d register type nRegs=%d",__LINE__,sym->nRegs);
933     sym->aop = op->aop = aop = newAsmop(AOP_REG);
934     aop->size = sym->nRegs;
935     for ( i = 0 ; i < sym->nRegs ;i++)
936         aop->aopu.aop_reg[i] = sym->regs[i];
937 }
938
939 /*-----------------------------------------------------------------*/
940 /* pic16_freeAsmop - free up the asmop given to an operand               */
941 /*----------------------------------------------------------------*/
942 void pic16_freeAsmop (operand *op, asmop *aaop, iCode *ic, bool pop)
943 {   
944     asmop *aop ;
945
946     if (!op)
947         aop = aaop;
948     else 
949         aop = op->aop;
950
951     if (!aop)
952         return ;
953
954     if (aop->freed)
955         goto dealloc; 
956
957     aop->freed = 1;
958
959     /* depending on the asmop type only three cases need work AOP_RO
960        , AOP_R1 && AOP_STK */
961 #if 0
962     switch (aop->type) {
963         case AOP_R0 :
964             if (_G.r0Pushed ) {
965                 if (pop) {
966                     pic16_emitcode ("pop","ar0");     
967                     _G.r0Pushed--;
968                 }
969             }
970             bitVectUnSetBit(ic->rUsed,R0_IDX);
971             break;
972
973         case AOP_R1 :
974             if (_G.r1Pushed ) {
975                 if (pop) {
976                     pic16_emitcode ("pop","ar1");
977                     _G.r1Pushed--;
978                 }
979             }
980             bitVectUnSetBit(ic->rUsed,R1_IDX);          
981             break;
982
983         case AOP_STK :
984         {
985             int sz = aop->size;    
986             int stk = aop->aopu.aop_stk + aop->size;
987             bitVectUnSetBit(ic->rUsed,R0_IDX);
988             bitVectUnSetBit(ic->rUsed,R1_IDX);          
989
990             getFreePtr(ic,&aop,FALSE);
991             
992             if (options.stack10bit)
993             {
994                 /* I'm not sure what to do here yet... */
995                 /* #STUB */
996                 fprintf(stderr, 
997                         "*** Warning: probably generating bad code for "
998                         "10 bit stack mode.\n");
999             }
1000             
1001             if (stk) {
1002                 pic16_emitcode ("mov","a,_bp");
1003                 pic16_emitcode ("add","a,#0x%02x",((char)stk) & 0xff);
1004                 pic16_emitcode ("mov","%s,a",aop->aopu.aop_ptr->name);
1005             } else {
1006                 pic16_emitcode ("mov","%s,_bp",aop->aopu.aop_ptr->name);
1007             }
1008
1009             while (sz--) {
1010                 pic16_emitcode("pop","acc");
1011                 pic16_emitcode("mov","@%s,a",aop->aopu.aop_ptr->name);
1012                 if (!sz) break;
1013                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1014             }
1015             op->aop = aop;
1016             pic16_freeAsmop(op,NULL,ic,TRUE);
1017             if (_G.r0Pushed) {
1018                 pic16_emitcode("pop","ar0");
1019                 _G.r0Pushed--;
1020             }
1021
1022             if (_G.r1Pushed) {
1023                 pic16_emitcode("pop","ar1");
1024                 _G.r1Pushed--;
1025             }       
1026         }
1027     }
1028 #endif
1029
1030 dealloc:
1031     /* all other cases just dealloc */
1032     if (op ) {
1033         op->aop = NULL;
1034         if (IS_SYMOP(op)) {
1035             OP_SYMBOL(op)->aop = NULL;    
1036             /* if the symbol has a spill */
1037             if (SPIL_LOC(op))
1038                 SPIL_LOC(op)->aop = NULL;
1039         }
1040     }
1041 }
1042
1043 /*-----------------------------------------------------------------*/
1044 /* pic16_aopGet - for fetching value of the aop                          */
1045 /*-----------------------------------------------------------------*/
1046 char *pic16_aopGet (asmop *aop, int offset, bool bit16, bool dname)
1047 {
1048     char *s = buffer ;
1049     char *rs;
1050
1051     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1052     /* offset is greater than
1053     size then zero */
1054     if (offset > (aop->size - 1) &&
1055         aop->type != AOP_LIT)
1056         return zero;
1057
1058     /* depending on type */
1059     switch (aop->type) {
1060         
1061     case AOP_R0:
1062     case AOP_R1:
1063         DEBUGpic16_emitcode(";","%d",__LINE__);
1064         /* if we need to increment it */       
1065         while (offset > aop->coff) {        
1066             pic16_emitcode ("inc","%s",aop->aopu.aop_ptr->name);  
1067             aop->coff++;
1068         }
1069         
1070         while (offset < aop->coff) {
1071             pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1072             aop->coff--;
1073         }
1074         
1075         aop->coff = offset ;
1076         if (aop->paged) {
1077             pic16_emitcode("movx","a,@%s",aop->aopu.aop_ptr->name);
1078             return (dname ? "acc" : "a");
1079         }       
1080         sprintf(s,"@%s",aop->aopu.aop_ptr->name);
1081         rs = Safe_calloc(1,strlen(s)+1);
1082         strcpy(rs,s);   
1083         return rs;
1084         
1085     case AOP_DPTR:
1086     case AOP_DPTR2:
1087         DEBUGpic16_emitcode(";","%d",__LINE__);
1088     if (aop->type == AOP_DPTR2)
1089     {
1090         genSetDPTR(1);
1091     }
1092     
1093         while (offset > aop->coff) {
1094             pic16_emitcode ("inc","dptr");
1095             aop->coff++;
1096         }
1097         
1098         while (offset < aop->coff) {        
1099             pic16_emitcode("lcall","__decdptr");
1100             aop->coff--;
1101         }
1102         
1103         aop->coff = offset;
1104         if (aop->code) {
1105             pic16_emitcode("clr","a");
1106             pic16_emitcode("movc","a,@a+dptr");
1107         }
1108     else {
1109             pic16_emitcode("movx","a,@dptr");
1110     }
1111             
1112     if (aop->type == AOP_DPTR2)
1113     {
1114         genSetDPTR(0);
1115     }
1116             
1117     return (dname ? "acc" : "a");
1118         
1119         
1120     case AOP_IMMD:
1121         if (bit16) 
1122             sprintf (s,"%s",aop->aopu.aop_immd);
1123         else
1124             if (offset) 
1125                 sprintf(s,"(%s >> %d)",
1126                         aop->aopu.aop_immd,
1127                         offset*8);
1128             else
1129                 sprintf(s,"%s",
1130                         aop->aopu.aop_immd);
1131         DEBUGpic16_emitcode(";","%d immd %s",__LINE__,s);
1132         rs = Safe_calloc(1,strlen(s)+1);
1133         strcpy(rs,s);   
1134         return rs;
1135         
1136     case AOP_DIR:
1137       if (offset) {
1138         sprintf(s,"(%s + %d)",
1139                 aop->aopu.aop_dir,
1140                 offset);
1141         DEBUGpic16_emitcode(";","oops AOP_DIR did this %s\n",s);
1142       } else
1143             sprintf(s,"%s",aop->aopu.aop_dir);
1144         rs = Safe_calloc(1,strlen(s)+1);
1145         strcpy(rs,s);   
1146         return rs;
1147         
1148     case AOP_REG:
1149       //if (dname) 
1150       //    return aop->aopu.aop_reg[offset]->dname;
1151       //else
1152             return aop->aopu.aop_reg[offset]->name;
1153         
1154     case AOP_CRY:
1155       //pic16_emitcode(";","%d",__LINE__);
1156       return aop->aopu.aop_dir;
1157         
1158     case AOP_ACC:
1159         DEBUGpic16_emitcode(";Warning -pic port ignoring get(AOP_ACC)","%d",__LINE__);
1160         return "AOP_accumulator_bug";
1161
1162     case AOP_LIT:
1163         sprintf(s,"0x%02x", pic16aopLiteral (aop->aopu.aop_lit,offset));
1164         rs = Safe_calloc(1,strlen(s)+1);
1165         strcpy(rs,s);   
1166         return rs;
1167         
1168     case AOP_STR:
1169         aop->coff = offset ;
1170         if (strcmp(aop->aopu.aop_str[offset],"a") == 0 &&
1171             dname)
1172             return "acc";
1173         DEBUGpic16_emitcode(";","%d - %s",__LINE__, aop->aopu.aop_str[offset]);
1174         
1175         return aop->aopu.aop_str[offset];
1176         
1177     case AOP_PCODE:
1178       {
1179         pCodeOp *pcop = aop->aopu.pcop;
1180         DEBUGpic16_emitcode(";","%d: pic16_aopGet AOP_PCODE type %s",__LINE__,pic16_pCodeOpType(pcop));
1181         if(pcop->name) {
1182           DEBUGpic16_emitcode(";","%s offset %d",pcop->name,PCOI(pcop)->offset);
1183           //sprintf(s,"(%s+0x%02x)", pcop->name,PCOI(aop->aopu.pcop)->offset);
1184           sprintf(s,"%s", pcop->name);
1185         } else
1186           sprintf(s,"0x%02x", PCOI(aop->aopu.pcop)->offset);
1187
1188       }
1189       rs = Safe_calloc(1,strlen(s)+1);
1190       strcpy(rs,s);   
1191       return rs;
1192
1193     }
1194
1195     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1196            "aopget got unsupported aop->type");
1197     exit(0);
1198 }
1199
1200
1201 /*-----------------------------------------------------------------*/
1202 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1203 /*-----------------------------------------------------------------*/
1204 pCodeOp *pic16_popGetTempReg(void)
1205 {
1206
1207   pCodeOp *pcop;
1208
1209   pcop = pic16_newpCodeOp(NULL, PO_GPR_TEMP);
1210   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r) {
1211     PCOR(pcop)->r->wasUsed=1;
1212     PCOR(pcop)->r->isFree=0;
1213   }
1214
1215   return pcop;
1216 }
1217
1218 /*-----------------------------------------------------------------*/
1219 /* pic16_popGetTempReg - create a new temporary pCodeOp                  */
1220 /*-----------------------------------------------------------------*/
1221 void pic16_popReleaseTempReg(pCodeOp *pcop)
1222 {
1223
1224   if(pcop && pcop->type == PO_GPR_TEMP && PCOR(pcop)->r)
1225     PCOR(pcop)->r->isFree = 1;
1226
1227 }
1228 /*-----------------------------------------------------------------*/
1229 /* pic16_popGetLabel - create a new pCodeOp of type PO_LABEL             */
1230 /*-----------------------------------------------------------------*/
1231 pCodeOp *pic16_popGetLabel(unsigned int key)
1232 {
1233
1234   DEBUGpic16_emitcode ("; ***","%s  key=%d, label offset %d",__FUNCTION__,key, labelOffset);
1235
1236   if(key>max_key)
1237     max_key = key;
1238
1239   return pic16_newpCodeOpLabel(NULL,key+100+labelOffset);
1240 }
1241
1242 /*-----------------------------------------------------------------*/
1243 /* pic16_popCopyReg - copy a pcode operator                              */
1244 /*-----------------------------------------------------------------*/
1245 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc)
1246 {
1247   pCodeOpReg *pcor;
1248
1249   pcor = Safe_calloc(1,sizeof(pCodeOpReg) );
1250   pcor->pcop.type = pc->pcop.type;
1251   if(pc->pcop.name) {
1252     if(!(pcor->pcop.name = Safe_strdup(pc->pcop.name)))
1253       fprintf(stderr,"oops %s %d",__FILE__,__LINE__);
1254   } else
1255     pcor->pcop.name = NULL;
1256
1257   pcor->r = pc->r;
1258   pcor->rIdx = pc->rIdx;
1259   pcor->r->wasUsed=1;
1260
1261   //DEBUGpic16_emitcode ("; ***","%s  , copying %s, rIdx=%d",__FUNCTION__,pc->pcop.name,pc->rIdx);
1262
1263   return PCOP(pcor);
1264 }
1265
1266 /*-----------------------------------------------------------------*/
1267 /* pic16_popGetLit - asm operator to pcode operator conversion     */
1268 /*-----------------------------------------------------------------*/
1269 pCodeOp *pic16_popGetLit(unsigned int lit)
1270 {
1271   return pic16_newpCodeOpLit(lit);
1272 }
1273
1274 /*-----------------------------------------------------------------*/
1275 /* pic16_popGetLit2 - asm operator to pcode operator conversion    */
1276 /*-----------------------------------------------------------------*/
1277 pCodeOp *pic16_popGetLit2(unsigned int lit, pCodeOp *arg2)
1278 {
1279   return pic16_newpCodeOpLit2(lit, arg2);
1280 }
1281
1282
1283 /*-----------------------------------------------------------------*/
1284 /* pic16_popGetImmd - asm operator to pcode immediate conversion   */
1285 /*-----------------------------------------------------------------*/
1286 pCodeOp *pic16_popGetImmd(char *name, unsigned int offset, int index)
1287 {
1288
1289   return pic16_newpCodeOpImmd(name, offset,index, 0);
1290 }
1291
1292
1293 /*-----------------------------------------------------------------*/
1294 /* pic16_popGet - asm operator to pcode operator conversion              */
1295 /*-----------------------------------------------------------------*/
1296 pCodeOp *pic16_popGetWithString(char *str)
1297 {
1298   pCodeOp *pcop;
1299
1300
1301   if(!str) {
1302     fprintf(stderr,"NULL string %s %d\n",__FILE__,__LINE__);
1303     exit (1);
1304   }
1305
1306   pcop = pic16_newpCodeOp(str,PO_STR);
1307
1308   return pcop;
1309 }
1310
1311 /*-----------------------------------------------------------------*/
1312 /* pic16_popRegFromString -                                        */
1313 /*-----------------------------------------------------------------*/
1314 static pCodeOp *pic16_popRegFromString(char *str, int size, int offset)
1315 {
1316
1317   pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1318   pcop->type = PO_DIR;
1319
1320   DEBUGpic16_emitcode(";","%d %s %s",__LINE__, __FUNCTION__, str);
1321 //  fprintf(stderr, "%s:%d: register name = %s pos = %d/%d\n", __FUNCTION__, __LINE__, str, offset, size);
1322
1323   if(!str)
1324     str = "BAD_STRING";
1325
1326   pcop->name = Safe_calloc(1,strlen(str)+1);
1327   strcpy(pcop->name,str);
1328
1329   //pcop->name = Safe_strdup( ( (str) ? str : "BAD STRING"));
1330
1331   PCOR(pcop)->r = pic16_dirregWithName(pcop->name);
1332   if(PCOR(pcop)->r == NULL) {
1333 //      fprintf(stderr, "%s:%d - couldn't find %s in allocated regsters, size= %d ofs= %d\n",
1334 //              __FUNCTION__, __LINE__, str, size, offset);
1335     PCOR(pcop)->r = pic16_allocRegByName (pcop->name,size);
1336
1337         //fprintf(stderr, "allocating new register -> %s\n", str);
1338
1339     DEBUGpic16_emitcode(";","%d  %s   offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset);
1340   } else {
1341     DEBUGpic16_emitcode(";","%d  %s   offset=%d",__LINE__,pcop->name,offset);
1342   }
1343   PCOR(pcop)->instance = offset;
1344
1345   return pcop;
1346 }
1347
1348 static pCodeOp *pic16_popRegFromIdx(int rIdx)
1349 {
1350   pCodeOp *pcop;
1351
1352 //      DEBUGpic16_emitcode ("; ***","%s,%d\trIdx=0x%x", __FUNCTION__,__LINE__,rIdx);
1353
1354         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1355         PCOR(pcop)->rIdx = rIdx;
1356         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1357         PCOR(pcop)->r->isFree = 0;
1358         PCOR(pcop)->r->wasUsed = 1;
1359
1360         pcop->type = PCOR(pcop)->r->pc_type;
1361
1362   return pcop;
1363 }
1364
1365 /*---------------------------------------------------------------------------------*/
1366 /* pic16_popGet2 - a variant of pic16_popGet to handle two memory operand commands */
1367 /*                 VR 030601                                                       */
1368 /*---------------------------------------------------------------------------------*/
1369 pCodeOp *pic16_popGet2(asmop *aop_src, asmop *aop_dst, int offset)
1370 {
1371   pCodeOpReg2 *pcop2;
1372   pCodeOp *temp;
1373   
1374         pcop2 = (pCodeOpReg2 *)pic16_popGet(aop_src, offset);
1375
1376         /* comment the following check, so errors to throw up */
1377 //      if(!pcop2)return NULL;
1378
1379         temp = pic16_popGet(aop_dst, offset);
1380         pcop2->pcop2 = temp;
1381         
1382   return PCOP(pcop2);
1383 }
1384
1385 /*---------------------------------------------------------------------------------*/
1386 /* pic16_popCombine2 - combine two pCodeOpReg variables into one for use with      */
1387 /*                     movff instruction                                           */
1388 /*---------------------------------------------------------------------------------*/
1389 pCodeOp *pic16_popCombine2(pCodeOpReg *src, pCodeOpReg *dst, int noalloc)
1390 {
1391   pCodeOpReg2 *pcop2;
1392
1393         if(!noalloc) {
1394                 pcop2 = (pCodeOpReg2 *)pic16_popCopyReg(src);
1395                 pcop2->pcop2 = pic16_popCopyReg(dst);
1396         } else {
1397                 /* the pCodeOp may be already allocated */
1398                 pcop2 = (pCodeOpReg2 *)(src);
1399                 pcop2->pcop2 = (pCodeOp *)(dst);
1400         }
1401
1402   return PCOP(pcop2);
1403 }
1404
1405
1406 /*-----------------------------------------------------------------*/
1407 /* pic16_popGet - asm operator to pcode operator conversion              */
1408 /*-----------------------------------------------------------------*/
1409 pCodeOp *pic16_popGet (asmop *aop, int offset) //, bool bit16, bool dname)
1410 {
1411   //char *s = buffer ;
1412     //char *rs;
1413
1414     pCodeOp *pcop;
1415
1416     //DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1417     /* offset is greater than
1418     size then zero */
1419
1420     if (offset > (aop->size - 1) &&
1421         aop->type != AOP_LIT)
1422       return NULL;  //zero;
1423
1424     /* depending on type */
1425     switch (aop->type) {
1426         
1427     case AOP_R0:
1428     case AOP_R1:
1429     case AOP_DPTR:
1430     case AOP_DPTR2:
1431     case AOP_ACC:
1432         DEBUGpic16_emitcode(";8051 legacy","%d type = %s",__LINE__,pic16_AopType(aop->type));
1433         fprintf(stderr, ";8051 legacy %d type = %s\n",__LINE__,pic16_AopType(aop->type));
1434         return NULL;
1435         
1436     case AOP_IMMD:
1437       DEBUGpic16_emitcode(";","%d\tAOP_IMMD",__LINE__);
1438       return pic16_popGetImmd(aop->aopu.aop_immd,offset,0);
1439
1440     case AOP_DIR:
1441       DEBUGpic16_emitcode(";","%d\tAOP_DIR", __LINE__);
1442       return pic16_popRegFromString(aop->aopu.aop_dir, aop->size, offset);
1443         
1444     case AOP_REG:
1445       {
1446         int rIdx = aop->aopu.aop_reg[offset]->rIdx;
1447
1448         DEBUGpic16_emitcode(";","%d\tAOP_REG", __LINE__);
1449         pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1450         PCOR(pcop)->rIdx = rIdx;
1451         PCOR(pcop)->r = pic16_regWithIdx(rIdx);
1452         PCOR(pcop)->r->wasUsed=1;
1453         PCOR(pcop)->r->isFree=0;
1454
1455         PCOR(pcop)->instance = offset;
1456         pcop->type = PCOR(pcop)->r->pc_type;
1457         //rs = aop->aopu.aop_reg[offset]->name;
1458         //DEBUGpic16_emitcode(";","%d regiser idx = %d name =%s",__LINE__,rIdx,rs);
1459         return pcop;
1460       }
1461
1462     case AOP_CRY:
1463         DEBUGpic16_emitcode(";","%d\tAOP_CRY", __LINE__);
1464
1465       pcop = pic16_newpCodeOpBit(aop->aopu.aop_dir,-1,1);
1466       PCOR(pcop)->r = pic16_dirregWithName(aop->aopu.aop_dir);
1467       //if(PCOR(pcop)->r == NULL)
1468       //fprintf(stderr,"%d - couldn't find %s in allocated registers\n",__LINE__,aop->aopu.aop_dir);
1469       return pcop;
1470         
1471     case AOP_LIT:
1472         DEBUGpic16_emitcode(";","%d\tAOP_LIT", __LINE__);
1473       return pic16_newpCodeOpLit(pic16aopLiteral (aop->aopu.aop_lit,offset));
1474
1475     case AOP_STR:
1476       DEBUGpic16_emitcode(";","%d AOP_STR %s",__LINE__,aop->aopu.aop_str[offset]);
1477       return pic16_newpCodeOpRegFromStr(aop->aopu.aop_str[offset]);
1478
1479       /*
1480       pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1481       PCOR(pcop)->r = pic16_allocRegByName(aop->aopu.aop_str[offset]);
1482       PCOR(pcop)->rIdx = PCOR(pcop)->r->rIdx;
1483       pcop->type = PCOR(pcop)->r->pc_type;
1484       pcop->name = PCOR(pcop)->r->name;
1485
1486       return pcop;
1487       */
1488
1489     case AOP_PCODE:
1490       DEBUGpic16_emitcode(";","pic16_popGet AOP_PCODE (%s) %d %s",pic16_pCodeOpType(aop->aopu.pcop),
1491                           __LINE__, 
1492                           ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name"));
1493       pcop = pic16_pCodeOpCopy(aop->aopu.pcop);
1494       PCOI(pcop)->offset = offset;
1495       return pcop;
1496     }
1497
1498     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1499            "pic16_popGet got unsupported aop->type");
1500     exit(0);
1501 }
1502 /*-----------------------------------------------------------------*/
1503 /* pic16_aopPut - puts a string for a aop                                */
1504 /*-----------------------------------------------------------------*/
1505 void pic16_aopPut (asmop *aop, char *s, int offset)
1506 {
1507     char *d = buffer ;
1508     symbol *lbl ;
1509
1510     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1511
1512     if (aop->size && offset > ( aop->size - 1)) {
1513         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1514                "pic16_aopPut got offset > aop->size");
1515         exit(0);
1516     }
1517
1518     /* will assign value to value */
1519     /* depending on where it is ofcourse */
1520     switch (aop->type) {
1521     case AOP_DIR:
1522       if (offset) {
1523         sprintf(d,"(%s + %d)",
1524                 aop->aopu.aop_dir,offset);
1525         fprintf(stderr,"oops pic16_aopPut:AOP_DIR did this %s\n",s);
1526
1527       } else
1528             sprintf(d,"%s",aop->aopu.aop_dir);
1529         
1530         if (strcmp(d,s)) {
1531           DEBUGpic16_emitcode(";","%d",__LINE__);
1532           if(strcmp(s,"W"))
1533             pic16_emitcode("movf","%s,w",s);
1534           pic16_emitcode("movwf","%s",d);
1535
1536           if(strcmp(s,"W")) {
1537             pic16_emitcode(";BUG!? should have this:movf","%s,w   %d",s,__LINE__);
1538             if(offset >= aop->size) {
1539               pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1540               break;
1541             } else
1542               pic16_emitpcode(POC_MOVLW,pic16_popGetImmd(s,offset,0));
1543           }
1544
1545           pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1546
1547
1548         }
1549         break;
1550         
1551     case AOP_REG:
1552       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) { // &&
1553         //strcmp(aop->aopu.aop_reg[offset]->dname,s)!= 0){
1554           /*
1555             if (*s == '@'           ||
1556                 strcmp(s,"r0") == 0 ||
1557                 strcmp(s,"r1") == 0 ||
1558                 strcmp(s,"r2") == 0 ||
1559                 strcmp(s,"r3") == 0 ||
1560                 strcmp(s,"r4") == 0 ||
1561                 strcmp(s,"r5") == 0 ||
1562                 strcmp(s,"r6") == 0 || 
1563                 strcmp(s,"r7") == 0 )
1564                 pic16_emitcode("mov","%s,%s  ; %d",
1565                          aop->aopu.aop_reg[offset]->dname,s,__LINE__);
1566             else
1567           */
1568
1569           if(strcmp(s,"W")==0 )
1570             pic16_emitcode("movf","%s,w  ; %d",s,__LINE__);
1571
1572           pic16_emitcode("movwf","%s",
1573                    aop->aopu.aop_reg[offset]->name);
1574
1575           if(strcmp(s,zero)==0) {
1576             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1577
1578           } else if(strcmp(s,"W")==0) {
1579             pCodeOp *pcop = Safe_calloc(1,sizeof(pCodeOpReg) );
1580             pcop->type = PO_GPR_REGISTER;
1581
1582             PCOR(pcop)->rIdx = -1;
1583             PCOR(pcop)->r = NULL;
1584
1585             DEBUGpic16_emitcode(";","%d",__LINE__);
1586             pcop->name = Safe_strdup(s);
1587             pic16_emitpcode(POC_MOVFW,pcop);
1588             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1589           } else if(strcmp(s,one)==0) {
1590             pic16_emitpcode(POC_CLRF,pic16_popGet(aop,offset));
1591             pic16_emitpcode(POC_INCF,pic16_popGet(aop,offset));
1592           } else {
1593             pic16_emitpcode(POC_MOVWF,pic16_popGet(aop,offset));
1594           }
1595         }
1596         break;
1597         
1598     case AOP_DPTR:
1599     case AOP_DPTR2:
1600     
1601     if (aop->type == AOP_DPTR2)
1602     {
1603         genSetDPTR(1);
1604     }
1605     
1606         if (aop->code) {
1607             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1608                    "pic16_aopPut writting to code space");
1609             exit(0);
1610         }
1611         
1612         while (offset > aop->coff) {
1613             aop->coff++;
1614             pic16_emitcode ("inc","dptr");
1615         }
1616         
1617         while (offset < aop->coff) {
1618             aop->coff-- ;
1619             pic16_emitcode("lcall","__decdptr");
1620         }
1621         
1622         aop->coff = offset;
1623         
1624         /* if not in accumulater */
1625         MOVA(s);        
1626         
1627         pic16_emitcode ("movx","@dptr,a");
1628         
1629     if (aop->type == AOP_DPTR2)
1630     {
1631         genSetDPTR(0);
1632     }
1633         break;
1634         
1635     case AOP_R0:
1636     case AOP_R1:
1637         while (offset > aop->coff) {
1638             aop->coff++;
1639             pic16_emitcode("inc","%s",aop->aopu.aop_ptr->name);
1640         }
1641         while (offset < aop->coff) {
1642             aop->coff-- ;
1643             pic16_emitcode ("dec","%s",aop->aopu.aop_ptr->name);
1644         }
1645         aop->coff = offset;
1646         
1647         if (aop->paged) {
1648             MOVA(s);           
1649             pic16_emitcode("movx","@%s,a",aop->aopu.aop_ptr->name);
1650             
1651         } else
1652             if (*s == '@') {
1653                 MOVA(s);
1654                 pic16_emitcode("mov","@%s,a ; %d",aop->aopu.aop_ptr->name,__LINE__);
1655             } else
1656                 if (strcmp(s,"r0") == 0 ||
1657                     strcmp(s,"r1") == 0 ||
1658                     strcmp(s,"r2") == 0 ||
1659                     strcmp(s,"r3") == 0 ||
1660                     strcmp(s,"r4") == 0 ||
1661                     strcmp(s,"r5") == 0 ||
1662                     strcmp(s,"r6") == 0 || 
1663                     strcmp(s,"r7") == 0 ) {
1664                     char buffer[10];
1665                     sprintf(buffer,"a%s",s);
1666                     pic16_emitcode("mov","@%s,%s",
1667                              aop->aopu.aop_ptr->name,buffer);
1668                 } else
1669                     pic16_emitcode("mov","@%s,%s",aop->aopu.aop_ptr->name,s);
1670         
1671         break;
1672         
1673     case AOP_STK:
1674         if (strcmp(s,"a") == 0)
1675             pic16_emitcode("push","acc");
1676         else
1677             pic16_emitcode("push","%s",s);
1678         
1679         break;
1680         
1681     case AOP_CRY:
1682         /* if bit variable */
1683         if (!aop->aopu.aop_dir) {
1684             pic16_emitcode("clr","a");
1685             pic16_emitcode("rlc","a");
1686         } else {
1687             if (s == zero) 
1688                 pic16_emitcode("clr","%s",aop->aopu.aop_dir);
1689             else
1690                 if (s == one)
1691                     pic16_emitcode("setb","%s",aop->aopu.aop_dir);
1692                 else
1693                     if (!strcmp(s,"c"))
1694                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1695                     else {
1696                         lbl = newiTempLabel(NULL);
1697                         
1698                         if (strcmp(s,"a")) {
1699                             MOVA(s);
1700                         }
1701                         pic16_emitcode("clr","c");
1702                         pic16_emitcode("jz","%05d_DS_",lbl->key+100);
1703                         pic16_emitcode("cpl","c");
1704                         pic16_emitcode("","%05d_DS_:",lbl->key+100);
1705                         pic16_emitcode("mov","%s,c",aop->aopu.aop_dir);
1706                     }
1707         }
1708         break;
1709         
1710     case AOP_STR:
1711         aop->coff = offset;
1712         if (strcmp(aop->aopu.aop_str[offset],s))
1713             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s,__LINE__);
1714         break;
1715         
1716     case AOP_ACC:
1717         aop->coff = offset;
1718         if (!offset && (strcmp(s,"acc") == 0))
1719             break;
1720         
1721         if (strcmp(aop->aopu.aop_str[offset],s))
1722             pic16_emitcode ("mov","%s,%s ; %d",aop->aopu.aop_str[offset],s, __LINE__);
1723         break;
1724
1725     default :
1726         werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1727                "pic16_aopPut got unsupported aop->type");
1728         exit(0);    
1729     }    
1730
1731 }
1732
1733 /*-----------------------------------------------------------------*/
1734 /* mov2w - generate either a MOVLW or MOVFW based operand type     */
1735 /*-----------------------------------------------------------------*/
1736 static void mov2w (asmop *aop, int offset)
1737 {
1738
1739   if(!aop)
1740     return;
1741
1742   DEBUGpic16_emitcode ("; ***","%s  %d  offset=%d",__FUNCTION__,__LINE__,offset);
1743
1744   if ( aop->type == AOP_PCODE ||
1745        aop->type == AOP_LIT )
1746     pic16_emitpcode(POC_MOVLW,pic16_popGet(aop,offset));
1747   else
1748     pic16_emitpcode(POC_MOVFW,pic16_popGet(aop,offset));
1749
1750 }
1751
1752
1753 void pic16_pushpCodeOpReg(pCodeOpReg *pcop)
1754 {
1755         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(pcop, &pic16_pc_postdec1, 0));
1756 }
1757
1758 void pic16_poppCodeOpReg(pCodeOpReg *pcop)
1759 {
1760         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, pcop, 0));
1761 }
1762
1763
1764 /*-----------------------------------------------------------------*/
1765 /* pushw - pushes wreg to stack                                    */
1766 /*-----------------------------------------------------------------*/
1767 void pushw(void)
1768 {
1769         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1770         pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_postdec1));
1771 }
1772
1773                 
1774 /*-----------------------------------------------------------------*/
1775 /* pushaop - pushes aop to stack                                   */
1776 /*-----------------------------------------------------------------*/
1777 void pushaop(asmop *aop, int offset)
1778 {
1779         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1780         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(PCOR(pic16_popGet(aop, offset)), &pic16_pc_postdec1, 0));
1781 }
1782
1783 /*-----------------------------------------------------------------*/
1784 /* popaop - pops aop from stack                                    */
1785 /*-----------------------------------------------------------------*/
1786 void popaop(asmop *aop, int offset)
1787 {
1788         DEBUGpic16_emitcode("; ***", "%s  %d", __FUNCTION__, __LINE__);
1789         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_preinc1, PCOR(pic16_popGet(aop, offset)), 0));
1790 }
1791
1792 void popaopidx(asmop *aop, int offset, int index)
1793 {
1794   int ofs=1;
1795
1796         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1797
1798         if(STACK_MODEL_LARGE)ofs++;
1799
1800         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(index + ofs));
1801         pic16_emitpcode(POC_MOVFF, pic16_popCombine2(&pic16_pc_plusw2, PCOR(pic16_popGet(aop, offset)), 0));
1802 }
1803
1804 /*-----------------------------------------------------------------*/
1805 /* reAdjustPreg - points a register back to where it should        */
1806 /*-----------------------------------------------------------------*/
1807 static void reAdjustPreg (asmop *aop)
1808 {
1809     int size ;
1810
1811     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1812     aop->coff = 0;
1813     if ((size = aop->size) <= 1)
1814         return ;
1815     size-- ;
1816     switch (aop->type) {
1817         case AOP_R0 :
1818         case AOP_R1 :
1819             while (size--)
1820                 pic16_emitcode("dec","%s",aop->aopu.aop_ptr->name);
1821             break;          
1822         case AOP_DPTR :
1823         case AOP_DPTR2:
1824             if (aop->type == AOP_DPTR2)
1825             {
1826                 genSetDPTR(1);
1827             } 
1828             while (size--)
1829             {
1830                 pic16_emitcode("lcall","__decdptr");
1831             }
1832                 
1833             if (aop->type == AOP_DPTR2)
1834             {
1835                 genSetDPTR(0);
1836             }                
1837             break;  
1838
1839     }   
1840
1841 }
1842
1843
1844 #if 0
1845 /*-----------------------------------------------------------------*/
1846 /* opIsGptr: returns non-zero if the passed operand is             */   
1847 /* a generic pointer type.                                         */
1848 /*-----------------------------------------------------------------*/ 
1849 static int opIsGptr(operand *op)
1850 {
1851     sym_link *type = operandType(op);
1852     
1853     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1854     if ((AOP_SIZE(op) == GPTRSIZE) && IS_GENPTR(type))
1855     {
1856         return 1;
1857     }
1858     return 0;        
1859 }
1860 #endif
1861
1862 /*-----------------------------------------------------------------*/
1863 /* pic16_getDataSize - get the operand data size                         */
1864 /*-----------------------------------------------------------------*/
1865 int pic16_getDataSize(operand *op)
1866 {
1867     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1868
1869
1870     return AOP_SIZE(op);
1871
1872     // tsd- in the pic port, the genptr size is 1, so this code here
1873     // fails. ( in the 8051 port, the size was 4).
1874 #if 0
1875     int size;
1876     size = AOP_SIZE(op);
1877     if (size == GPTRSIZE)
1878     {
1879         sym_link *type = operandType(op);
1880         if (IS_GENPTR(type))
1881         {
1882             /* generic pointer; arithmetic operations
1883              * should ignore the high byte (pointer type).
1884              */
1885             size--;
1886     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1887         }
1888     }
1889     return size;
1890 #endif
1891 }
1892
1893 /*-----------------------------------------------------------------*/
1894 /* pic16_outAcc - output Acc                                             */
1895 /*-----------------------------------------------------------------*/
1896 void pic16_outAcc(operand *result)
1897 {
1898   int size,offset;
1899   DEBUGpic16_emitcode ("; ***","%s  %d - ",__FUNCTION__,__LINE__);
1900   DEBUGpic16_pic16_AopType(__LINE__,NULL,NULL,result);
1901
1902
1903   size = pic16_getDataSize(result);
1904   if(size){
1905     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
1906     size--;
1907     offset = 1;
1908     /* unsigned or positive */
1909     while(size--)
1910       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset++));
1911   }
1912
1913 }
1914
1915 /*-----------------------------------------------------------------*/
1916 /* pic16_outBitC - output a bit C                                        */
1917 /*-----------------------------------------------------------------*/
1918 void pic16_outBitC(operand *result)
1919 {
1920
1921     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1922     /* if the result is bit */
1923     if (AOP_TYPE(result) == AOP_CRY) 
1924         pic16_aopPut(AOP(result),"c",0);
1925     else {
1926         pic16_emitcode("clr","a  ; %d", __LINE__);
1927         pic16_emitcode("rlc","a");
1928         pic16_outAcc(result);
1929     }
1930 }
1931
1932 /*-----------------------------------------------------------------*/
1933 /* pic16_toBoolean - emit code for orl a,operator(sizeop)                */
1934 /*-----------------------------------------------------------------*/
1935 void pic16_toBoolean(operand *oper)
1936 {
1937     int size = AOP_SIZE(oper) - 1;
1938     int offset = 1;
1939
1940     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1941
1942     if ( AOP_TYPE(oper) != AOP_ACC) {
1943       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(oper),0));
1944     }
1945     while (size--) {
1946       pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(oper),offset++));
1947     }
1948 }
1949
1950
1951 #if !defined(GEN_Not)
1952 /*-----------------------------------------------------------------*/
1953 /* genNot - generate code for ! operation                          */
1954 /*-----------------------------------------------------------------*/
1955 static void pic16_genNot (iCode *ic)
1956 {
1957   symbol *tlbl;
1958   int size;
1959
1960   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
1961   /* assign asmOps to operand & result */
1962   pic16_aopOp (IC_LEFT(ic),ic,FALSE);
1963   pic16_aopOp (IC_RESULT(ic),ic,TRUE);
1964
1965   DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),NULL,IC_RESULT(ic));
1966   /* if in bit space then a special case */
1967   if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1968     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
1969       pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1970       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1971     } else {
1972       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1973       pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(IC_LEFT(ic)),0));
1974       pic16_emitpcode(POC_INCF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1975     }
1976     goto release;
1977   }
1978
1979   size = AOP_SIZE(IC_LEFT(ic));
1980   if(size == 1) {
1981     pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(IC_LEFT(ic)),0));
1982     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(1));
1983     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
1984     goto release;
1985   }
1986   pic16_toBoolean(IC_LEFT(ic));
1987
1988   tlbl = newiTempLabel(NULL);
1989   pic16_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
1990   pic16_emitcode("","%05d_DS_:",tlbl->key+100);
1991   pic16_outBitC(IC_RESULT(ic));
1992
1993  release:    
1994   /* release the aops */
1995   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
1996   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
1997 }
1998 #endif
1999
2000
2001 #if !defined(GEN_Cpl)
2002 /*-----------------------------------------------------------------*/
2003 /* genCpl - generate code for complement                           */
2004 /*-----------------------------------------------------------------*/
2005 static void pic16_genCpl (iCode *ic)
2006 {
2007     int offset = 0;
2008     int size ;
2009
2010
2011     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2012     /* assign asmOps to operand & result */
2013     pic16_aopOp (IC_LEFT(ic),ic,FALSE);
2014     pic16_aopOp (IC_RESULT(ic),ic,TRUE);
2015
2016     /* if both are in bit space then 
2017     a special case */
2018     if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2019         AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2020
2021         pic16_emitcode("mov","c,%s",IC_LEFT(ic)->aop->aopu.aop_dir); 
2022         pic16_emitcode("cpl","c"); 
2023         pic16_emitcode("mov","%s,c",IC_RESULT(ic)->aop->aopu.aop_dir); 
2024         goto release; 
2025     } 
2026
2027     size = AOP_SIZE(IC_RESULT(ic));
2028     while (size--) {
2029 /*
2030         char *l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE);
2031         MOVA(l);       
2032         pic16_emitcode("cpl","a");
2033         pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2034 */
2035         if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2036               pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)), offset));
2037         } else {
2038                 pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
2039                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
2040         }
2041         offset++;
2042
2043     }
2044
2045
2046 release:
2047     /* release the aops */
2048     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2049     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2050 }
2051 #endif
2052
2053 /*-----------------------------------------------------------------*/
2054 /* genUminusFloat - unary minus for floating points                */
2055 /*-----------------------------------------------------------------*/
2056 static void genUminusFloat(operand *op,operand *result)
2057 {
2058     int size ,offset =0 ;
2059     char *l;
2060
2061     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2062     /* for this we just need to flip the 
2063     first it then copy the rest in place */
2064     size = AOP_SIZE(op) - 1;
2065     l = pic16_aopGet(AOP(op),3,FALSE,FALSE);
2066
2067     MOVA(l);    
2068
2069     pic16_emitcode("cpl","acc.7");
2070     pic16_aopPut(AOP(result),"a",3);    
2071
2072     while(size--) {
2073         pic16_aopPut(AOP(result),
2074                pic16_aopGet(AOP(op),offset,FALSE,FALSE),
2075                offset);
2076         offset++;
2077     }          
2078 }
2079
2080 /*-----------------------------------------------------------------*/
2081 /* genUminus - unary minus code generation                         */
2082 /*-----------------------------------------------------------------*/
2083 static void genUminus (iCode *ic)
2084 {
2085   int size, i;
2086   sym_link *optype, *rtype;
2087
2088
2089   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2090   /* assign asmops */
2091   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2092   pic16_aopOp(IC_RESULT(ic),ic,TRUE);
2093
2094   /* if both in bit space then special
2095      case */
2096   if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
2097       AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
2098
2099     pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2100     pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(IC_LEFT(ic)),0));
2101     pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(IC_RESULT(ic)),0));
2102
2103     goto release; 
2104   } 
2105
2106   optype = operandType(IC_LEFT(ic));
2107   rtype = operandType(IC_RESULT(ic));
2108
2109   /* if float then do float stuff */
2110   if (IS_FLOAT(optype)) {
2111     genUminusFloat(IC_LEFT(ic),IC_RESULT(ic));
2112     goto release;
2113   }
2114
2115   /* otherwise subtract from zero by taking the 2's complement */
2116   size = AOP_SIZE(IC_LEFT(ic));
2117
2118   for(i=0; i<size; i++) {
2119     if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
2120       pic16_emitpcode(POC_COMF,  pic16_popGet(AOP(IC_LEFT(ic)),i));
2121     else {
2122       pic16_emitpcode(POC_COMFW, pic16_popGet(AOP(IC_LEFT(ic)),i));
2123       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),i));
2124     }
2125   }
2126
2127   pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
2128   for(i=1; i<size; i++) {
2129     emitSKPNZ;
2130     pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),i));
2131   }
2132
2133  release:
2134   /* release the aops */
2135   pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? 0 : 1));
2136   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);    
2137 }
2138
2139 /*-----------------------------------------------------------------*/
2140 /* saveRegisters - will look for a call and save the registers     */
2141 /*-----------------------------------------------------------------*/
2142 static void saveRegisters(iCode *lic) 
2143 {
2144     int i;
2145     iCode *ic;
2146     bitVect *rsave;
2147     sym_link *dtype;
2148
2149     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2150     /* look for call */
2151     for (ic = lic ; ic ; ic = ic->next) 
2152         if (ic->op == CALL || ic->op == PCALL)
2153             break;
2154
2155     if (!ic) {
2156         fprintf(stderr,"found parameter push with no function call\n");
2157         return ;
2158     }
2159
2160     /* if the registers have been saved already then
2161     do nothing */
2162     if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type))
2163         return ;
2164
2165     /* find the registers in use at this time 
2166     and push them away to safety */
2167     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2168                           ic->rUsed);
2169
2170     ic->regsSaved = 1;
2171     if (options.useXstack) {
2172         if (bitVectBitValue(rsave,R0_IDX))
2173             pic16_emitcode("mov","b,r0");
2174         pic16_emitcode("mov","r0,%s",spname);
2175         for (i = 0 ; i < pic16_nRegs ; i++) {
2176             if (bitVectBitValue(rsave,i)) {
2177                 if (i == R0_IDX)
2178                     pic16_emitcode("mov","a,b");
2179                 else
2180                     pic16_emitcode("mov","a,%s",pic16_regWithIdx(i)->name);
2181                 pic16_emitcode("movx","@r0,a");
2182                 pic16_emitcode("inc","r0");
2183             }
2184         }
2185         pic16_emitcode("mov","%s,r0",spname);
2186         if (bitVectBitValue(rsave,R0_IDX))
2187             pic16_emitcode("mov","r0,b");           
2188     }// else
2189     //for (i = 0 ; i < pic16_nRegs ; i++) {
2190     //    if (bitVectBitValue(rsave,i))
2191     //  pic16_emitcode("push","%s",pic16_regWithIdx(i)->dname);
2192     //}
2193
2194     dtype = operandType(IC_LEFT(ic));
2195     if (currFunc && dtype && 
2196         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2197         IFFUNC_ISISR(currFunc->type) &&
2198         !ic->bankSaved) 
2199
2200         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2201
2202 }
2203 /*-----------------------------------------------------------------*/
2204 /* unsaveRegisters - pop the pushed registers                      */
2205 /*-----------------------------------------------------------------*/
2206 static void unsaveRegisters (iCode *ic)
2207 {
2208     int i;
2209     bitVect *rsave;
2210
2211     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2212     /* find the registers in use at this time 
2213     and push them away to safety */
2214     rsave = bitVectCplAnd(bitVectCopy(ic->rMask),
2215                           ic->rUsed);
2216     
2217     if (options.useXstack) {
2218         pic16_emitcode("mov","r0,%s",spname);   
2219         for (i =  pic16_nRegs ; i >= 0 ; i--) {
2220             if (bitVectBitValue(rsave,i)) {
2221                 pic16_emitcode("dec","r0");
2222                 pic16_emitcode("movx","a,@r0");
2223                 if (i == R0_IDX)
2224                     pic16_emitcode("mov","b,a");
2225                 else
2226                     pic16_emitcode("mov","%s,a",pic16_regWithIdx(i)->name);
2227             }       
2228
2229         }
2230         pic16_emitcode("mov","%s,r0",spname);
2231         if (bitVectBitValue(rsave,R0_IDX))
2232             pic16_emitcode("mov","r0,b");
2233     } //else
2234     //for (i =  pic16_nRegs ; i >= 0 ; i--) {
2235     //    if (bitVectBitValue(rsave,i))
2236     //  pic16_emitcode("pop","%s",pic16_regWithIdx(i)->dname);
2237     //}
2238
2239 }  
2240
2241
2242 /*-----------------------------------------------------------------*/
2243 /* pushSide -                                                      */
2244 /*-----------------------------------------------------------------*/
2245 static void pushSide(operand * oper, int size)
2246 {
2247 #if 0
2248         int offset = 0;
2249     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2250         while (size--) {
2251                 char *l = pic16_aopGet(AOP(oper),offset++,FALSE,TRUE);
2252                 if (AOP_TYPE(oper) != AOP_REG &&
2253                     AOP_TYPE(oper) != AOP_DIR &&
2254                     strcmp(l,"a") ) {
2255                         pic16_emitcode("mov","a,%s",l);
2256                         pic16_emitcode("push","acc");
2257                 } else
2258                         pic16_emitcode("push","%s",l);
2259         }
2260 #endif
2261 }
2262
2263 /*-----------------------------------------------------------------*/
2264 /* assignResultValue -                                             */
2265 /*-----------------------------------------------------------------*/
2266 static void assignResultValue(operand * oper)
2267 {
2268   int size = AOP_SIZE(oper);
2269
2270         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2271         DEBUGpic16_pic16_AopType(__LINE__,oper,NULL,NULL);
2272
2273         if(!GpsuedoStkPtr) {
2274 //              DEBUGpic16_emitcode("; ", "pop %d", GpsuedoStkPtr);
2275                 /* The last byte in the assignment is in W */
2276                 size--;
2277                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2278                 GpsuedoStkPtr++;
2279         }
2280
2281         while (size--) {
2282 //              DEBUGpic16_emitcode("; ", "POC_MOVLW %d", GpsuedoStkPtr);
2283 //              DEBUGpic16_emitcode("; ", "POC_MOVFW PLUSW2");
2284                 
2285 #if STACK_SUPPORT
2286                 if(USE_STACK) {
2287                         popaopidx(AOP(oper), size, GpsuedoStkPtr);
2288                 } else {
2289                         pic16_emitpcode(POC_MOVFW, pic16_popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2290                 }
2291 #else
2292                 pic16_emitpcode(POC_MOVFW, pic16_popRegFromIdx(GpsuedoStkPtr-1 + pic16_Gstack_base_addr));
2293 #endif  /* STACK_SUPPORT */
2294                 GpsuedoStkPtr++;
2295
2296 #if STACK_SUPPORT
2297                 if(!USE_STACK)
2298                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2299 #else
2300                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper),size));
2301 #endif
2302
2303         }
2304                 
2305 }
2306
2307
2308 /*-----------------------------------------------------------------*/
2309 /* genIpush - genrate code for pushing this gets a little complex  */
2310 /*-----------------------------------------------------------------*/
2311 static void genIpush (iCode *ic)
2312 {
2313
2314   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2315 #if 0
2316     int size, offset = 0 ;
2317     char *l;
2318
2319
2320     /* if this is not a parm push : ie. it is spill push 
2321     and spill push is always done on the local stack */
2322     if (!ic->parmPush) {
2323
2324         /* and the item is spilt then do nothing */
2325         if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2326             return ;
2327
2328         pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2329         size = AOP_SIZE(IC_LEFT(ic));
2330         /* push it on the stack */
2331         while(size--) {
2332             l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2333             if (*l == '#') {
2334                 MOVA(l);
2335                 l = "acc";
2336             }
2337             pic16_emitcode("push","%s",l);
2338         }
2339         return ;        
2340     }
2341
2342     /* this is a paramter push: in this case we call
2343     the routine to find the call and save those
2344     registers that need to be saved */   
2345     saveRegisters(ic);
2346
2347     /* then do the push */
2348     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2349
2350
2351         // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2352     size = AOP_SIZE(IC_LEFT(ic));
2353
2354     while (size--) {
2355         l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,FALSE,TRUE);
2356         if (AOP_TYPE(IC_LEFT(ic)) != AOP_REG && 
2357             AOP_TYPE(IC_LEFT(ic)) != AOP_DIR &&
2358             strcmp(l,"a") ) {
2359             pic16_emitcode("mov","a,%s",l);
2360             pic16_emitcode("push","acc");
2361         } else
2362             pic16_emitcode("push","%s",l);
2363     }       
2364
2365     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2366 #endif
2367 }
2368
2369 /*-----------------------------------------------------------------*/
2370 /* genIpop - recover the registers: can happen only for spilling   */
2371 /*-----------------------------------------------------------------*/
2372 static void genIpop (iCode *ic)
2373 {
2374   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2375 #if 0
2376     int size,offset ;
2377
2378
2379     /* if the temp was not pushed then */
2380     if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
2381         return ;
2382
2383     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2384     size = AOP_SIZE(IC_LEFT(ic));
2385     offset = (size-1);
2386     while (size--) 
2387         pic16_emitcode("pop","%s",pic16_aopGet(AOP(IC_LEFT(ic)),offset--,
2388                                    FALSE,TRUE));
2389
2390     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE);
2391 #endif
2392 }
2393
2394 /*-----------------------------------------------------------------*/
2395 /* unsaverbank - restores the resgister bank from stack            */
2396 /*-----------------------------------------------------------------*/
2397 static void unsaverbank (int bank,iCode *ic,bool popPsw)
2398 {
2399   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2400 #if 0
2401     int i;
2402     asmop *aop ;
2403     regs *r = NULL;
2404
2405     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2406     if (popPsw) {
2407         if (options.useXstack) {
2408             aop = newAsmop(0);
2409             r = getFreePtr(ic,&aop,FALSE);
2410             
2411             
2412             pic16_emitcode("mov","%s,_spx",r->name);
2413             pic16_emitcode("movx","a,@%s",r->name);
2414             pic16_emitcode("mov","psw,a");
2415             pic16_emitcode("dec","%s",r->name);
2416             
2417         }else
2418             pic16_emitcode ("pop","psw");
2419     }
2420
2421     for (i = (pic16_nRegs - 1) ; i >= 0 ;i--) {
2422         if (options.useXstack) {       
2423             pic16_emitcode("movx","a,@%s",r->name);
2424             //pic16_emitcode("mov","(%s+%d),a",
2425             //       regspic16[i].base,8*bank+regspic16[i].offset);
2426             pic16_emitcode("dec","%s",r->name);
2427
2428         } else 
2429           pic16_emitcode("pop",""); //"(%s+%d)",
2430         //regspic16[i].base,8*bank); //+regspic16[i].offset);
2431     }
2432
2433     if (options.useXstack) {
2434
2435         pic16_emitcode("mov","_spx,%s",r->name);
2436         pic16_freeAsmop(NULL,aop,ic,TRUE);
2437
2438     }
2439 #endif 
2440 }
2441
2442 /*-----------------------------------------------------------------*/
2443 /* saverbank - saves an entire register bank on the stack          */
2444 /*-----------------------------------------------------------------*/
2445 static void saverbank (int bank, iCode *ic, bool pushPsw)
2446 {
2447   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2448 #if 0
2449     int i;
2450     asmop *aop ;
2451     regs *r = NULL;
2452
2453     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2454     if (options.useXstack) {
2455
2456         aop = newAsmop(0);
2457         r = getFreePtr(ic,&aop,FALSE);  
2458         pic16_emitcode("mov","%s,_spx",r->name);
2459
2460     }
2461
2462     for (i = 0 ; i < pic16_nRegs ;i++) {
2463         if (options.useXstack) {
2464             pic16_emitcode("inc","%s",r->name);
2465             //pic16_emitcode("mov","a,(%s+%d)",
2466             //         regspic16[i].base,8*bank+regspic16[i].offset);
2467             pic16_emitcode("movx","@%s,a",r->name);           
2468         } else 
2469           pic16_emitcode("push","");// "(%s+%d)",
2470                      //regspic16[i].base,8*bank+regspic16[i].offset);
2471     }
2472     
2473     if (pushPsw) {
2474         if (options.useXstack) {
2475             pic16_emitcode("mov","a,psw");
2476             pic16_emitcode("movx","@%s,a",r->name);     
2477             pic16_emitcode("inc","%s",r->name);
2478             pic16_emitcode("mov","_spx,%s",r->name);       
2479             pic16_freeAsmop (NULL,aop,ic,TRUE);
2480             
2481         } else
2482             pic16_emitcode("push","psw");
2483         
2484         pic16_emitcode("mov","psw,#0x%02x",(bank << 3)&0x00ff);
2485     }
2486     ic->bankSaved = 1;
2487 #endif
2488 }
2489
2490
2491
2492 /*-----------------------------------------------------------------*/
2493 /* genCall - generates a call statement                            */
2494 /*-----------------------------------------------------------------*/
2495 static void genCall (iCode *ic)
2496 {
2497   sym_link *dtype;   
2498   int stackParms=0;
2499   
2500         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2501
2502         /* if caller saves & we have not saved then */
2503         if (!ic->regsSaved)
2504                 saveRegisters(ic);
2505
2506         /* if we are calling a function that is not using
2507          * the same register bank then we need to save the
2508          * destination registers on the stack */
2509         dtype = operandType(IC_LEFT(ic));
2510         if (currFunc && dtype && 
2511                 (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)) &&
2512                 IFFUNC_ISISR(currFunc->type) &&
2513                 !ic->bankSaved) 
2514
2515                         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2516
2517         /* if send set is not empty the assign */
2518         if (_G.sendSet) {
2519           iCode *sic;
2520
2521                 /* For the Pic port, there is no data stack.
2522                  * So parameters passed to functions are stored
2523                  * in registers. (The pCode optimizer will get
2524                  * rid of most of these :). */
2525
2526           int psuedoStkPtr=-1; 
2527           int firstTimeThruLoop = 1;
2528
2529                 _G.sendSet = reverseSet(_G.sendSet);
2530
2531                 /* First figure how many parameters are getting passed */
2532                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2533                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2534                         psuedoStkPtr += AOP_SIZE(IC_LEFT(sic));
2535                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,FALSE);
2536                 }
2537
2538                 stackParms = psuedoStkPtr;
2539
2540                 for (sic = setFirstItem(_G.sendSet) ; sic ; sic = setNextItem(_G.sendSet)) {
2541                   int size, offset = 0;
2542
2543                         pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2544                         size = AOP_SIZE(IC_LEFT(sic));
2545
2546                         while (size--) {
2547                                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2548                                         pic16_AopType(AOP_TYPE(IC_LEFT(sic))));
2549                                 DEBUGpic16_emitcode("; ", "push %d", psuedoStkPtr-1);
2550
2551                                 if(!firstTimeThruLoop) {
2552                                         /* If this is not the first time we've been through the loop
2553                                          * then we need to save the parameter in a temporary
2554                                          * register. The last byte of the last parameter is
2555                                          * passed in W. */
2556
2557 #if STACK_SUPPORT
2558                                         if(USE_STACK) {
2559                                                 pushw();
2560                                                 --psuedoStkPtr;         // sanity check
2561                                         } else {
2562                                                 pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2563                                         }
2564 #else
2565                                         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(--psuedoStkPtr + pic16_Gstack_base_addr));
2566 #endif  /* STACK_SUPPORT */
2567                                 }
2568                         
2569                                 firstTimeThruLoop=0;
2570
2571                                 mov2w (AOP(IC_LEFT(sic)),  offset);
2572                                 offset++;
2573                         }
2574                         pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2575                 }
2576                 _G.sendSet = NULL;
2577         }
2578
2579         /* make the call */
2580         pic16_emitpcode(POC_CALL,pic16_popGetWithString(OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
2581                         OP_SYMBOL(IC_LEFT(ic))->rname :
2582                         OP_SYMBOL(IC_LEFT(ic))->name));
2583
2584         GpsuedoStkPtr=0;
2585         /* if we need assign a result value */
2586         if ((IS_ITEMP(IC_RESULT(ic)) && 
2587                 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2588                 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
2589                 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2590
2591                 _G.accInUse++;
2592                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2593                 _G.accInUse--;
2594
2595                 assignResultValue(IC_RESULT(ic));
2596
2597                 DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
2598                          pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
2599                 
2600                 pic16_freeAsmop(IC_RESULT(ic),NULL, ic,TRUE);
2601         }
2602
2603 #if STACK_SUPPORT
2604         if(USE_STACK && stackParms>0) {
2605                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(stackParms));
2606                 pic16_emitpcode(POC_ADDWF, pic16_popCopyReg( &pic16_pc_fsr1l ));
2607                 if(STACK_MODEL_LARGE) {
2608                         emitSKPNC;
2609                         pic16_emitpcode(POC_INCF, pic16_popCopyReg( &pic16_pc_fsr1h ));
2610                 }
2611         }
2612 #endif
2613
2614         /* adjust the stack for parameters if required */
2615 //      fprintf(stderr, "%s:%d: %s ic->parmBytes= %d\n", __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name, ic->parmBytes);
2616
2617         if (ic->parmBytes) {
2618           int i;
2619
2620                 if (ic->parmBytes > 3) {
2621                         pic16_emitcode("mov","a,%s",spname);
2622                         pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2623                         pic16_emitcode("mov","%s,a",spname);
2624                 } else 
2625                         for ( i = 0 ; i <  ic->parmBytes ;i++)
2626                                 pic16_emitcode("dec","%s",spname);
2627         }
2628
2629         /* if register bank was saved then pop them */
2630         if (ic->bankSaved)
2631                 unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2632
2633         /* if we hade saved some registers then unsave them */
2634         if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2635                 unsaveRegisters (ic);
2636 }
2637
2638 /*-----------------------------------------------------------------*/
2639 /* genPcall - generates a call by pointer statement                */
2640 /*-----------------------------------------------------------------*/
2641 static void genPcall (iCode *ic)
2642 {
2643     sym_link *dtype;
2644     symbol *rlbl = newiTempLabel(NULL);
2645
2646
2647     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2648     /* if caller saves & we have not saved then */
2649     if (!ic->regsSaved)
2650         saveRegisters(ic);
2651
2652     /* if we are calling a function that is not using
2653     the same register bank then we need to save the
2654     destination registers on the stack */
2655     dtype = operandType(IC_LEFT(ic));
2656     if (currFunc && dtype && 
2657         IFFUNC_ISISR(currFunc->type) &&
2658         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2659         saverbank(FUNC_REGBANK(dtype),ic,TRUE);
2660
2661
2662     /* push the return address on to the stack */
2663     pic16_emitcode("mov","a,#%05d_DS_",(rlbl->key+100));
2664     pic16_emitcode("push","acc");    
2665     pic16_emitcode("mov","a,#(%05d_DS_ >> 8)",(rlbl->key+100));
2666     pic16_emitcode("push","acc");
2667     
2668     if (options.model == MODEL_FLAT24)
2669     {
2670         pic16_emitcode("mov","a,#(%05d_DS_ >> 16)",(rlbl->key+100));
2671         pic16_emitcode("push","acc");    
2672     }
2673
2674     /* now push the calling address */
2675     pic16_aopOp(IC_LEFT(ic),ic,FALSE);
2676
2677     pushSide(IC_LEFT(ic), FPTRSIZE);
2678
2679     pic16_freeAsmop(IC_LEFT(ic),NULL,ic,TRUE); 
2680
2681     /* if send set is not empty the assign */
2682     if (_G.sendSet) {
2683         iCode *sic ;
2684
2685         for (sic = setFirstItem(_G.sendSet) ; sic ; 
2686              sic = setNextItem(_G.sendSet)) {
2687             int size, offset = 0;
2688             pic16_aopOp(IC_LEFT(sic),sic,FALSE);
2689             size = AOP_SIZE(IC_LEFT(sic));
2690             while (size--) {
2691                 char *l = pic16_aopGet(AOP(IC_LEFT(sic)),offset,
2692                                 FALSE,FALSE);
2693                 if (strcmp(l,fReturn[offset]))
2694                     pic16_emitcode("mov","%s,%s",
2695                              fReturn[offset],
2696                              l);
2697                 offset++;
2698             }
2699             pic16_freeAsmop (IC_LEFT(sic),NULL,sic,TRUE);
2700         }
2701         _G.sendSet = NULL;
2702     }
2703
2704     pic16_emitcode("ret","");
2705     pic16_emitcode("","%05d_DS_:",(rlbl->key+100));
2706
2707
2708     /* if we need assign a result value */
2709     if ((IS_ITEMP(IC_RESULT(ic)) &&
2710          (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
2711           OP_SYMBOL(IC_RESULT(ic))->spildir)) ||
2712         IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
2713
2714         _G.accInUse++;
2715         pic16_aopOp(IC_RESULT(ic),ic,FALSE);
2716         _G.accInUse--;
2717         
2718         assignResultValue(IC_RESULT(ic));
2719
2720         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
2721     }
2722
2723     /* adjust the stack for parameters if 
2724     required */
2725     if (ic->parmBytes) {
2726         int i;
2727         if (ic->parmBytes > 3) {
2728             pic16_emitcode("mov","a,%s",spname);
2729             pic16_emitcode("add","a,#0x%02x", (- ic->parmBytes) & 0xff);
2730             pic16_emitcode("mov","%s,a",spname);
2731         } else 
2732             for ( i = 0 ; i <  ic->parmBytes ;i++)
2733                 pic16_emitcode("dec","%s",spname);
2734
2735     }
2736
2737     /* if register bank was saved then unsave them */
2738     if (currFunc && dtype && 
2739         (FUNC_REGBANK(currFunc->type) != FUNC_REGBANK(dtype)))
2740         unsaverbank(FUNC_REGBANK(dtype),ic,TRUE);
2741
2742     /* if we hade saved some registers then
2743     unsave them */
2744     if (ic->regsSaved)
2745         unsaveRegisters (ic);
2746
2747 }
2748
2749 /*-----------------------------------------------------------------*/
2750 /* resultRemat - result  is rematerializable                       */
2751 /*-----------------------------------------------------------------*/
2752 static int resultRemat (iCode *ic)
2753 {
2754   //    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2755   if (SKIP_IC(ic) || ic->op == IFX)
2756     return 0;
2757
2758   if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
2759     symbol *sym = OP_SYMBOL(IC_RESULT(ic));
2760     if (sym->remat && !POINTER_SET(ic)) 
2761       return 1;
2762   }
2763
2764   return 0;
2765 }
2766
2767 #if defined(__BORLANDC__) || defined(_MSC_VER)
2768 #define STRCASECMP stricmp
2769 #else
2770 #define STRCASECMP strcasecmp
2771 #endif
2772
2773 #if 0
2774 /*-----------------------------------------------------------------*/
2775 /* inExcludeList - return 1 if the string is in exclude Reg list   */
2776 /*-----------------------------------------------------------------*/
2777 static bool inExcludeList(char *s)
2778 {
2779   DEBUGpic16_emitcode ("; ***","%s  %d - WARNING no code generated",__FUNCTION__,__LINE__);
2780     int i =0;
2781     
2782     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
2783     if (options.excludeRegs[i] &&
2784     STRCASECMP(options.excludeRegs[i],"none") == 0)
2785         return FALSE ;
2786
2787     for ( i = 0 ; options.excludeRegs[i]; i++) {
2788         if (options.excludeRegs[i] &&
2789         STRCASECMP(s,options.excludeRegs[i]) == 0)
2790             return TRUE;
2791     }
2792     return FALSE ;
2793 }
2794 #endif
2795
2796 /*-----------------------------------------------------------------*/
2797 /* genFunction - generated code for function entry                 */
2798 /*-----------------------------------------------------------------*/
2799 static void genFunction (iCode *ic)
2800 {
2801   symbol *sym;
2802   sym_link *ftype;
2803
2804         DEBUGpic16_emitcode ("; ***","%s  %d curr label offset=%dprevious max_key=%d ",__FUNCTION__,__LINE__,labelOffset,max_key);
2805
2806         labelOffset += (max_key+4);
2807         max_key=0;
2808         GpsuedoStkPtr=0;
2809         _G.nRegsSaved = 0;
2810         /* create the function header */
2811         pic16_emitcode(";","-----------------------------------------");
2812         pic16_emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
2813         pic16_emitcode(";","-----------------------------------------");
2814
2815         pic16_emitcode("","%s:",sym->rname);
2816         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(moduleName,sym->rname));
2817
2818         {
2819           absSym *ab;
2820
2821                 for(ab = setFirstItem(absSymSet); ab; ab = setNextItem(absSymSet))
2822                         if(strcmp(ab->name, sym->name)) {
2823                                 pic16_pBlockConvert2Absolute(pb);
2824                                 break;
2825                         }
2826                 
2827         }
2828
2829         ftype = operandType(IC_LEFT(ic));
2830
2831         if(IFFUNC_ISNAKED(ftype)) {
2832                 DEBUGpic16_emitcode("; ***", "_naked function, no prologue");
2833                 return;
2834         }
2835         
2836
2837         /* if critical function then turn interrupts off */
2838         if (IFFUNC_ISCRITICAL(ftype))
2839                 pic16_emitcode("clr","ea");
2840
2841         /* here we need to generate the equates for the
2842          * register bank if required */
2843 #if 0
2844         if (FUNC_REGBANK(ftype) != rbank) {
2845           int i ;
2846
2847                 rbank = FUNC_REGBANK(ftype);
2848                 for ( i = 0 ; i < pic16_nRegs ; i++ ) {
2849                         if (strcmp(regspic16[i].base,"0") == 0)
2850                                 pic16_emitcode("","%s = 0x%02x",
2851                                         regspic16[i].dname,
2852                                         8*rbank+regspic16[i].offset);
2853                         else
2854                                 pic16_emitcode ("","%s = %s + 0x%02x",
2855                                         regspic16[i].dname,
2856                                         regspic16[i].base,
2857                                         *rbank+regspic16[i].offset);
2858                 }
2859         }
2860 #endif
2861
2862         /* if this is an interrupt service routine then
2863          * save acc, b, dpl, dph  */
2864         if (IFFUNC_ISISR(sym->type)) {
2865                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_wsave));
2866                 pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_status));
2867                 pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
2868                 pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_ssave));
2869
2870                 pic16_pBlockConvert2ISR(pb);
2871 #if 0  
2872                 if (!inExcludeList("acc"))          
2873                         pic16_emitcode ("push","acc");  
2874                 if (!inExcludeList("b"))
2875                         pic16_emitcode ("push","b");
2876                 if (!inExcludeList("dpl"))
2877                         pic16_emitcode ("push","dpl");
2878                 if (!inExcludeList("dph"))
2879                         pic16_emitcode ("push","dph");
2880                 
2881                 if (options.model == MODEL_FLAT24 && !inExcludeList("dpx")) {
2882                         pic16_emitcode ("push", "dpx");
2883
2884                         /* Make sure we're using standard DPTR */
2885                         pic16_emitcode ("push", "dps");
2886                         pic16_emitcode ("mov", "dps, #0x00");
2887                         if (options.stack10bit) {       
2888                                 /* This ISR could conceivably use DPTR2. Better save it. */
2889                                 pic16_emitcode ("push", "dpl1");
2890                                 pic16_emitcode ("push", "dph1");
2891                                 pic16_emitcode ("push", "dpx1");
2892                         }
2893                 }
2894
2895                 /* if this isr has no bank i.e. is going to
2896                  * run with bank 0 , then we need to save more
2897                  * registers :-) */
2898                 if (!FUNC_REGBANK(sym->type)) {
2899
2900                         /* if this function does not call any other
2901                          * function then we can be economical and
2902                          * save only those registers that are used */
2903                         if (! IFFUNC_HASFCALL(sym->type)) {
2904                           int i;
2905
2906                                 /* if any registers used */
2907                                 if (sym->regsUsed) {
2908                                         /* save the registers used */
2909                                         for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2910                                                 if (bitVectBitValue(sym->regsUsed,i) ||
2911                                                         (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
2912                                                 pic16_emitcode("push","junk");//"%s",pic16_regWithIdx(i)->dname);                           
2913                                         }
2914                                 }
2915
2916                         } else {
2917                                 /* this function has  a function call cannot
2918                                  * determines register usage so we will have the
2919                                  * entire bank */
2920                                 saverbank(0,ic,FALSE);
2921                         }           
2922                 }
2923 #endif
2924         } else {
2925 #if STACK_SUPPORT
2926                 /* emit code to setup stack frame if user enabled,
2927                  * and function is not main() */
2928          
2929 //              fprintf(stderr, "function name: %s\n", sym->name);
2930                 if(USE_STACK && strcmp(sym->name, "main")) {
2931                         if(!options.ommitFramePtr || sym->regsUsed) {
2932                         /* setup the stack frame */
2933                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr2l, &pic16_pc_postdec1, 0));
2934                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1l, &pic16_pc_fsr2l, 0));
2935                                 if(STACK_MODEL_LARGE)
2936                                         pic16_emitpcode(POC_MOVFF, pic16_popCombine2( &pic16_pc_fsr1h, &pic16_pc_fsr2h, 0));
2937                         }
2938                 }
2939 #endif
2940
2941                 /* if callee-save to be used for this function
2942                 * then save the registers being used in this function */
2943                 if (IFFUNC_CALLEESAVES(sym->type)) {
2944                   int i;
2945             
2946 //                      fprintf(stderr, "%s:%d function sym->regsUsed= %p\n", __FILE__, __LINE__, sym->regsUsed);
2947                         
2948                         /* if any registers used */
2949                         if (sym->regsUsed
2950 #if STACK_SUPPORT
2951                                 && USE_STACK
2952 #endif
2953                                 ) {
2954                                 /* save the registers used */
2955                                 DEBUGpic16_emitcode("; **", "Saving used registers in stack");
2956                                 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
2957                                         if (bitVectBitValue(sym->regsUsed,i)) {
2958 //                                              fprintf(stderr, "%s:%d function %s uses register %s\n",
2959 //                                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
2960 //                                                              pic16_regWithIdx(i)->name);
2961
2962                                                 pic16_pushpCodeOpReg( PCOR(pic16_popRegFromIdx(i) ));
2963 //                                              pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
2964 //                                                      PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))),
2965 //                                                      &pic16_pc_postdec1, 0));
2966                                                 _G.nRegsSaved++;
2967                                         }
2968                                 }
2969                         }
2970                 }
2971         }
2972
2973
2974         
2975 #if 0
2976         if (IFFUNC_ISREENT(sym->type) || options.stackAuto) {
2977
2978                 if (options.useXstack) {
2979                         pic16_emitcode("mov","r0,%s",spname);
2980                         pic16_emitcode("mov","a,_bp");
2981                         pic16_emitcode("movx","@r0,a");
2982                         pic16_emitcode("inc","%s",spname);
2983                 } else {
2984                         /* set up the stack */
2985                         pic16_emitcode ("push","_bp");     /* save the callers stack  */
2986                 }
2987                 pic16_emitcode ("mov","_bp,%s",spname);
2988         }
2989 #endif
2990         DEBUGpic16_emitcode("; ", "need to adjust stack = %d", sym->stack);
2991
2992         /* adjust the stack for the function */
2993         if (sym->stack) {
2994           int i = sym->stack;
2995
2996                 if (i > 127 ) 
2997                         werror(W_STACK_OVERFLOW,sym->name);
2998
2999                 if (i > 3 && sym->recvSize < 4) {              
3000                         pic16_emitcode ("mov","a,sp");
3001                         pic16_emitcode ("add","a,#0x%02x",((char)sym->stack & 0xff));
3002                         pic16_emitcode ("mov","sp,a");
3003                 } else
3004                         while(i--)
3005                                 pic16_emitcode("inc","sp");
3006         }
3007
3008         if (sym->xstack) {
3009                 DEBUGpic16_emitcode("; ", "%s", __FUNCTION__);
3010
3011                 pic16_emitcode ("mov","a,_spx");
3012                 pic16_emitcode ("add","a,#0x%02x",((char)sym->xstack & 0xff));
3013                 pic16_emitcode ("mov","_spx,a");
3014         }
3015     
3016 }
3017
3018 /*-----------------------------------------------------------------*/
3019 /* genEndFunction - generates epilogue for functions               */
3020 /*-----------------------------------------------------------------*/
3021 static void genEndFunction (iCode *ic)
3022 {
3023     symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3024
3025     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3026
3027     if(IFFUNC_ISNAKED(sym->type)) {
3028         DEBUGpic16_emitcode("; ***", "_naked function, no epilogue");
3029         return;
3030     }
3031
3032 #if 0
3033     if (IFFUNC_ISREENT(sym->type) || options.stackAuto)
3034     {
3035         pic16_emitcode ("mov","%s,_bp",spname);
3036     }
3037 #endif
3038
3039     /* if use external stack but some variables were
3040     added to the local stack then decrement the
3041     local stack */
3042     if (options.useXstack && sym->stack) {      
3043         pic16_emitcode("mov","a,sp");
3044         pic16_emitcode("add","a,#0x%02x",((char)-sym->stack) & 0xff);
3045         pic16_emitcode("mov","sp,a");
3046     }
3047
3048
3049 #if 0
3050     if ((IFFUNC_ISREENT(sym->type) || options.stackAuto)) {
3051         if (options.useXstack) {
3052             pic16_emitcode("mov","r0,%s",spname);
3053             pic16_emitcode("movx","a,@r0");
3054             pic16_emitcode("mov","_bp,a");
3055             pic16_emitcode("dec","%s",spname);
3056         }
3057         else
3058         {
3059             pic16_emitcode ("pop","_bp");
3060         }
3061     }
3062 #endif
3063
3064     /* restore the register bank  */    
3065     if (FUNC_REGBANK(sym->type) || FUNC_ISISR(sym->type))
3066         pic16_emitcode ("pop","psw");
3067
3068     if (IFFUNC_ISISR(sym->type)) {
3069
3070         /* now we need to restore the registers */
3071         /* if this isr has no bank i.e. is going to
3072            run with bank 0 , then we need to save more
3073            registers :-) */
3074         if (!FUNC_REGBANK(sym->type)) {
3075             
3076             /* if this function does not call any other
3077                function then we can be economical and
3078                save only those registers that are used */
3079             if (! IFFUNC_HASFCALL(sym->type)) {
3080                 int i;
3081                 
3082                 /* if any registers used */
3083                 if (sym->regsUsed) {
3084                     /* save the registers used */
3085                     for ( i = sym->regsUsed->size ; i >= 0 ; i--) {
3086                         if (bitVectBitValue(sym->regsUsed,i) ||
3087                           (pic16_ptrRegReq && (i == R0_IDX || i == R1_IDX)) )
3088                           pic16_emitcode("pop","junk");//"%s",pic16_regWithIdx(i)->dname);
3089                     }
3090                 }
3091                 
3092             } else {
3093                 /* this function has  a function call cannot
3094                    determines register usage so we will have the
3095                    entire bank */
3096                 unsaverbank(0,ic,FALSE);
3097             }       
3098         }
3099 #if 0
3100         if (options.model == MODEL_FLAT24 && !inExcludeList("dpx"))
3101         {
3102             if (options.stack10bit)
3103             {
3104                 pic16_emitcode ("pop", "dpx1");
3105                 pic16_emitcode ("pop", "dph1");
3106                 pic16_emitcode ("pop", "dpl1");
3107             }   
3108             pic16_emitcode ("pop", "dps");
3109             pic16_emitcode ("pop", "dpx");
3110         }
3111         if (!inExcludeList("dph"))
3112             pic16_emitcode ("pop","dph");
3113         if (!inExcludeList("dpl"))
3114             pic16_emitcode ("pop","dpl");
3115         if (!inExcludeList("b"))
3116             pic16_emitcode ("pop","b");
3117         if (!inExcludeList("acc"))
3118             pic16_emitcode ("pop","acc");
3119
3120         if (IFFUNC_ISCRITICAL(sym->type))
3121             pic16_emitcode("setb","ea");
3122 #endif
3123
3124         /* if debug then send end of function */
3125 /*      if (options.debug && currFunc) { */
3126         if (currFunc) {
3127             _G.debugLine = 1;
3128             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3129                      FileBaseName(ic->filename),currFunc->lastLine,
3130                      ic->level,ic->block); 
3131             if (IS_STATIC(currFunc->etype))         
3132                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3133             else
3134                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3135             _G.debugLine = 0;
3136         }
3137         
3138 //      pic16_emitcode ("reti","");
3139
3140         pic16_emitpcode(POC_CLRF,   pic16_popCopyReg(&pic16_pc_status));
3141         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_ssave));
3142         pic16_emitpcode(POC_MOVWF,  pic16_popCopyReg(&pic16_pc_status));
3143         pic16_emitpcode(POC_SWAPF,  pic16_popCopyReg(&pic16_pc_wsave));
3144         pic16_emitpcode(POC_SWAPFW, pic16_popCopyReg(&pic16_pc_wsave));
3145
3146 #if 0
3147         pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("END_OF_INTERRUPT",-1));
3148 #endif
3149
3150         pic16_emitpcodeNULLop(POC_RETFIE);
3151
3152     }
3153     else {
3154         if (IFFUNC_ISCRITICAL(sym->type))
3155             pic16_emitcode("setb","ea");
3156         
3157         /* if any registers used */
3158         if (sym->regsUsed
3159 #if STACK_SUPPORT
3160                 && USE_STACK
3161 #endif
3162         ) {
3163           int i;
3164                 /* save the registers used */
3165                 DEBUGpic16_emitcode("; **", "Restoring used registers from stack");
3166                 for ( i = sym->regsUsed->size; i >= 0; i--) {
3167                         if (bitVectBitValue(sym->regsUsed,i)) {
3168 //                              fprintf(stderr, "%s:%d function %s uses register %s\n",
3169 //                                              __FILE__, __LINE__, OP_SYMBOL(IC_LEFT(ic))->name,
3170 //                                              pic16_regWithIdx(i)->name);
3171         
3172                                 pic16_emitpcode(POC_MOVFF, pic16_popCombine2(
3173                                         &pic16_pc_preinc1,
3174                                         PCOR(pic16_popCopyReg( PCOR(pic16_popRegFromIdx(i)))), 0));
3175                         }
3176                 }
3177         }
3178         
3179
3180         /* if debug then send end of function */
3181         if (currFunc) {
3182             _G.debugLine = 1;
3183             pic16_emitcode(";","C$%s$%d$%d$%d ==.",
3184                      FileBaseName(ic->filename),currFunc->lastLine,
3185                      ic->level,ic->block); 
3186             if (IS_STATIC(currFunc->etype))         
3187                 pic16_emitcode(";","XF%s$%s$0$0 ==.",moduleName,currFunc->name); 
3188             else
3189                 pic16_emitcode(";","XG$%s$0$0 ==.",currFunc->name);
3190             _G.debugLine = 0;
3191         }
3192
3193 #if STACK_SUPPORT
3194         /* insert code to restore stack frame, if user enabled it
3195          * and function is not main() */
3196          
3197         if(USE_STACK && strcmp(sym->name, "main")) {
3198                 if(!options.ommitFramePtr || sym->regsUsed) {
3199                         /* restore stack frame */
3200                         if(STACK_MODEL_LARGE)
3201                                 pic16_emitpcode(POC_MOVFF,
3202                                         pic16_popCombine2( &pic16_pc_postinc1, &pic16_pc_fsr2h, 0));
3203                         pic16_emitpcode(POC_MOVFF,
3204                                         pic16_popCombine2( &pic16_pc_postinc1, &pic16_pc_fsr2l, 0));
3205                 }
3206         }
3207 #endif
3208
3209         pic16_emitcode ("return","");
3210         pic16_emitpcodeNULLop(POC_RETURN);
3211
3212         /* Mark the end of a function */
3213         pic16_addpCode2pBlock(pb,pic16_newpCodeFunction(NULL,NULL));
3214     }
3215
3216 }
3217
3218 /*-----------------------------------------------------------------*/
3219 /* genRet - generate code for return statement                     */
3220 /*-----------------------------------------------------------------*/
3221 static void genRet (iCode *ic)
3222 {
3223   int size,offset = 0 , pushed = 0;
3224     
3225   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3226   /* if we have no return value then
3227      just generate the "ret" */
3228   if (!IC_LEFT(ic)) 
3229     goto jumpret;       
3230     
3231   /* we have something to return then
3232      move the return value into place */
3233   pic16_aopOp(IC_LEFT(ic),ic,FALSE);
3234   size = AOP_SIZE(IC_LEFT(ic));
3235     
3236   while (size--) {
3237     char *l ;
3238     if (AOP_TYPE(IC_LEFT(ic)) == AOP_DPTR) {
3239       /* #NOCHANGE */
3240       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset++,
3241                  FALSE,TRUE);
3242       pic16_emitcode("push","%s",l);
3243       pushed++;
3244     } else {
3245         DEBUGpic16_emitcode(";", "%d", __LINE__);
3246       l = pic16_aopGet(AOP(IC_LEFT(ic)),offset,
3247                  FALSE,FALSE);
3248         DEBUGpic16_emitcode(";", "%d l= %s", __LINE__, l);       
3249       if (strcmp(fReturn[offset],l)) {
3250         if( ( (AOP(IC_LEFT(ic))->type) == AOP_IMMD) ||
3251             ((AOP(IC_LEFT(ic))->type) == AOP_LIT) ) {
3252           pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3253         }else {
3254           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
3255         }
3256         if(size) {
3257           pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(offset + pic16_Gstack_base_addr));
3258         }
3259         offset++;
3260       }
3261     }
3262   }    
3263
3264   if (pushed) {
3265     while(pushed) {
3266       pushed--;
3267       if (strcmp(fReturn[pushed],"a"))
3268         pic16_emitcode("pop",fReturn[pushed]);
3269       else
3270         pic16_emitcode("pop","acc");
3271     }
3272   }
3273   pic16_freeAsmop (IC_LEFT(ic),NULL,ic,TRUE);
3274     
3275  jumpret:
3276   /* generate a jump to the return label
3277      if the next is not the return statement */
3278   if (!(ic->next && ic->next->op == LABEL &&
3279         IC_LABEL(ic->next) == returnLabel)) {
3280         
3281     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(returnLabel->key));
3282     pic16_emitcode("goto","_%05d_DS_",returnLabel->key+100 + labelOffset);
3283   }
3284     
3285 }
3286
3287 /*-----------------------------------------------------------------*/
3288 /* genLabel - generates a label                                    */
3289 /*-----------------------------------------------------------------*/
3290 static void genLabel (iCode *ic)
3291 {
3292     /* special case never generate */
3293     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3294     if (IC_LABEL(ic) == entryLabel)
3295         return ;
3296
3297     pic16_emitpLabel(IC_LABEL(ic)->key);
3298     pic16_emitcode("","_%05d_DS_:",(IC_LABEL(ic)->key+100 + labelOffset));
3299 }
3300
3301 /*-----------------------------------------------------------------*/
3302 /* genGoto - generates a goto                                      */
3303 /*-----------------------------------------------------------------*/
3304 //tsd
3305 static void genGoto (iCode *ic)
3306 {
3307   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_LABEL(ic)->key));
3308   pic16_emitcode ("goto","_%05d_DS_",(IC_LABEL(ic)->key+100)+labelOffset);
3309 }
3310
3311
3312 /*-----------------------------------------------------------------*/
3313 /* genMultbits :- multiplication of bits                           */
3314 /*-----------------------------------------------------------------*/
3315 static void genMultbits (operand *left, 
3316                          operand *right, 
3317                          operand *result)
3318 {
3319   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3320
3321   if(!pic16_sameRegs(AOP(result),AOP(right)))
3322     pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),0));
3323
3324   pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
3325   pic16_emitpcode(POC_BTFSS,pic16_popGet(AOP(left),0));
3326   pic16_emitpcode(POC_BCF,  pic16_popGet(AOP(result),0));
3327
3328 }
3329
3330
3331 /*-----------------------------------------------------------------*/
3332 /* genMultOneByte : 8 bit multiplication & division                */
3333 /*-----------------------------------------------------------------*/
3334 static void genMultOneByte (operand *left,
3335                             operand *right,
3336                             operand *result)
3337 {
3338   sym_link *opetype = operandType(result);
3339
3340   // symbol *lbl ;
3341   int size,offset;
3342
3343   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3344   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3345   DEBUGpic16_pic16_AopTypeSign(__LINE__,left,right,result);
3346
3347   /* (if two literals, the value is computed before) */
3348   /* if one literal, literal on the right */
3349   if (AOP_TYPE(left) == AOP_LIT){
3350     operand *t = right;
3351     right = left;
3352     left = t;
3353   }
3354
3355   size = AOP_SIZE(result);
3356   if(size == 1) {
3357
3358     if (AOP_TYPE(right) == AOP_LIT){
3359       pic16_emitcode("multiply ","lit val:%s by variable %s and store in %s", 
3360                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3361                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3362                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3363       pic16_emitcode("call","genMultLit");
3364     } else {
3365       pic16_emitcode("multiply ","variable :%s by variable %s and store in %s", 
3366                      pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3367                      pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3368                      pic16_aopGet(AOP(result),0,FALSE,FALSE));
3369       pic16_emitcode("call","pic16_genMult8X8_8");
3370
3371     }
3372     pic16_genMult8X8_8 (left, right,result);
3373
3374
3375     /* signed or unsigned */
3376     //pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3377     //l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3378     //MOVA(l);       
3379     //pic16_emitcode("mul","ab");
3380     /* if result size = 1, mul signed = mul unsigned */
3381     //pic16_aopPut(AOP(result),"a",0);
3382
3383   } else {  // (size > 1)
3384
3385     pic16_emitcode("multiply (size>1) ","variable :%s by variable %s and store in %s", 
3386                    pic16_aopGet(AOP(right),0,FALSE,FALSE), 
3387                    pic16_aopGet(AOP(left),0,FALSE,FALSE), 
3388                    pic16_aopGet(AOP(result),0,FALSE,FALSE));
3389
3390     if (SPEC_USIGN(opetype)){
3391       pic16_emitcode("multiply ","unsigned result. size = %d",AOP_SIZE(result));
3392       pic16_genUMult8X8_16 (left, right, result, NULL);
3393
3394       if (size > 2) {
3395         /* for filling the MSBs */
3396         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),2));
3397         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),3));
3398       }
3399     }
3400     else{
3401       pic16_emitcode("multiply ","signed result. size = %d",AOP_SIZE(result));
3402
3403       pic16_emitcode("mov","a,b");
3404
3405       /* adjust the MSB if left or right neg */
3406
3407       /* if one literal */
3408       if (AOP_TYPE(right) == AOP_LIT){
3409         pic16_emitcode("multiply ","right is a lit");
3410         /* AND literal negative */
3411         if((int) floatFromVal (AOP(right)->aopu.aop_lit) < 0){
3412           /* adjust MSB (c==0 after mul) */
3413           pic16_emitcode("subb","a,%s", pic16_aopGet(AOP(left),0,FALSE,FALSE));
3414         }
3415       }
3416       else{
3417         pic16_genSMult8X8_16 (left, right, result, NULL);
3418       }
3419
3420       if(size > 2){
3421         pic16_emitcode("multiply ","size is greater than 2, so propogate sign");
3422         /* get the sign */
3423         pic16_emitcode("rlc","a");
3424         pic16_emitcode("subb","a,acc");
3425       }
3426     }
3427
3428     size -= 2;   
3429     offset = 2;
3430     if (size > 0)
3431       while (size--)
3432         pic16_emitcode("multiply ","size is way greater than 2, so propogate sign");
3433     //pic16_aopPut(AOP(result),"a",offset++);
3434   }
3435 }
3436
3437 /*-----------------------------------------------------------------*/
3438 /* genMult - generates code for multiplication                     */
3439 /*-----------------------------------------------------------------*/
3440 static void genMult (iCode *ic)
3441 {
3442     operand *left = IC_LEFT(ic);
3443     operand *right = IC_RIGHT(ic);
3444     operand *result= IC_RESULT(ic);   
3445
3446     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3447     /* assign the amsops */
3448     pic16_aopOp (left,ic,FALSE);
3449     pic16_aopOp (right,ic,FALSE);
3450     pic16_aopOp (result,ic,TRUE);
3451
3452   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3453
3454     /* special cases first */
3455     /* both are bits */
3456     if (AOP_TYPE(left) == AOP_CRY &&
3457         AOP_TYPE(right)== AOP_CRY) {
3458         genMultbits(left,right,result);
3459         goto release ;
3460     }
3461
3462     /* if both are of size == 1 */
3463     if (AOP_SIZE(left) == 1 &&
3464         AOP_SIZE(right) == 1 ) {
3465         genMultOneByte(left,right,result);
3466         goto release ;
3467     }
3468
3469     pic16_emitcode("multiply ","sizes are greater than 2... need to insert proper algor.");
3470
3471     /* should have been converted to function call */
3472     //assert(0) ;
3473
3474 release :
3475     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3476     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3477     pic16_freeAsmop(result,NULL,ic,TRUE); 
3478 }
3479
3480 /*-----------------------------------------------------------------*/
3481 /* genDivbits :- division of bits                                  */
3482 /*-----------------------------------------------------------------*/
3483 static void genDivbits (operand *left, 
3484                         operand *right, 
3485                         operand *result)
3486 {
3487
3488     char *l;
3489
3490     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3491     /* the result must be bit */    
3492     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3493     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3494
3495     MOVA(l);    
3496
3497     pic16_emitcode("div","ab");
3498     pic16_emitcode("rrc","a");
3499     pic16_aopPut(AOP(result),"c",0);
3500 }
3501
3502 /*-----------------------------------------------------------------*/
3503 /* genDivOneByte : 8 bit division                                  */
3504 /*-----------------------------------------------------------------*/
3505 static void genDivOneByte (operand *left,
3506                            operand *right,
3507                            operand *result)
3508 {
3509     sym_link *opetype = operandType(result);
3510     char *l ;
3511     symbol *lbl ;
3512     int size,offset;
3513
3514     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3515     size = AOP_SIZE(result) - 1;
3516     offset = 1;
3517     /* signed or unsigned */
3518     if (SPEC_USIGN(opetype)) {
3519         /* unsigned is easy */
3520         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3521         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3522         MOVA(l);        
3523         pic16_emitcode("div","ab");
3524         pic16_aopPut(AOP(result),"a",0);
3525         while (size--)
3526             pic16_aopPut(AOP(result),zero,offset++);
3527         return ;
3528     }
3529
3530     /* signed is a little bit more difficult */
3531
3532     /* save the signs of the operands */
3533     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3534     MOVA(l);    
3535     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,TRUE));
3536     pic16_emitcode("push","acc"); /* save it on the stack */
3537
3538     /* now sign adjust for both left & right */
3539     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3540     MOVA(l);       
3541     lbl = newiTempLabel(NULL);
3542     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));   
3543     pic16_emitcode("cpl","a");   
3544     pic16_emitcode("inc","a");
3545     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3546     pic16_emitcode("mov","b,a");
3547
3548     /* sign adjust left side */
3549     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3550     MOVA(l);
3551
3552     lbl = newiTempLabel(NULL);
3553     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3554     pic16_emitcode("cpl","a");
3555     pic16_emitcode("inc","a");
3556     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3557
3558     /* now the division */
3559     pic16_emitcode("div","ab");
3560     /* we are interested in the lower order
3561     only */
3562     pic16_emitcode("mov","b,a");
3563     lbl = newiTempLabel(NULL);
3564     pic16_emitcode("pop","acc");   
3565     /* if there was an over flow we don't 
3566     adjust the sign of the result */
3567     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3568     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3569     CLRC;
3570     pic16_emitcode("clr","a");
3571     pic16_emitcode("subb","a,b");
3572     pic16_emitcode("mov","b,a");
3573     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3574
3575     /* now we are done */
3576     pic16_aopPut(AOP(result),"b",0);
3577     if(size > 0){
3578         pic16_emitcode("mov","c,b.7");
3579         pic16_emitcode("subb","a,acc");   
3580     }
3581     while (size--)
3582         pic16_aopPut(AOP(result),"a",offset++);
3583
3584 }
3585
3586 /*-----------------------------------------------------------------*/
3587 /* genDiv - generates code for division                            */
3588 /*-----------------------------------------------------------------*/
3589 static void genDiv (iCode *ic)
3590 {
3591     operand *left = IC_LEFT(ic);
3592     operand *right = IC_RIGHT(ic);
3593     operand *result= IC_RESULT(ic);   
3594
3595     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3596     /* assign the amsops */
3597     pic16_aopOp (left,ic,FALSE);
3598     pic16_aopOp (right,ic,FALSE);
3599     pic16_aopOp (result,ic,TRUE);
3600
3601     /* special cases first */
3602     /* both are bits */
3603     if (AOP_TYPE(left) == AOP_CRY &&
3604         AOP_TYPE(right)== AOP_CRY) {
3605         genDivbits(left,right,result);
3606         goto release ;
3607     }
3608
3609     /* if both are of size == 1 */
3610     if (AOP_SIZE(left) == 1 &&
3611         AOP_SIZE(right) == 1 ) {
3612         genDivOneByte(left,right,result);
3613         goto release ;
3614     }
3615
3616     /* should have been converted to function call */
3617     assert(0);
3618 release :
3619     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3620     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3621     pic16_freeAsmop(result,NULL,ic,TRUE); 
3622 }
3623
3624 /*-----------------------------------------------------------------*/
3625 /* genModbits :- modulus of bits                                   */
3626 /*-----------------------------------------------------------------*/
3627 static void genModbits (operand *left, 
3628                         operand *right, 
3629                         operand *result)
3630 {
3631
3632     char *l;
3633
3634     /* the result must be bit */    
3635     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3636     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3637
3638     MOVA(l);       
3639
3640     pic16_emitcode("div","ab");
3641     pic16_emitcode("mov","a,b");
3642     pic16_emitcode("rrc","a");
3643     pic16_aopPut(AOP(result),"c",0);
3644 }
3645
3646 /*-----------------------------------------------------------------*/
3647 /* genModOneByte : 8 bit modulus                                   */
3648 /*-----------------------------------------------------------------*/
3649 static void genModOneByte (operand *left,
3650                            operand *right,
3651                            operand *result)
3652 {
3653     sym_link *opetype = operandType(result);
3654     char *l ;
3655     symbol *lbl ;
3656
3657     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3658     /* signed or unsigned */
3659     if (SPEC_USIGN(opetype)) {
3660         /* unsigned is easy */
3661         pic16_emitcode("mov","b,%s", pic16_aopGet(AOP(right),0,FALSE,FALSE));
3662         l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
3663         MOVA(l);    
3664         pic16_emitcode("div","ab");
3665         pic16_aopPut(AOP(result),"b",0);
3666         return ;
3667     }
3668
3669     /* signed is a little bit more difficult */
3670
3671     /* save the signs of the operands */
3672     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3673     MOVA(l);
3674
3675     pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
3676     pic16_emitcode("push","acc"); /* save it on the stack */
3677
3678     /* now sign adjust for both left & right */
3679     l =  pic16_aopGet(AOP(right),0,FALSE,FALSE);    
3680     MOVA(l);
3681
3682     lbl = newiTempLabel(NULL);
3683     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));  
3684     pic16_emitcode("cpl","a");   
3685     pic16_emitcode("inc","a");
3686     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3687     pic16_emitcode("mov","b,a"); 
3688
3689     /* sign adjust left side */
3690     l =  pic16_aopGet(AOP(left),0,FALSE,FALSE);    
3691     MOVA(l);
3692
3693     lbl = newiTempLabel(NULL);
3694     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3695     pic16_emitcode("cpl","a");   
3696     pic16_emitcode("inc","a");
3697     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3698
3699     /* now the multiplication */
3700     pic16_emitcode("div","ab");
3701     /* we are interested in the lower order
3702     only */
3703     lbl = newiTempLabel(NULL);
3704     pic16_emitcode("pop","acc");   
3705     /* if there was an over flow we don't 
3706     adjust the sign of the result */
3707     pic16_emitcode("jb","ov,%05d_DS_",(lbl->key+100));
3708     pic16_emitcode("jnb","acc.7,%05d_DS_",(lbl->key+100));
3709     CLRC ;
3710     pic16_emitcode("clr","a");
3711     pic16_emitcode("subb","a,b");
3712     pic16_emitcode("mov","b,a");
3713     pic16_emitcode("","%05d_DS_:",(lbl->key+100));
3714
3715     /* now we are done */
3716     pic16_aopPut(AOP(result),"b",0);
3717
3718 }
3719
3720 /*-----------------------------------------------------------------*/
3721 /* genMod - generates code for division                            */
3722 /*-----------------------------------------------------------------*/
3723 static void genMod (iCode *ic)
3724 {
3725     operand *left = IC_LEFT(ic);
3726     operand *right = IC_RIGHT(ic);
3727     operand *result= IC_RESULT(ic);  
3728
3729     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3730     /* assign the amsops */
3731     pic16_aopOp (left,ic,FALSE);
3732     pic16_aopOp (right,ic,FALSE);
3733     pic16_aopOp (result,ic,TRUE);
3734
3735     /* special cases first */
3736     /* both are bits */
3737     if (AOP_TYPE(left) == AOP_CRY &&
3738         AOP_TYPE(right)== AOP_CRY) {
3739         genModbits(left,right,result);
3740         goto release ;
3741     }
3742
3743     /* if both are of size == 1 */
3744     if (AOP_SIZE(left) == 1 &&
3745         AOP_SIZE(right) == 1 ) {
3746         genModOneByte(left,right,result);
3747         goto release ;
3748     }
3749
3750     /* should have been converted to function call */
3751     assert(0);
3752
3753 release :
3754     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3755     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
3756     pic16_freeAsmop(result,NULL,ic,TRUE); 
3757 }
3758
3759 /*-----------------------------------------------------------------*/
3760 /* genIfxJump :- will create a jump depending on the ifx           */
3761 /*-----------------------------------------------------------------*/
3762 /*
3763   note: May need to add parameter to indicate when a variable is in bit space.
3764 */
3765 static void genIfxJump (iCode *ic, char *jval)
3766 {
3767
3768     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3769     /* if true label then we jump if condition
3770     supplied is true */
3771     if ( IC_TRUE(ic) ) {
3772
3773         if(strcmp(jval,"a") == 0)
3774           emitSKPZ;
3775         else if (strcmp(jval,"c") == 0)
3776           emitSKPC;
3777         else {
3778           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3779           pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(jval,-1,1));
3780         }
3781
3782         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
3783         pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ic)->key+100 + labelOffset);
3784
3785     }
3786     else {
3787         /* false label is present */
3788         if(strcmp(jval,"a") == 0)
3789           emitSKPNZ;
3790         else if (strcmp(jval,"c") == 0)
3791           emitSKPNC;
3792         else {
3793           DEBUGpic16_emitcode ("; ***","%d - assuming %s is in bit space",__LINE__,jval);         
3794           pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(jval,-1,1));
3795         }
3796
3797         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
3798         pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ic)->key+100 + labelOffset);
3799
3800     }
3801
3802
3803     /* mark the icode as generated */
3804     ic->generated = 1;
3805 }
3806
3807 /*-----------------------------------------------------------------*/
3808 /* genSkip                                                         */
3809 /*-----------------------------------------------------------------*/
3810 static void genSkip(iCode *ifx,int status_bit)
3811 {
3812   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3813   if(!ifx)
3814     return;
3815
3816   if ( IC_TRUE(ifx) ) {
3817     switch(status_bit) {
3818     case 'z':
3819       emitSKPNZ;
3820       break;
3821
3822     case 'c':
3823       emitSKPNC;
3824       break;
3825
3826     case 'd':
3827       emitSKPDC;
3828       break;
3829
3830     }
3831
3832     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3833     // pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3834
3835   } else {
3836
3837     switch(status_bit) {
3838
3839     case 'z':
3840       emitSKPZ;
3841       break;
3842
3843     case 'c':
3844       emitSKPC;
3845       break;
3846
3847     case 'd':
3848       emitSKPDC;
3849       break;
3850     }
3851     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3852     // pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3853
3854   }
3855
3856 }
3857
3858 /*-----------------------------------------------------------------*/
3859 /* genSkipc                                                        */
3860 /*-----------------------------------------------------------------*/
3861 static void genSkipc(resolvedIfx *rifx)
3862 {
3863   if(!rifx)
3864     return;
3865
3866   if(rifx->condition)
3867     emitSKPC;
3868   else
3869     emitSKPNC;
3870
3871   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3872   rifx->generated = 1;
3873 }
3874
3875 /*-----------------------------------------------------------------*/
3876 /* genSkipz2                                                       */
3877 /*-----------------------------------------------------------------*/
3878 static void genSkipz2(resolvedIfx *rifx, int invert_condition)
3879 {
3880   if(!rifx)
3881     return;
3882
3883   if( (rifx->condition ^ invert_condition) & 1)
3884     emitSKPZ;
3885   else
3886     emitSKPNZ;
3887
3888   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3889   rifx->generated = 1;
3890 }
3891
3892 /*-----------------------------------------------------------------*/
3893 /* genSkipz                                                        */
3894 /*-----------------------------------------------------------------*/
3895 static void genSkipz(iCode *ifx, int condition)
3896 {
3897   if(!ifx)
3898     return;
3899
3900   if(condition)
3901     emitSKPNZ;
3902   else
3903     emitSKPZ;
3904
3905   if ( IC_TRUE(ifx) )
3906     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
3907   else
3908     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
3909
3910   if ( IC_TRUE(ifx) )
3911     pic16_emitcode("goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
3912   else
3913     pic16_emitcode("goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
3914
3915 }
3916 /*-----------------------------------------------------------------*/
3917 /* genSkipCond                                                     */
3918 /*-----------------------------------------------------------------*/
3919 static void genSkipCond(resolvedIfx *rifx,operand *op, int offset, int bit)
3920 {
3921   if(!rifx)
3922     return;
3923
3924   if(rifx->condition)
3925     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3926   else
3927     pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(op),offset,FALSE,FALSE),bit,0));
3928
3929
3930   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rifx->lbl->key));
3931   rifx->generated = 1;
3932 }
3933
3934 #if 0
3935 /*-----------------------------------------------------------------*/
3936 /* genChkZeroes :- greater or less than comparison                 */
3937 /*     For each byte in a literal that is zero, inclusive or the   */
3938 /*     the corresponding byte in the operand with W                */
3939 /*     returns true if any of the bytes are zero                   */
3940 /*-----------------------------------------------------------------*/
3941 static int genChkZeroes(operand *op, int lit,  int size)
3942 {
3943
3944   int i;
3945   int flag =1;
3946
3947   while(size--) {
3948     i = (lit >> (size*8)) & 0xff;
3949
3950     if(i==0) {
3951       if(flag) 
3952         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(op),size));
3953       else
3954         pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(op),size));
3955       flag = 0;
3956     }
3957   }
3958
3959   return (flag==0);
3960 }
3961 #endif
3962
3963 /*-----------------------------------------------------------------*/
3964 /* genCmp :- greater or less than comparison                       */
3965 /*-----------------------------------------------------------------*/
3966 static void genCmp (operand *left,operand *right,
3967                     operand *result, iCode *ifx, int sign)
3968 {
3969   int size; //, offset = 0 ;
3970   unsigned long lit = 0L,i = 0;
3971   resolvedIfx rFalseIfx;
3972   //  resolvedIfx rTrueIfx;
3973   symbol *truelbl;
3974   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
3975 /*
3976   if(ifx) {
3977     DEBUGpic16_emitcode ("; ***","true ifx is %s",((IC_TRUE(ifx) == NULL) ? "false" : "true"));
3978     DEBUGpic16_emitcode ("; ***","false ifx is %s",((IC_FALSE(ifx) == NULL) ? "false" : "true"));
3979   }
3980 */
3981
3982   resolveIfx(&rFalseIfx,ifx);
3983   truelbl  = newiTempLabel(NULL);
3984   size = max(AOP_SIZE(left),AOP_SIZE(right));
3985
3986   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
3987
3988 #define _swapp
3989
3990   /* if literal is on the right then swap with left */
3991   if ((AOP_TYPE(right) == AOP_LIT)) {
3992     operand *tmp = right ;
3993     unsigned long mask = (0x100 << (8*(size-1))) - 1;
3994     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3995 #ifdef _swapp
3996
3997     lit = (lit - 1) & mask;
3998     right = left;
3999     left = tmp;
4000     rFalseIfx.condition ^= 1;
4001 #endif
4002
4003   } else if ((AOP_TYPE(left) == AOP_LIT)) {
4004     lit = (unsigned long)floatFromVal(AOP(left)->aopu.aop_lit);
4005   }
4006
4007
4008   //if(IC_TRUE(ifx) == NULL)
4009   /* if left & right are bit variables */
4010   if (AOP_TYPE(left) == AOP_CRY &&
4011       AOP_TYPE(right) == AOP_CRY ) {
4012     pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
4013     pic16_emitcode("anl","c,/%s",AOP(left)->aopu.aop_dir);
4014   } else {
4015     /* subtract right from left if at the
4016        end the carry flag is set then we know that
4017        left is greater than right */
4018
4019     //    {
4020
4021     symbol *lbl  = newiTempLabel(NULL);
4022
4023 #ifndef _swapp
4024     if(AOP_TYPE(right) == AOP_LIT) {
4025
4026       //lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4027
4028       DEBUGpic16_emitcode(";right lit","lit = 0x%x,sign=%d",lit,sign);
4029
4030       /* special cases */
4031
4032       if(lit == 0) {
4033
4034         if(sign != 0) 
4035           genSkipCond(&rFalseIfx,left,size-1,7);
4036         else 
4037           /* no need to compare to 0...*/
4038           /* NOTE: this is a de-generate compare that most certainly 
4039            *       creates some dead code. */
4040           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4041
4042         if(ifx) ifx->generated = 1;
4043         return;
4044
4045       }
4046       size--;
4047
4048       if(size == 0) {
4049         //i = (lit >> (size*8)) & 0xff;
4050         DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4051         
4052         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4053
4054         i = ((0-lit) & 0xff);
4055         if(sign) {
4056           if( i == 0x81) { 
4057             /* lit is 0x7f, all signed chars are less than
4058              * this except for 0x7f itself */
4059             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4060             genSkipz2(&rFalseIfx,0);
4061           } else {
4062             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4063             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i^0x80));
4064             genSkipc(&rFalseIfx);
4065           }
4066
4067         } else {
4068           if(lit == 1) {
4069             genSkipz2(&rFalseIfx,1);
4070           } else {
4071             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(i));
4072             genSkipc(&rFalseIfx);
4073           }
4074         }
4075
4076         if(ifx) ifx->generated = 1;
4077         return;
4078       }
4079
4080       /* chars are out of the way. now do ints and longs */
4081
4082
4083       DEBUGpic16_emitcode(";right lit","line = %d",__LINE__);
4084         
4085       /* special cases */
4086
4087       if(sign) {
4088
4089         if(lit == 0) {
4090           genSkipCond(&rFalseIfx,left,size,7);
4091           if(ifx) ifx->generated = 1;
4092           return;
4093         }
4094
4095         if(lit <0x100) {
4096           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4097
4098           //rFalseIfx.condition ^= 1;
4099           //genSkipCond(&rFalseIfx,left,size,7);
4100           //rFalseIfx.condition ^= 1;
4101
4102           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4103           if(rFalseIfx.condition)
4104             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4105           else
4106             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4107
4108           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x100-lit));
4109           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4110           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),1));
4111
4112           while(size > 1)
4113             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size--));
4114
4115           if(rFalseIfx.condition) {
4116             emitSKPZ;
4117             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4118
4119           } else {
4120             emitSKPNZ;
4121           }
4122
4123           genSkipc(&rFalseIfx);
4124           pic16_emitpLabel(truelbl->key);
4125           if(ifx) ifx->generated = 1;
4126           return;
4127
4128         }
4129
4130         if(size == 1) {
4131
4132           if( (lit & 0xff) == 0) {
4133             /* lower byte is zero */
4134             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4135             i = ((lit >> 8) & 0xff) ^0x80;
4136             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4137             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4138             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4139             genSkipc(&rFalseIfx);
4140
4141
4142             if(ifx) ifx->generated = 1;
4143             return;
4144
4145           }
4146         } else {
4147           /* Special cases for signed longs */
4148           if( (lit & 0xffffff) == 0) {
4149             /* lower byte is zero */
4150             DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4151             i = ((lit >> 8*3) & 0xff) ^0x80;
4152             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4153             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4154             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4155             genSkipc(&rFalseIfx);
4156
4157
4158             if(ifx) ifx->generated = 1;
4159             return;
4160
4161           }
4162
4163         }
4164
4165
4166         if(lit & (0x80 << (size*8))) {
4167           /* lit is negative */
4168           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4169
4170           //genSkipCond(&rFalseIfx,left,size,7);
4171
4172           pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4173
4174           if(rFalseIfx.condition)
4175             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4176           else
4177             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4178
4179
4180         } else {
4181           /* lit is positive */
4182           DEBUGpic16_emitcode(";right lit","line = %d signed compare to 0x%x",__LINE__,lit);
4183           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),size,FALSE,FALSE),7,0));
4184           if(rFalseIfx.condition)
4185             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4186           else
4187             pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4188
4189         }
4190
4191         /*
4192           This works, but is only good for ints.
4193           It also requires a "known zero" register.
4194           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(mlit & 0xff));
4195           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));
4196           pic16_emitpcode(POC_RLCFW,  pic16_popCopyReg(&pic16_pc_kzero));
4197           pic16_emitpcode(POC_ADDLW, pic16_popGetLit( ((mlit>>8) & 0xff)));
4198           pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),1));
4199           genSkipc(&rFalseIfx);
4200
4201           pic16_emitpLabel(truelbl->key);
4202           if(ifx) ifx->generated = 1;
4203           return;
4204         **/
4205           
4206         /* There are no more special cases, so perform a general compare */
4207   
4208         pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4209         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4210
4211         while(size--) {
4212
4213           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit >> (size*8)) & 0xff));
4214           emitSKPNZ;
4215           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4216         }
4217         //rFalseIfx.condition ^= 1;
4218         genSkipc(&rFalseIfx);
4219
4220         pic16_emitpLabel(truelbl->key);
4221
4222         if(ifx) ifx->generated = 1;
4223         return;
4224
4225
4226       }
4227
4228
4229       /* sign is out of the way. So now do an unsigned compare */
4230       DEBUGpic16_emitcode(";right lit","line = %d unsigned compare to 0x%x",__LINE__,lit);
4231
4232
4233       /* General case - compare to an unsigned literal on the right.*/
4234
4235       i = (lit >> (size*8)) & 0xff;
4236       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4237       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4238       while(size--) {
4239         i = (lit >> (size*8)) & 0xff;
4240
4241         if(i) {
4242           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4243           emitSKPNZ;
4244           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4245         } else {
4246           /* this byte of the lit is zero, 
4247            *if it's not the last then OR in the variable */
4248           if(size)
4249             pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(left),size));
4250         }
4251       }
4252
4253
4254       pic16_emitpLabel(lbl->key);
4255       //if(emitFinalCheck)
4256       genSkipc(&rFalseIfx);
4257       if(sign)
4258         pic16_emitpLabel(truelbl->key);
4259
4260       if(ifx) ifx->generated = 1;
4261       return;
4262
4263
4264     }
4265 #endif  // _swapp
4266
4267     if(AOP_TYPE(left) == AOP_LIT) {
4268       //symbol *lbl = newiTempLabel(NULL);
4269
4270       //EXPERIMENTAL lit = (unsigned long)(floatFromVal(AOP(left)->aopu.aop_lit));
4271
4272
4273       DEBUGpic16_emitcode(";left lit","lit = 0x%x,sign=%d",lit,sign);
4274
4275       /* Special cases */
4276       if((lit == 0) && (sign == 0)){
4277
4278         size--;
4279         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4280         while(size) 
4281           pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),--size));
4282
4283         genSkipz2(&rFalseIfx,0);
4284         if(ifx) ifx->generated = 1;
4285         return;
4286       }
4287
4288       if(size==1) {
4289         /* Special cases */
4290         lit &= 0xff;
4291         if(((lit == 0xff) && !sign) || ((lit==0x7f) && sign)) {
4292           /* degenerate compare can never be true */
4293           if(rFalseIfx.condition == 0)
4294             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rFalseIfx.lbl->key));
4295
4296           if(ifx) ifx->generated = 1;
4297           return;
4298         }
4299
4300         if(sign) {
4301           /* signed comparisons to a literal byte */
4302
4303           int lp1 = (lit+1) & 0xff;
4304
4305           DEBUGpic16_emitcode(";left lit","line = %d lit = 0x%x",__LINE__,lit);
4306           switch (lp1) {
4307           case 0:
4308             rFalseIfx.condition ^= 1;
4309             genSkipCond(&rFalseIfx,right,0,7);
4310             break;
4311           case 0x7f:
4312             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4313             pic16_emitpcode(POC_XORLW, pic16_popGetLit(0x7f));
4314             genSkipz2(&rFalseIfx,1);
4315             break;
4316           default:
4317             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4318             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4319             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(((-(lit+1)) & 0xff) ^ 0x80));
4320             rFalseIfx.condition ^= 1;
4321             genSkipc(&rFalseIfx);
4322             break;
4323           }
4324         } else {
4325           /* unsigned comparisons to a literal byte */
4326
4327           switch(lit & 0xff ) {
4328           case 0:
4329             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4330             genSkipz2(&rFalseIfx,0);
4331             break;
4332           case 0x7f:
4333             rFalseIfx.condition ^= 1;
4334             genSkipCond(&rFalseIfx,right,0,7);
4335             break;
4336
4337           default:
4338             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lit+1) & 0xff));
4339             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4340             DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4341             rFalseIfx.condition ^= 1;
4342             if (AOP_TYPE(result) == AOP_CRY)
4343               genSkipc(&rFalseIfx);
4344             else {
4345               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4346               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4347             }         
4348             break;
4349           }
4350         }
4351
4352         if(ifx) ifx->generated = 1;
4353         //goto check_carry;
4354         return;
4355
4356       } else {
4357
4358         /* Size is greater than 1 */
4359
4360         if(sign) {
4361           int lp1 = lit+1;
4362
4363           size--;
4364
4365           if(lp1 == 0) {
4366             /* this means lit = 0xffffffff, or -1 */
4367
4368
4369             DEBUGpic16_emitcode(";left lit = -1","line = %d ",__LINE__);
4370             rFalseIfx.condition ^= 1;
4371             genSkipCond(&rFalseIfx,right,size,7);
4372             if(ifx) ifx->generated = 1;
4373             return;
4374           }
4375
4376           if(lit == 0) {
4377             int s = size;
4378
4379             if(rFalseIfx.condition) {
4380               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4381               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4382             }
4383
4384             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4385             while(size--)
4386               pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4387
4388
4389             emitSKPZ;
4390             if(rFalseIfx.condition) {
4391               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4392               pic16_emitpLabel(truelbl->key);
4393             }else {
4394               rFalseIfx.condition ^= 1;
4395               genSkipCond(&rFalseIfx,right,s,7);
4396             }
4397
4398             if(ifx) ifx->generated = 1;
4399             return;
4400           }
4401
4402           if((size == 1) &&  (0 == (lp1&0xff))) {
4403             /* lower byte of signed word is zero */
4404             DEBUGpic16_emitcode(";left lit","line = %d  0x%x+1 low byte is zero",__LINE__,lit);
4405             i = ((lp1 >> 8) & 0xff) ^0x80;
4406             pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4407             pic16_emitpcode(POC_ADDLW, pic16_popGetLit( 0x80));
4408             pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x100-i));
4409             rFalseIfx.condition ^= 1;
4410             genSkipc(&rFalseIfx);
4411
4412
4413             if(ifx) ifx->generated = 1;
4414             return;
4415           }
4416
4417           if(lit & (0x80 << (size*8))) {
4418             /* Lit is less than zero */
4419             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is less than 0",__LINE__,lit);
4420             //rFalseIfx.condition ^= 1;
4421             //genSkipCond(&rFalseIfx,left,size,7);
4422             //rFalseIfx.condition ^= 1;
4423             pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4424             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4425
4426             if(rFalseIfx.condition)
4427               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4428             else
4429               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4430
4431
4432           } else {
4433             /* Lit is greater than or equal to zero */
4434             DEBUGpic16_emitcode(";left lit","line = %d  0x%x is greater than 0",__LINE__,lit);
4435             //rFalseIfx.condition ^= 1;
4436             //genSkipCond(&rFalseIfx,right,size,7);
4437             //rFalseIfx.condition ^= 1;
4438
4439             //pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4440             //pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4441
4442             pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size,FALSE,FALSE),7,0));
4443             if(rFalseIfx.condition)
4444               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4445             else
4446               pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4447
4448           }
4449
4450
4451           pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4452           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4453
4454           while(size--) {
4455
4456             pic16_emitpcode(POC_MOVLW, pic16_popGetLit((lp1 >> (size*8)) & 0xff));
4457             emitSKPNZ;
4458             pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4459           }
4460           rFalseIfx.condition ^= 1;
4461           //rFalseIfx.condition = 1;
4462           genSkipc(&rFalseIfx);
4463
4464           pic16_emitpLabel(truelbl->key);
4465
4466           if(ifx) ifx->generated = 1;
4467           return;
4468           // end of if (sign)
4469         } else {
4470
4471           /* compare word or long to an unsigned literal on the right.*/
4472
4473
4474           size--;
4475           if(lit < 0xff) {
4476             DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x < 0xff",__FUNCTION__,__LINE__,lit);
4477             switch (lit) {
4478             case 0:
4479               break; /* handled above */
4480 /*
4481             case 0xff:
4482               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4483               while(size--)
4484                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4485               genSkipz2(&rFalseIfx,0);
4486               break;
4487 */
4488             default:
4489               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4490               while(--size)
4491                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4492
4493               emitSKPZ;
4494               if(rFalseIfx.condition)
4495                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(rFalseIfx.lbl->key));
4496               else
4497                 pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(truelbl->key));
4498
4499
4500               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit+1));
4501               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),0));
4502
4503               rFalseIfx.condition ^= 1;
4504               genSkipc(&rFalseIfx);
4505             }
4506
4507             pic16_emitpLabel(truelbl->key);
4508
4509             if(ifx) ifx->generated = 1;
4510             return;
4511           }
4512
4513
4514           lit++;
4515           DEBUGpic16_emitcode ("; ***","%s  %d lit =0x%x",__FUNCTION__,__LINE__,lit);
4516           i = (lit >> (size*8)) & 0xff;
4517
4518           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4519           pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4520
4521           while(size--) {
4522             i = (lit >> (size*8)) & 0xff;
4523
4524             if(i) {
4525               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(i));
4526               emitSKPNZ;
4527               pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(right),size));
4528             } else {
4529               /* this byte of the lit is zero, 
4530                *if it's not the last then OR in the variable */
4531               if(size)
4532                 pic16_emitpcode(POC_IORFW, pic16_popGet(AOP(right),size));
4533             }
4534           }
4535
4536
4537           pic16_emitpLabel(lbl->key);
4538
4539           rFalseIfx.condition ^= 1;
4540           genSkipc(&rFalseIfx);
4541         }
4542
4543         if(sign)
4544           pic16_emitpLabel(truelbl->key);
4545         if(ifx) ifx->generated = 1;
4546         return;
4547       }
4548     }
4549     /* Compare two variables */
4550
4551     DEBUGpic16_emitcode(";sign","%d",sign);
4552
4553     size--;
4554     if(sign) {
4555       /* Sigh. thus sucks... */
4556       if(size) {
4557         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),size));
4558         pic16_emitpcode(POC_MOVWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4559         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x80));
4560         pic16_emitpcode(POC_XORWF, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4561         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),size));
4562         pic16_emitpcode(POC_SUBFW, pic16_popRegFromIdx(pic16_Gstack_base_addr));
4563       } else {
4564         /* Signed char comparison */
4565         /* Special thanks to Nikolai Golovchenko for this snippet */
4566         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
4567         pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),0));
4568         pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0)); /* could be any register */
4569         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(left),0));
4570         pic16_emitpcode(POC_XORFW, pic16_popGet(AOP(right),0));
4571         pic16_emitpcode(POC_ADDLW, pic16_popGetLit(0x80));
4572
4573         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4574         genSkipc(&rFalseIfx);
4575           
4576         if(ifx) ifx->generated = 1;
4577         return;
4578       }
4579
4580     } else {
4581
4582       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4583       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4584     }
4585
4586
4587     /* The rest of the bytes of a multi-byte compare */
4588     while (size) {
4589
4590       emitSKPZ;
4591       pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(lbl->key));
4592       size--;
4593
4594       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),size));
4595       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(left),size));
4596
4597
4598     }
4599
4600     pic16_emitpLabel(lbl->key);
4601
4602     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4603     if ((AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) || 
4604         (AOP_TYPE(result) == AOP_REG)) {
4605       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
4606       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),0));
4607     } else {
4608       genSkipc(&rFalseIfx);
4609     }         
4610     //genSkipc(&rFalseIfx);
4611     if(ifx) ifx->generated = 1;
4612
4613     return;
4614
4615   }
4616
4617   // check_carry:
4618   if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
4619     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4620     pic16_outBitC(result);
4621   } else {
4622     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4623     /* if the result is used in the next
4624        ifx conditional branch then generate
4625        code a little differently */
4626     if (ifx )
4627       genIfxJump (ifx,"c");
4628     else
4629       pic16_outBitC(result);
4630     /* leave the result in acc */
4631   }
4632
4633 }
4634
4635 /*-----------------------------------------------------------------*/
4636 /* genCmpGt :- greater than comparison                             */
4637 /*-----------------------------------------------------------------*/
4638 static void genCmpGt (iCode *ic, iCode *ifx)
4639 {
4640     operand *left, *right, *result;
4641     sym_link *letype , *retype;
4642     int sign ;
4643
4644     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4645     left = IC_LEFT(ic);
4646     right= IC_RIGHT(ic);
4647     result = IC_RESULT(ic);
4648
4649     letype = getSpec(operandType(left));
4650     retype =getSpec(operandType(right));
4651     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4652     /* assign the amsops */
4653     pic16_aopOp (left,ic,FALSE);
4654     pic16_aopOp (right,ic,FALSE);
4655     pic16_aopOp (result,ic,TRUE);
4656
4657     genCmp(right, left, result, ifx, sign);
4658
4659     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4660     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4661     pic16_freeAsmop(result,NULL,ic,TRUE); 
4662 }
4663
4664 /*-----------------------------------------------------------------*/
4665 /* genCmpLt - less than comparisons                                */
4666 /*-----------------------------------------------------------------*/
4667 static void genCmpLt (iCode *ic, iCode *ifx)
4668 {
4669     operand *left, *right, *result;
4670     sym_link *letype , *retype;
4671     int sign ;
4672
4673     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4674     left = IC_LEFT(ic);
4675     right= IC_RIGHT(ic);
4676     result = IC_RESULT(ic);
4677
4678     letype = getSpec(operandType(left));
4679     retype =getSpec(operandType(right));
4680     sign =  !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
4681
4682     /* assign the amsops */
4683     pic16_aopOp (left,ic,FALSE);
4684     pic16_aopOp (right,ic,FALSE);
4685     pic16_aopOp (result,ic,TRUE);
4686
4687     genCmp(left, right, result, ifx, sign);
4688
4689     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4690     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
4691     pic16_freeAsmop(result,NULL,ic,TRUE); 
4692 }
4693
4694 /*-----------------------------------------------------------------*/
4695 /* genc16bit2lit - compare a 16 bit value to a literal             */
4696 /*-----------------------------------------------------------------*/
4697 static void genc16bit2lit(operand *op, int lit, int offset)
4698 {
4699   int i;
4700
4701   DEBUGpic16_emitcode ("; ***","%s  %d, lit = %d",__FUNCTION__,__LINE__,lit);
4702   if( (lit&0xff) == 0) 
4703     i=1;
4704   else
4705     i=0;
4706
4707   switch( BYTEofLONG(lit,i)) { 
4708   case 0:
4709     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4710     break;
4711   case 1:
4712     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4713     break;
4714   case 0xff:
4715     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4716     break;
4717   default:
4718     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(op),offset+i));
4719     pic16_emitpcode(POC_XORLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4720   }
4721
4722   i ^= 1;
4723
4724   switch( BYTEofLONG(lit,i)) { 
4725   case 0:
4726     pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(op),offset+i));
4727     break;
4728   case 1:
4729     emitSKPNZ;
4730     pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(op),offset+i));
4731     break;
4732   case 0xff:
4733     emitSKPNZ;
4734     pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(op),offset+i));
4735     break;
4736   default:
4737     pic16_emitpcode(POC_MOVLW,pic16_popGetLit(BYTEofLONG(lit,i)));
4738     emitSKPNZ;
4739     pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(op),offset+i));
4740
4741   }
4742
4743 }
4744
4745 /*-----------------------------------------------------------------*/
4746 /* gencjneshort - compare and jump if not equal                    */
4747 /*-----------------------------------------------------------------*/
4748 static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
4749 {
4750   int size = max(AOP_SIZE(left),AOP_SIZE(right));
4751   int offset = 0;
4752   int res_offset = 0;  /* the result may be a different size then left or right */
4753   int res_size = AOP_SIZE(result);
4754   resolvedIfx rIfx;
4755   symbol *lbl;
4756
4757   unsigned long lit = 0L;
4758   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4759   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4760   if(result)
4761     DEBUGpic16_emitcode ("; ***","%s  %d result is not null",__FUNCTION__,__LINE__);
4762   resolveIfx(&rIfx,ifx);
4763   lbl =  newiTempLabel(NULL);
4764
4765
4766   /* if the left side is a literal or 
4767      if the right is in a pointer register and left 
4768      is not */
4769   if ((AOP_TYPE(left) == AOP_LIT) || 
4770       (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4771     operand *t = right;
4772     right = left;
4773     left = t;
4774   }
4775   if(AOP_TYPE(right) == AOP_LIT)
4776     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4777
4778   /* if the right side is a literal then anything goes */
4779   if (AOP_TYPE(right) == AOP_LIT &&
4780       AOP_TYPE(left) != AOP_DIR ) {
4781     switch(size) {
4782     case 2:
4783       genc16bit2lit(left, lit, 0);
4784       emitSKPNZ;
4785       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4786       break;
4787     default:
4788       while (size--) {
4789         if(lit & 0xff) {
4790           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4791           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4792         } else {
4793           pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4794         }
4795
4796         emitSKPNZ;
4797         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4798         offset++;
4799         if(res_offset < res_size-1)
4800           res_offset++;
4801         lit >>= 8;
4802       }
4803       break;
4804     }
4805   }
4806
4807   /* if the right side is in a register or in direct space or
4808      if the left is a pointer register & right is not */    
4809   else if (AOP_TYPE(right) == AOP_REG ||
4810            AOP_TYPE(right) == AOP_DIR || 
4811            (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) ||
4812            (IS_AOP_PREG(left) && !IS_AOP_PREG(right))) {
4813     //int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
4814     int lbl_key = lbl->key;
4815
4816     if(result) {
4817       pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),res_offset));
4818       //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4819     }else {
4820       DEBUGpic16_emitcode ("; ***","%s  %d -- ERROR",__FUNCTION__,__LINE__);
4821       fprintf(stderr, "%s  %d error - expecting result to be non_null\n",
4822               __FUNCTION__,__LINE__);
4823       return;
4824     }
4825
4826 /*     switch(size) { */
4827 /*     case 2: */
4828 /*       genc16bit2lit(left, lit, 0); */
4829 /*       emitSKPNZ; */
4830 /*       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key)); */
4831 /*       break; */
4832 /*     default: */
4833     while (size--) {
4834       int emit_skip=1;
4835       if((AOP_TYPE(left) == AOP_DIR) && 
4836          ((AOP_TYPE(right) == AOP_REG) || (AOP_TYPE(right) == AOP_DIR))) {
4837
4838         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4839         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4840
4841       } else if((AOP_TYPE(left) == AOP_DIR) && (AOP_TYPE(right) == AOP_LIT)){
4842             
4843         switch (lit & 0xff) {
4844         case 0:
4845           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4846           break;
4847         case 1:
4848           pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
4849           pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4850           //pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl->key));
4851           emit_skip=0;
4852           break;
4853         case 0xff:
4854           pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4855           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4856           //pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
4857           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4858           emit_skip=0;
4859           break;
4860         default:
4861           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4862           pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
4863         }
4864         lit >>= 8;
4865
4866       } else {
4867         pic16_emitpcode(POC_MOVF,pic16_popGet(AOP(left),offset));
4868       }
4869       if(emit_skip) {
4870         if(AOP_TYPE(result) == AOP_CRY) {
4871           pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4872           if(rIfx.condition)
4873             emitSKPNZ;
4874           else
4875             emitSKPZ;
4876           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4877         } else {
4878           /* fix me. probably need to check result size too */
4879           //pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),0));
4880           if(rIfx.condition)
4881             emitSKPZ;
4882           else
4883             emitSKPNZ;
4884           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(lbl_key));
4885           //pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4886         }
4887         if(ifx)
4888           ifx->generated=1;
4889       }
4890       emit_skip++;
4891       offset++;
4892       if(res_offset < res_size-1)
4893         res_offset++;
4894     }
4895 /*       break; */
4896 /*     } */
4897   } else if(AOP_TYPE(right) == AOP_REG &&
4898             AOP_TYPE(left) != AOP_DIR){
4899
4900     while(size--) {
4901       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
4902       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
4903       pic16_emitcode(";***","%s  %d",__FUNCTION__,__LINE__);
4904       if(rIfx.condition)
4905         emitSKPNZ;
4906       else
4907         emitSKPZ;
4908       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4909       offset++;
4910       if(res_offset < res_size-1)
4911         res_offset++;
4912     }
4913       
4914   }else{
4915     /* right is a pointer reg need both a & b */
4916     while(size--) {
4917       char *l = pic16_aopGet(AOP(left),offset,FALSE,FALSE);
4918       if(strcmp(l,"b"))
4919         pic16_emitcode("mov","b,%s",l);
4920       MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
4921       pic16_emitcode("cjne","a,b,%05d_DS_",lbl->key+100);    
4922       offset++;
4923     }
4924   }
4925
4926   pic16_emitpcode(POC_INCF,pic16_popGet(AOP(result),res_offset));
4927   if(!rIfx.condition)
4928     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
4929
4930   pic16_emitpLabel(lbl->key);
4931
4932   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4933
4934   if(ifx)
4935     ifx->generated = 1;
4936 }
4937
4938 #if 0
4939 /*-----------------------------------------------------------------*/
4940 /* gencjne - compare and jump if not equal                         */
4941 /*-----------------------------------------------------------------*/
4942 static void gencjne(operand *left, operand *right, iCode *ifx)
4943 {
4944     symbol *tlbl  = newiTempLabel(NULL);
4945
4946     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4947     gencjneshort(left, right, lbl);
4948
4949     pic16_emitcode("mov","a,%s",one);
4950     pic16_emitcode("sjmp","%05d_DS_",tlbl->key+100);
4951     pic16_emitcode("","%05d_DS_:",lbl->key+100);
4952     pic16_emitcode("clr","a");
4953     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
4954
4955     pic16_emitpLabel(lbl->key);
4956     pic16_emitpLabel(tlbl->key);
4957
4958 }
4959 #endif
4960
4961 /*-----------------------------------------------------------------*/
4962 /* genCmpEq - generates code for equal to                          */
4963 /*-----------------------------------------------------------------*/
4964 static void genCmpEq (iCode *ic, iCode *ifx)
4965 {
4966     operand *left, *right, *result;
4967     unsigned long lit = 0L;
4968     int size,offset=0;
4969     symbol *falselbl  = newiTempLabel(NULL);
4970
4971
4972     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
4973
4974     if(ifx)
4975       DEBUGpic16_emitcode ("; ifx is non-null","");
4976     else
4977       DEBUGpic16_emitcode ("; ifx is null","");
4978
4979     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
4980     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
4981     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
4982
4983     size = max(AOP_SIZE(left),AOP_SIZE(right));
4984
4985     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
4986
4987     /* if literal, literal on the right or 
4988     if the right is in a pointer register and left 
4989     is not */
4990     if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) || 
4991         (IS_AOP_PREG(right) && !IS_AOP_PREG(left))) {
4992       operand *tmp = right ;
4993       right = left;
4994       left = tmp;
4995     }
4996
4997
4998     if(ifx && !AOP_SIZE(result)){
4999         DEBUGpic16_emitcode ("; ***","%s  %d CASE 1",__FUNCTION__,__LINE__);
5000         symbol *tlbl;
5001         /* if they are both bit variables */
5002         if (AOP_TYPE(left) == AOP_CRY &&
5003             ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5004                 DEBUGpic16_emitcode ("; ***","%s  %d CASE 11",__FUNCTION__,__LINE__);
5005             if(AOP_TYPE(right) == AOP_LIT){
5006                 unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5007                 if(lit == 0L){
5008                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5009                     pic16_emitcode("cpl","c");
5010                 } else if(lit == 1L) {
5011                     pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5012                 } else {
5013                     pic16_emitcode("clr","c");
5014                 }
5015                 /* AOP_TYPE(right) == AOP_CRY */
5016             } else {
5017                 symbol *lbl = newiTempLabel(NULL);
5018                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5019                 pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5020                 pic16_emitcode("cpl","c");
5021                 pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5022             }
5023             /* if true label then we jump if condition
5024             supplied is true */
5025             tlbl = newiTempLabel(NULL);
5026             if ( IC_TRUE(ifx) ) {
5027                 pic16_emitcode("jnc","%05d_DS_",tlbl->key+100);
5028                 pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100);
5029             } else {
5030                 pic16_emitcode("jc","%05d_DS_",tlbl->key+100);
5031                 pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ifx)->key+100);
5032             }
5033             pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5034
5035                 {
5036                 /* left and right are both bit variables, result is carry */
5037                         resolvedIfx rIfx;
5038               
5039                         resolveIfx(&rIfx,ifx);
5040
5041                         pic16_emitpcode(POC_MOVLW,pic16_popGet(AOP(left),0));
5042                         pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),0));
5043                         pic16_emitpcode(POC_BTFSC,pic16_popGet(AOP(right),0));
5044                         pic16_emitpcode(POC_ANDLW,pic16_popGet(AOP(left),0));
5045                         genSkipz2(&rIfx,0);
5046                 }
5047         } else {
5048
5049                         DEBUGpic16_emitcode ("; ***","%s  %d CASE 12",__FUNCTION__,__LINE__);
5050
5051                         /* They're not both bit variables. Is the right a literal? */
5052                         if(AOP_TYPE(right) == AOP_LIT) {
5053                         lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5054             
5055                         switch(size) {
5056
5057                                 case 1:
5058                                         switch(lit & 0xff) {
5059                                                 case 1:
5060                                                                 if ( IC_TRUE(ifx) ) {
5061                                                                         pic16_emitpcode(POC_DECFW,pic16_popGet(AOP(left),offset));
5062                                                                         emitSKPNZ;
5063                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5064                                                                 } else {
5065                                                                         pic16_emitpcode(POC_DECFSZW,pic16_popGet(AOP(left),offset));
5066                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5067                                                                 }
5068                                                                 break;
5069                                                 case 0xff:
5070                                                                 if ( IC_TRUE(ifx) ) {
5071                                                                         pic16_emitpcode(POC_INCFW,pic16_popGet(AOP(left),offset));
5072                                                                         emitSKPNZ;
5073                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5074                                                                 } else {
5075                                                                         pic16_emitpcode(POC_INCFSZW,pic16_popGet(AOP(left),offset));
5076                                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5077                                                                 }
5078                                                                 break;
5079                                                 default:
5080                                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5081                                                                 if(lit)
5082                                                                         pic16_emitpcode(POC_XORLW,pic16_popGetLit(lit & 0xff));
5083                                                                 genSkip(ifx,'z');
5084                                         } // switch lit
5085
5086
5087                                         /* end of size == 1 */
5088                                         break;
5089               
5090                                 case 2:
5091                                         genc16bit2lit(left,lit,offset);
5092                                         genSkip(ifx,'z');
5093                                         break;
5094                                         /* end of size == 2 */
5095
5096                                 default:
5097                                         /* size is 4 */
5098                                         if(lit==0) {
5099                                                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5100                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),1));
5101                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5102                                                 pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5103                                                 genSkip(ifx,'z');
5104                                         } else {
5105                                                 /* search for patterns that can be optimized */
5106
5107                                                 genc16bit2lit(left,lit,0);
5108                                                 lit >>= 16;
5109                                                 if(lit) {
5110                                                                 if(IC_TRUE(ifx))
5111                                                                 emitSKPZ; // if hi word unequal
5112                                                                 else
5113                                                                 emitSKPNZ; // if hi word equal
5114                                                                 // fail early
5115                                                         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(falselbl->key));
5116                                                         genc16bit2lit(left,lit,2);
5117                                                         genSkip(ifx,'z');
5118                                                 } else {
5119                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),2));
5120                                                         pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),3));
5121                                                         genSkip(ifx,'z');
5122                                                 }
5123                                         }
5124                                                 pic16_emitpLabel(falselbl->key);
5125                                                 break;
5126
5127                         } // switch size
5128           
5129                         ifx->generated = 1;
5130                         goto release ;
5131             
5132
5133           } else if(AOP_TYPE(right) == AOP_CRY ) {
5134             /* we know the left is not a bit, but that the right is */
5135             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5136             pic16_emitpcode( ( (IC_TRUE(ifx)) ? POC_BTFSC : POC_BTFSS),
5137                       pic16_popGet(AOP(right),offset));
5138             pic16_emitpcode(POC_XORLW,pic16_popGetLit(1));
5139
5140             /* if the two are equal, then W will be 0 and the Z bit is set
5141              * we could test Z now, or go ahead and check the high order bytes if
5142              * the variable we're comparing is larger than a byte. */
5143
5144             while(--size)
5145               pic16_emitpcode(POC_IORFW,pic16_popGet(AOP(left),offset));
5146
5147             if ( IC_TRUE(ifx) ) {
5148               emitSKPNZ;
5149               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5150               // pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5151             } else {
5152               emitSKPZ;
5153               pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5154               // pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5155             }
5156
5157           } else {
5158             /* They're both variables that are larger than bits */
5159             int s = size;
5160
5161             tlbl = newiTempLabel(NULL);
5162
5163             while(size--) {
5164               pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5165               pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
5166
5167               if ( IC_TRUE(ifx) ) {
5168                 if(size) {
5169                   emitSKPZ;
5170                 
5171                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPZ");
5172
5173                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
5174                   pic16_emitcode(" goto","_%05d_DS_",tlbl->key+100+labelOffset);
5175                 } else {
5176                   emitSKPNZ;
5177
5178                         DEBUGpic16_emitcode (";","\tIC_TRUE emitSKPNZ");
5179
5180
5181                   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
5182                   pic16_emitcode(" goto","_%05d_DS_",IC_TRUE(ifx)->key+100+labelOffset);
5183                 }
5184               } else {
5185                 emitSKPZ;
5186
5187                         DEBUGpic16_emitcode (";","\tnot IC_TRUE emitSKPZ");
5188
5189                 pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ifx)->key));
5190                 pic16_emitcode(" goto","_%05d_DS_",IC_FALSE(ifx)->key+100+labelOffset);
5191               }
5192               offset++;
5193             }
5194             if(s>1 && IC_TRUE(ifx)) {
5195               pic16_emitpLabel(tlbl->key);
5196               pic16_emitcode("","_%05d_DS_:",tlbl->key+100+labelOffset);                
5197             }
5198           }
5199         }
5200         /* mark the icode as generated */
5201         ifx->generated = 1;
5202         goto release ;
5203     }
5204
5205     /* if they are both bit variables */
5206     if (AOP_TYPE(left) == AOP_CRY &&
5207         ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
5208         DEBUGpic16_emitcode ("; ***","%s  %d CASE 2",__FUNCTION__,__LINE__);
5209         if(AOP_TYPE(right) == AOP_LIT){
5210             unsigned long lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
5211             if(lit == 0L){
5212                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5213                 pic16_emitcode("cpl","c");
5214             } else if(lit == 1L) {
5215                 pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5216             } else {
5217                 pic16_emitcode("clr","c");
5218             }
5219             /* AOP_TYPE(right) == AOP_CRY */
5220         } else {
5221             symbol *lbl = newiTempLabel(NULL);
5222             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5223             pic16_emitcode("jb","%s,%05d_DS_",AOP(right)->aopu.aop_dir,(lbl->key+100));
5224             pic16_emitcode("cpl","c");
5225             pic16_emitcode("","%05d_DS_:",(lbl->key+100));
5226         }
5227         /* c = 1 if egal */
5228         if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)){
5229             pic16_outBitC(result);
5230             goto release ;
5231         }
5232         if (ifx) {
5233             genIfxJump (ifx,"c");
5234             goto release ;
5235         }
5236         /* if the result is used in an arithmetic operation
5237         then put the result in place */
5238         pic16_outBitC(result);
5239     } else {
5240       
5241       DEBUGpic16_emitcode ("; ***","%s  %d CASE 3",__FUNCTION__,__LINE__);
5242       gencjne(left,right,result,ifx);
5243 /*
5244       if(ifx) 
5245         gencjne(left,right,newiTempLabel(NULL));
5246       else {
5247         if(IC_TRUE(ifx)->key)
5248           gencjne(left,right,IC_TRUE(ifx)->key);
5249         else
5250           gencjne(left,right,IC_FALSE(ifx)->key);
5251         ifx->generated = 1;
5252         goto release ;
5253       }
5254       if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
5255         pic16_aopPut(AOP(result),"a",0);
5256         goto release ;
5257       }
5258
5259       if (ifx) {
5260         genIfxJump (ifx,"a");
5261         goto release ;
5262       }
5263 */
5264       /* if the result is used in an arithmetic operation
5265          then put the result in place */
5266 /*
5267       if (AOP_TYPE(result) != AOP_CRY) 
5268         pic16_outAcc(result);
5269 */
5270       /* leave the result in acc */
5271     }
5272
5273 release:
5274     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5275     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5276     pic16_freeAsmop(result,NULL,ic,TRUE);
5277 }
5278
5279 /*-----------------------------------------------------------------*/
5280 /* ifxForOp - returns the icode containing the ifx for operand     */
5281 /*-----------------------------------------------------------------*/
5282 static iCode *ifxForOp ( operand *op, iCode *ic )
5283 {
5284     /* if true symbol then needs to be assigned */
5285     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5286     if (IS_TRUE_SYMOP(op))
5287         return NULL ;
5288
5289     /* if this has register type condition and
5290     the next instruction is ifx with the same operand
5291     and live to of the operand is upto the ifx only then */
5292     if (ic->next &&
5293         ic->next->op == IFX &&
5294         IC_COND(ic->next)->key == op->key &&
5295         OP_SYMBOL(op)->liveTo <= ic->next->seq )
5296         return ic->next;
5297
5298     if (ic->next &&
5299         ic->next->op == IFX &&
5300         IC_COND(ic->next)->key == op->key) {
5301       DEBUGpic16_emitcode ("; WARNING ","%d IGNORING liveTo range in %s",__LINE__,__FUNCTION__);
5302       return ic->next;
5303     }
5304
5305     DEBUGpic16_emitcode ("; NULL :(","%d",__LINE__);
5306     if (ic->next &&
5307         ic->next->op == IFX)
5308       DEBUGpic16_emitcode ("; ic-next"," is an IFX");
5309
5310     if (ic->next &&
5311         ic->next->op == IFX &&
5312         IC_COND(ic->next)->key == op->key) {
5313       DEBUGpic16_emitcode ("; "," key is okay");
5314       DEBUGpic16_emitcode ("; "," key liveTo %d, next->seq = %d",
5315                            OP_SYMBOL(op)->liveTo,
5316                            ic->next->seq);
5317     }
5318
5319
5320     return NULL;
5321 }
5322 /*-----------------------------------------------------------------*/
5323 /* genAndOp - for && operation                                     */
5324 /*-----------------------------------------------------------------*/
5325 static void genAndOp (iCode *ic)
5326 {
5327     operand *left,*right, *result;
5328 /*     symbol *tlbl; */
5329
5330     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5331     /* note here that && operations that are in an
5332     if statement are taken away by backPatchLabels
5333     only those used in arthmetic operations remain */
5334     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5335     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5336     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5337
5338     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5339
5340     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
5341     pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),0));
5342     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
5343
5344     /* if both are bit variables */
5345 /*     if (AOP_TYPE(left) == AOP_CRY && */
5346 /*         AOP_TYPE(right) == AOP_CRY ) { */
5347 /*         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir); */
5348 /*         pic16_emitcode("anl","c,%s",AOP(right)->aopu.aop_dir); */
5349 /*         pic16_outBitC(result); */
5350 /*     } else { */
5351 /*         tlbl = newiTempLabel(NULL); */
5352 /*         pic16_toBoolean(left);     */
5353 /*         pic16_emitcode("jz","%05d_DS_",tlbl->key+100); */
5354 /*         pic16_toBoolean(right); */
5355 /*         pic16_emitcode("","%05d_DS_:",tlbl->key+100); */
5356 /*         pic16_outBitAcc(result); */
5357 /*     } */
5358
5359     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5360     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5361     pic16_freeAsmop(result,NULL,ic,TRUE);
5362 }
5363
5364
5365 /*-----------------------------------------------------------------*/
5366 /* genOrOp - for || operation                                      */
5367 /*-----------------------------------------------------------------*/
5368 /*
5369   tsd pic port -
5370   modified this code, but it doesn't appear to ever get called
5371 */
5372
5373 static void genOrOp (iCode *ic)
5374 {
5375     operand *left,*right, *result;
5376     symbol *tlbl;
5377
5378     /* note here that || operations that are in an
5379     if statement are taken away by backPatchLabels
5380     only those used in arthmetic operations remain */
5381     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5382     pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
5383     pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
5384     pic16_aopOp((result=IC_RESULT(ic)),ic,FALSE);
5385
5386     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5387
5388     /* if both are bit variables */
5389     if (AOP_TYPE(left) == AOP_CRY &&
5390         AOP_TYPE(right) == AOP_CRY ) {
5391       pic16_emitcode("clrc","");
5392       pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5393                AOP(left)->aopu.aop_dir,
5394                AOP(left)->aopu.aop_dir);
5395       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5396                AOP(right)->aopu.aop_dir,
5397                AOP(right)->aopu.aop_dir);
5398       pic16_emitcode("setc","");
5399
5400     } else {
5401         tlbl = newiTempLabel(NULL);
5402         pic16_toBoolean(left);
5403         emitSKPZ;
5404         pic16_emitcode("goto","%05d_DS_",tlbl->key+100+labelOffset);
5405         pic16_toBoolean(right);
5406         pic16_emitcode("","%05d_DS_:",tlbl->key+100+labelOffset);
5407
5408         pic16_outBitAcc(result);
5409     }
5410
5411     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5412     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5413     pic16_freeAsmop(result,NULL,ic,TRUE);            
5414 }
5415
5416 /*-----------------------------------------------------------------*/
5417 /* isLiteralBit - test if lit == 2^n                               */
5418 /*-----------------------------------------------------------------*/
5419 static int isLiteralBit(unsigned long lit)
5420 {
5421     unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
5422     0x100L,0x200L,0x400L,0x800L,
5423     0x1000L,0x2000L,0x4000L,0x8000L,
5424     0x10000L,0x20000L,0x40000L,0x80000L,
5425     0x100000L,0x200000L,0x400000L,0x800000L,
5426     0x1000000L,0x2000000L,0x4000000L,0x8000000L,
5427     0x10000000L,0x20000000L,0x40000000L,0x80000000L};
5428     int idx;
5429     
5430     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5431     for(idx = 0; idx < 32; idx++)
5432         if(lit == pw[idx])
5433             return idx+1;
5434     return 0;
5435 }
5436
5437 /*-----------------------------------------------------------------*/
5438 /* continueIfTrue -                                                */
5439 /*-----------------------------------------------------------------*/
5440 static void continueIfTrue (iCode *ic)
5441 {
5442     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5443     if(IC_TRUE(ic))
5444         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5445     ic->generated = 1;
5446 }
5447
5448 /*-----------------------------------------------------------------*/
5449 /* jmpIfTrue -                                                     */
5450 /*-----------------------------------------------------------------*/
5451 static void jumpIfTrue (iCode *ic)
5452 {
5453     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5454     if(!IC_TRUE(ic))
5455         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5456     ic->generated = 1;
5457 }
5458
5459 /*-----------------------------------------------------------------*/
5460 /* jmpTrueOrFalse -                                                */
5461 /*-----------------------------------------------------------------*/
5462 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
5463 {
5464     // ugly but optimized by peephole
5465     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5466     if(IC_TRUE(ic)){
5467         symbol *nlbl = newiTempLabel(NULL);
5468         pic16_emitcode("sjmp","%05d_DS_",nlbl->key+100);                 
5469         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5470         pic16_emitcode("ljmp","%05d_DS_",IC_TRUE(ic)->key+100);
5471         pic16_emitcode("","%05d_DS_:",nlbl->key+100);
5472     }
5473     else{
5474         pic16_emitcode("ljmp","%05d_DS_",IC_FALSE(ic)->key+100);
5475         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5476     }
5477     ic->generated = 1;
5478 }
5479
5480 /*-----------------------------------------------------------------*/
5481 /* genAnd  - code for and                                          */
5482 /*-----------------------------------------------------------------*/
5483 static void genAnd (iCode *ic, iCode *ifx)
5484 {
5485   operand *left, *right, *result;
5486   int size, offset=0;  
5487   unsigned long lit = 0L;
5488   int bytelit = 0;
5489   resolvedIfx rIfx;
5490
5491
5492   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5493   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5494   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5495   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5496
5497   resolveIfx(&rIfx,ifx);
5498
5499   /* if left is a literal & right is not then exchange them */
5500   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5501       AOP_NEEDSACC(left)) {
5502     operand *tmp = right ;
5503     right = left;
5504     left = tmp;
5505   }
5506
5507   /* if result = right then exchange them */
5508   if(pic16_sameRegs(AOP(result),AOP(right))){
5509     operand *tmp = right ;
5510     right = left;
5511     left = tmp;
5512   }
5513
5514   /* if right is bit then exchange them */
5515   if (AOP_TYPE(right) == AOP_CRY &&
5516       AOP_TYPE(left) != AOP_CRY){
5517     operand *tmp = right ;
5518     right = left;
5519     left = tmp;
5520   }
5521   if(AOP_TYPE(right) == AOP_LIT)
5522     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5523
5524   size = AOP_SIZE(result);
5525
5526   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5527
5528   // if(bit & yy)
5529   // result = bit & yy;
5530   if (AOP_TYPE(left) == AOP_CRY){
5531     // c = bit & literal;
5532     if(AOP_TYPE(right) == AOP_LIT){
5533       if(lit & 1) {
5534         if(size && pic16_sameRegs(AOP(result),AOP(left)))
5535           // no change
5536           goto release;
5537         pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
5538       } else {
5539         // bit(result) = 0;
5540         if(size && (AOP_TYPE(result) == AOP_CRY)){
5541           pic16_emitcode("clr","%s",AOP(result)->aopu.aop_dir);
5542           goto release;
5543         }
5544         if((AOP_TYPE(result) == AOP_CRY) && ifx){
5545           jumpIfTrue(ifx);
5546           goto release;
5547         }
5548         pic16_emitcode("clr","c");
5549       }
5550     } else {
5551       if (AOP_TYPE(right) == AOP_CRY){
5552         // c = bit & bit;
5553         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
5554         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5555       } else {
5556         // c = bit & val;
5557         MOVA(pic16_aopGet(AOP(right),0,FALSE,FALSE));
5558         // c = lsb
5559         pic16_emitcode("rrc","a");
5560         pic16_emitcode("anl","c,%s",AOP(left)->aopu.aop_dir);
5561       }
5562     }
5563     // bit = c
5564     // val = c
5565     if(size)
5566       pic16_outBitC(result);
5567     // if(bit & ...)
5568     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5569       genIfxJump(ifx, "c");           
5570     goto release ;
5571   }
5572
5573   // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
5574   // bit = val & 0xZZ     - size = 1, ifx = FALSE -
5575   if((AOP_TYPE(right) == AOP_LIT) &&
5576      (AOP_TYPE(result) == AOP_CRY) &&
5577      (AOP_TYPE(left) != AOP_CRY)){
5578     int posbit = isLiteralBit(lit);
5579     /* left &  2^n */
5580     if(posbit){
5581       posbit--;
5582       //MOVA(pic16_aopGet(AOP(left),posbit>>3,FALSE,FALSE));
5583       // bit = left & 2^n
5584       if(size)
5585         pic16_emitcode("mov","c,acc.%d",posbit&0x07);
5586       // if(left &  2^n)
5587       else{
5588         if(ifx){
5589 /*
5590           if(IC_TRUE(ifx)) {
5591             pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5592             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ic)->key));
5593           } else {
5594             pic16_emitpcode(POC_BTFSS,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5595             pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_FALSE(ic)->key));
5596           }
5597 */
5598           pic16_emitpcode(((rIfx.condition) ? POC_BTFSC : POC_BTFSS),
5599                     pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),posbit,0));
5600           pic16_emitpcode(POC_GOTO,pic16_popGetLabel(rIfx.lbl->key));
5601           
5602           ifx->generated = 1;
5603         }
5604         goto release;
5605       }
5606     } else {
5607       symbol *tlbl = newiTempLabel(NULL);
5608       int sizel = AOP_SIZE(left);
5609       if(size)
5610         pic16_emitcode("setb","c");
5611       while(sizel--){
5612         if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
5613           MOVA( pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5614           // byte ==  2^n ?
5615           if((posbit = isLiteralBit(bytelit)) != 0)
5616             pic16_emitcode("jb","acc.%d,%05d_DS_",(posbit-1)&0x07,tlbl->key+100);
5617           else{
5618             if(bytelit != 0x0FFL)
5619               pic16_emitcode("anl","a,%s",
5620                              pic16_aopGet(AOP(right),offset,FALSE,TRUE));
5621             pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5622           }
5623         }
5624         offset++;
5625       }
5626       // bit = left & literal
5627       if(size){
5628         pic16_emitcode("clr","c");
5629         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5630       }
5631       // if(left & literal)
5632       else{
5633         if(ifx)
5634           jmpTrueOrFalse(ifx, tlbl);
5635         goto release ;
5636       }
5637     }
5638     pic16_outBitC(result);
5639     goto release ;
5640   }
5641
5642   /* if left is same as result */
5643   if(pic16_sameRegs(AOP(result),AOP(left))){
5644     int know_W = -1;
5645     for(;size--; offset++,lit>>=8) {
5646       if(AOP_TYPE(right) == AOP_LIT){
5647         switch(lit & 0xff) {
5648         case 0x00:
5649           /*  and'ing with 0 has clears the result */
5650 //        pic16_emitcode("clrf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5651           pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5652           break;
5653         case 0xff:
5654           /* and'ing with 0xff is a nop when the result and left are the same */
5655           break;
5656
5657         default:
5658           {
5659             int p = my_powof2( (~lit) & 0xff );
5660             if(p>=0) {
5661               /* only one bit is set in the literal, so use a bcf instruction */
5662 //            pic16_emitcode("bcf","%s,%d",pic16_aopGet(AOP(left),offset,FALSE,TRUE),p);
5663               pic16_emitpcode(POC_BCF,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5664
5665             } else {
5666               pic16_emitcode("movlw","0x%x", (lit & 0xff));
5667               pic16_emitcode("andwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
5668               if(know_W != (lit&0xff))
5669                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5670               know_W = lit &0xff;
5671               pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5672             }
5673           }    
5674         }
5675       } else {
5676         if (AOP_TYPE(left) == AOP_ACC) {
5677           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5678         } else {                    
5679           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5680           pic16_emitpcode(POC_ANDWF,pic16_popGet(AOP(left),offset));
5681
5682         }
5683       }
5684     }
5685
5686   } else {
5687     // left & result in different registers
5688     if(AOP_TYPE(result) == AOP_CRY){
5689       // result = bit
5690       // if(size), result in bit
5691       // if(!size && ifx), conditional oper: if(left & right)
5692       symbol *tlbl = newiTempLabel(NULL);
5693       int sizer = min(AOP_SIZE(left),AOP_SIZE(right));
5694       if(size)
5695         pic16_emitcode("setb","c");
5696       while(sizer--){
5697         MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5698         pic16_emitcode("anl","a,%s",
5699                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5700         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
5701         offset++;
5702       }
5703       if(size){
5704         CLRC;
5705         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5706         pic16_outBitC(result);
5707       } else if(ifx)
5708         jmpTrueOrFalse(ifx, tlbl);
5709     } else {
5710       for(;(size--);offset++) {
5711         // normal case
5712         // result = left & right
5713         if(AOP_TYPE(right) == AOP_LIT){
5714           int t = (lit >> (offset*8)) & 0x0FFL;
5715           switch(t) { 
5716           case 0x00:
5717             pic16_emitcode("clrf","%s",
5718                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5719             pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
5720             break;
5721           case 0xff:
5722             pic16_emitcode("movf","%s,w",
5723                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5724             pic16_emitcode("movwf","%s",
5725                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5726             pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
5727             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5728             break;
5729           default:
5730             pic16_emitcode("movlw","0x%x",t);
5731             pic16_emitcode("andwf","%s,w",
5732                            pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5733             pic16_emitcode("movwf","%s",
5734                            pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5735               
5736             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
5737             pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5738             pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5739           }
5740           continue;
5741         }
5742
5743         if (AOP_TYPE(left) == AOP_ACC) {
5744           pic16_emitcode("andwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5745           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(right),offset));
5746         } else {
5747           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5748           pic16_emitcode("andwf","%s,w",
5749                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5750           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
5751           pic16_emitpcode(POC_ANDFW,pic16_popGet(AOP(left),offset));
5752         }
5753         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
5754         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
5755       }
5756     }
5757   }
5758
5759   release :
5760     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5761   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
5762   pic16_freeAsmop(result,NULL,ic,TRUE);     
5763 }
5764
5765 /*-----------------------------------------------------------------*/
5766 /* genOr  - code for or                                            */
5767 /*-----------------------------------------------------------------*/
5768 static void genOr (iCode *ic, iCode *ifx)
5769 {
5770     operand *left, *right, *result;
5771     int size, offset=0;
5772     unsigned long lit = 0L;
5773
5774     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
5775
5776     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
5777     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
5778     pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
5779
5780     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5781
5782     /* if left is a literal & right is not then exchange them */
5783     if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
5784         AOP_NEEDSACC(left)) {
5785         operand *tmp = right ;
5786         right = left;
5787         left = tmp;
5788     }
5789
5790     /* if result = right then exchange them */
5791     if(pic16_sameRegs(AOP(result),AOP(right))){
5792         operand *tmp = right ;
5793         right = left;
5794         left = tmp;
5795     }
5796
5797     /* if right is bit then exchange them */
5798     if (AOP_TYPE(right) == AOP_CRY &&
5799         AOP_TYPE(left) != AOP_CRY){
5800         operand *tmp = right ;
5801         right = left;
5802         left = tmp;
5803     }
5804
5805     DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
5806
5807     if(AOP_TYPE(right) == AOP_LIT)
5808         lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
5809
5810     size = AOP_SIZE(result);
5811
5812     // if(bit | yy)
5813     // xx = bit | yy;
5814     if (AOP_TYPE(left) == AOP_CRY){
5815         if(AOP_TYPE(right) == AOP_LIT){
5816             // c = bit & literal;
5817             if(lit){
5818                 // lit != 0 => result = 1
5819                 if(AOP_TYPE(result) == AOP_CRY){
5820                   if(size)
5821                     pic16_emitpcode(POC_BSF, pic16_popGet(AOP(result),0));
5822                   //pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5823                   //     AOP(result)->aopu.aop_dir,
5824                   //     AOP(result)->aopu.aop_dir);
5825                     else if(ifx)
5826                         continueIfTrue(ifx);
5827                     goto release;
5828                 }
5829             } else {
5830                 // lit == 0 => result = left
5831                 if(size && pic16_sameRegs(AOP(result),AOP(left)))
5832                     goto release;
5833                 pic16_emitcode(";XXX mov","c,%s  %s,%d",AOP(left)->aopu.aop_dir,__FILE__,__LINE__);
5834             }
5835         } else {
5836             if (AOP_TYPE(right) == AOP_CRY){
5837               if(pic16_sameRegs(AOP(result),AOP(left))){
5838                 // c = bit | bit;
5839                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5840                 pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
5841                 pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5842
5843                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5844                          AOP(result)->aopu.aop_dir,
5845                          AOP(result)->aopu.aop_dir);
5846                 pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5847                          AOP(right)->aopu.aop_dir,
5848                          AOP(right)->aopu.aop_dir);
5849                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5850                          AOP(result)->aopu.aop_dir,
5851                          AOP(result)->aopu.aop_dir);
5852               } else {
5853                 if( AOP_TYPE(result) == AOP_ACC) {
5854                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
5855                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5856                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5857                   pic16_emitpcode(POC_MOVLW, pic16_popGetLit(1));
5858
5859                 } else {
5860
5861                   pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5862                   pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
5863                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5864                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5865
5866                   pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
5867                                  AOP(result)->aopu.aop_dir,
5868                                  AOP(result)->aopu.aop_dir);
5869                   pic16_emitcode("btfss","(%s >> 3), (%s & 7)",
5870                                  AOP(right)->aopu.aop_dir,
5871                                  AOP(right)->aopu.aop_dir);
5872                   pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
5873                                  AOP(left)->aopu.aop_dir,
5874                                  AOP(left)->aopu.aop_dir);
5875                   pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
5876                                  AOP(result)->aopu.aop_dir,
5877                                  AOP(result)->aopu.aop_dir);
5878                 }
5879               }
5880             } else {
5881                 // c = bit | val;
5882                 symbol *tlbl = newiTempLabel(NULL);
5883                 pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5884
5885
5886                 pic16_emitpcode(POC_BCF,   pic16_popGet(AOP(result),0));
5887                 if( AOP_TYPE(right) == AOP_ACC) {
5888                   pic16_emitpcode(POC_IORLW, pic16_popGetLit(0));
5889                   emitSKPNZ;
5890                   pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
5891                   pic16_emitpcode(POC_BSF,   pic16_popGet(AOP(result),0));
5892                 }
5893
5894
5895
5896                 if(!((AOP_TYPE(result) == AOP_CRY) && ifx))
5897                     pic16_emitcode(";XXX setb","c");
5898                 pic16_emitcode(";XXX jb","%s,%05d_DS_",
5899                          AOP(left)->aopu.aop_dir,tlbl->key+100);
5900                 pic16_toBoolean(right);
5901                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5902                 if((AOP_TYPE(result) == AOP_CRY) && ifx){
5903                     jmpTrueOrFalse(ifx, tlbl);
5904                     goto release;
5905                 } else {
5906                     CLRC;
5907                     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5908                 }
5909             }
5910         }
5911         // bit = c
5912         // val = c
5913         if(size)
5914             pic16_outBitC(result);
5915         // if(bit | ...)
5916         else if((AOP_TYPE(result) == AOP_CRY) && ifx)
5917             genIfxJump(ifx, "c");           
5918         goto release ;
5919     }
5920
5921     // if(val | 0xZZ)       - size = 0, ifx != FALSE  -
5922     // bit = val | 0xZZ     - size = 1, ifx = FALSE -
5923     if((AOP_TYPE(right) == AOP_LIT) &&
5924        (AOP_TYPE(result) == AOP_CRY) &&
5925        (AOP_TYPE(left) != AOP_CRY)){
5926         if(lit){
5927           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5928             // result = 1
5929             if(size)
5930                 pic16_emitcode(";XXX setb","%s",AOP(result)->aopu.aop_dir);
5931             else 
5932                 continueIfTrue(ifx);
5933             goto release;
5934         } else {
5935           pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5936             // lit = 0, result = boolean(left)
5937             if(size)
5938                 pic16_emitcode(";XXX setb","c");
5939             pic16_toBoolean(right);
5940             if(size){
5941                 symbol *tlbl = newiTempLabel(NULL);
5942                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
5943                 CLRC;
5944                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
5945             } else {
5946                 genIfxJump (ifx,"a");
5947                 goto release;
5948             }
5949         }
5950         pic16_outBitC(result);
5951         goto release ;
5952     }
5953
5954     /* if left is same as result */
5955     if(pic16_sameRegs(AOP(result),AOP(left))){
5956       int know_W = -1;
5957       for(;size--; offset++,lit>>=8) {
5958         if(AOP_TYPE(right) == AOP_LIT){
5959           if((lit & 0xff) == 0)
5960             /*  or'ing with 0 has no effect */
5961             continue;
5962           else {
5963             int p = my_powof2(lit & 0xff);
5964             if(p>=0) {
5965               /* only one bit is set in the literal, so use a bsf instruction */
5966               pic16_emitpcode(POC_BSF,
5967                         pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offset,FALSE,FALSE),p,0));
5968             } else {
5969               if(know_W != (lit & 0xff))
5970                 pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0xff));
5971               know_W = lit & 0xff;
5972               pic16_emitpcode(POC_IORWF, pic16_popGet(AOP(left),offset));
5973             }
5974                     
5975           }
5976         } else {
5977           if (AOP_TYPE(left) == AOP_ACC) {
5978             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(right),offset));
5979             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5980           } else {                  
5981             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
5982             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(left),offset));
5983
5984             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
5985             pic16_emitcode("iorwf","%s,f",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
5986
5987           }
5988         }
5989       }
5990     } else {
5991         // left & result in different registers
5992         if(AOP_TYPE(result) == AOP_CRY){
5993             // result = bit
5994             // if(size), result in bit
5995             // if(!size && ifx), conditional oper: if(left | right)
5996             symbol *tlbl = newiTempLabel(NULL);
5997             int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
5998             pic16_emitcode(";XXX "," %s,%d",__FILE__,__LINE__);
5999
6000
6001             if(size)
6002                 pic16_emitcode(";XXX setb","c");
6003             while(sizer--){
6004                 MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6005                 pic16_emitcode(";XXX orl","a,%s",
6006                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6007                 pic16_emitcode(";XXX jnz","%05d_DS_",tlbl->key+100);
6008                 offset++;
6009             }
6010             if(size){
6011                 CLRC;
6012                 pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6013                 pic16_outBitC(result);
6014             } else if(ifx)
6015                 jmpTrueOrFalse(ifx, tlbl);
6016         } else for(;(size--);offset++){
6017           // normal case
6018           // result = left & right
6019           if(AOP_TYPE(right) == AOP_LIT){
6020             int t = (lit >> (offset*8)) & 0x0FFL;
6021             switch(t) { 
6022             case 0x00:
6023               pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
6024               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6025
6026               pic16_emitcode("movf","%s,w",
6027                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6028               pic16_emitcode("movwf","%s",
6029                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6030               break;
6031             default:
6032               pic16_emitpcode(POC_MOVLW,  pic16_popGetLit(t));
6033               pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6034               pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6035
6036               pic16_emitcode("movlw","0x%x",t);
6037               pic16_emitcode("iorwf","%s,w",
6038                        pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6039               pic16_emitcode("movwf","%s",
6040                        pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6041               
6042             }
6043             continue;
6044           }
6045
6046           // faster than result <- left, anl result,right
6047           // and better if result is SFR
6048           if (AOP_TYPE(left) == AOP_ACC) {
6049             pic16_emitpcode(POC_IORWF,  pic16_popGet(AOP(right),offset));
6050             pic16_emitcode("iorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6051           } else {
6052             pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(right),offset));
6053             pic16_emitpcode(POC_IORFW,  pic16_popGet(AOP(left),offset));
6054
6055             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6056             pic16_emitcode("iorwf","%s,w",
6057                      pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6058           }
6059           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
6060           pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6061         }
6062     }
6063
6064 release :
6065     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6066     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6067     pic16_freeAsmop(result,NULL,ic,TRUE);     
6068 }
6069
6070 /*-----------------------------------------------------------------*/
6071 /* genXor - code for xclusive or                                   */
6072 /*-----------------------------------------------------------------*/
6073 static void genXor (iCode *ic, iCode *ifx)
6074 {
6075   operand *left, *right, *result;
6076   int size, offset=0;
6077   unsigned long lit = 0L;
6078
6079   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6080
6081   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
6082   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
6083   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
6084
6085   /* if left is a literal & right is not ||
6086      if left needs acc & right does not */
6087   if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
6088       (AOP_NEEDSACC(left) && !AOP_NEEDSACC(right))) {
6089     operand *tmp = right ;
6090     right = left;
6091     left = tmp;
6092   }
6093
6094   /* if result = right then exchange them */
6095   if(pic16_sameRegs(AOP(result),AOP(right))){
6096     operand *tmp = right ;
6097     right = left;
6098     left = tmp;
6099   }
6100
6101   /* if right is bit then exchange them */
6102   if (AOP_TYPE(right) == AOP_CRY &&
6103       AOP_TYPE(left) != AOP_CRY){
6104     operand *tmp = right ;
6105     right = left;
6106     left = tmp;
6107   }
6108   if(AOP_TYPE(right) == AOP_LIT)
6109     lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
6110
6111   size = AOP_SIZE(result);
6112
6113   // if(bit ^ yy)
6114   // xx = bit ^ yy;
6115   if (AOP_TYPE(left) == AOP_CRY){
6116     if(AOP_TYPE(right) == AOP_LIT){
6117       // c = bit & literal;
6118       if(lit>>1){
6119         // lit>>1  != 0 => result = 1
6120         if(AOP_TYPE(result) == AOP_CRY){
6121           if(size)
6122             {pic16_emitpcode(POC_BSF,  pic16_popGet(AOP(result),offset));
6123             pic16_emitcode("setb","%s",AOP(result)->aopu.aop_dir);}
6124           else if(ifx)
6125             continueIfTrue(ifx);
6126           goto release;
6127         }
6128         pic16_emitcode("setb","c");
6129       } else{
6130         // lit == (0 or 1)
6131         if(lit == 0){
6132           // lit == 0, result = left
6133           if(size && pic16_sameRegs(AOP(result),AOP(left)))
6134             goto release;
6135           pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6136         } else{
6137           // lit == 1, result = not(left)
6138           if(size && pic16_sameRegs(AOP(result),AOP(left))){
6139             pic16_emitpcode(POC_MOVLW,  pic16_popGet(AOP(result),offset));
6140             pic16_emitpcode(POC_XORWF,  pic16_popGet(AOP(result),offset));
6141             pic16_emitcode("cpl","%s",AOP(result)->aopu.aop_dir);
6142             goto release;
6143           } else {
6144             pic16_emitcode("mov","c,%s",AOP(left)->aopu.aop_dir);
6145             pic16_emitcode("cpl","c");
6146           }
6147         }
6148       }
6149
6150     } else {
6151       // right != literal
6152       symbol *tlbl = newiTempLabel(NULL);
6153       if (AOP_TYPE(right) == AOP_CRY){
6154         // c = bit ^ bit;
6155         pic16_emitcode("mov","c,%s",AOP(right)->aopu.aop_dir);
6156       }
6157       else{
6158         int sizer = AOP_SIZE(right);
6159         // c = bit ^ val
6160         // if val>>1 != 0, result = 1
6161         pic16_emitcode("setb","c");
6162         while(sizer){
6163           MOVA(pic16_aopGet(AOP(right),sizer-1,FALSE,FALSE));
6164           if(sizer == 1)
6165             // test the msb of the lsb
6166             pic16_emitcode("anl","a,#0xfe");
6167           pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6168           sizer--;
6169         }
6170         // val = (0,1)
6171         pic16_emitcode("rrc","a");
6172       }
6173       pic16_emitcode("jnb","%s,%05d_DS_",AOP(left)->aopu.aop_dir,(tlbl->key+100));
6174       pic16_emitcode("cpl","c");
6175       pic16_emitcode("","%05d_DS_:",(tlbl->key+100));
6176     }
6177     // bit = c
6178     // val = c
6179     if(size)
6180       pic16_outBitC(result);
6181     // if(bit | ...)
6182     else if((AOP_TYPE(result) == AOP_CRY) && ifx)
6183       genIfxJump(ifx, "c");           
6184     goto release ;
6185   }
6186
6187   if(pic16_sameRegs(AOP(result),AOP(left))){
6188     /* if left is same as result */
6189     for(;size--; offset++) {
6190       if(AOP_TYPE(right) == AOP_LIT){
6191         int t  = (lit >> (offset*8)) & 0x0FFL;
6192         if(t == 0x00L)
6193           continue;
6194         else
6195           if (IS_AOP_PREG(left)) {
6196             MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6197             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6198             pic16_aopPut(AOP(result),"a",offset);
6199           } else {
6200             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6201             pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6202             pic16_emitcode("xrl","%s,%s",
6203                            pic16_aopGet(AOP(left),offset,FALSE,TRUE),
6204                            pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6205           }
6206       } else {
6207         if (AOP_TYPE(left) == AOP_ACC)
6208           pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6209         else {
6210           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6211           pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(left),offset));
6212 /*
6213           if (IS_AOP_PREG(left)) {
6214             pic16_emitcode("xrl","a,%s",pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6215             pic16_aopPut(AOP(result),"a",offset);
6216           } else
6217             pic16_emitcode("xrl","%s,a",
6218                            pic16_aopGet(AOP(left),offset,FALSE,TRUE));
6219 */
6220         }
6221       }
6222     }
6223   } else {
6224     // left & result in different registers
6225     if(AOP_TYPE(result) == AOP_CRY){
6226       // result = bit
6227       // if(size), result in bit
6228       // if(!size && ifx), conditional oper: if(left ^ right)
6229       symbol *tlbl = newiTempLabel(NULL);
6230       int sizer = max(AOP_SIZE(left),AOP_SIZE(right));
6231       if(size)
6232         pic16_emitcode("setb","c");
6233       while(sizer--){
6234         if((AOP_TYPE(right) == AOP_LIT) &&
6235            (((lit >> (offset*8)) & 0x0FFL) == 0x00L)){
6236           MOVA(pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6237         } else {
6238           MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6239           pic16_emitcode("xrl","a,%s",
6240                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6241         }
6242         pic16_emitcode("jnz","%05d_DS_",tlbl->key+100);
6243         offset++;
6244       }
6245       if(size){
6246         CLRC;
6247         pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6248         pic16_outBitC(result);
6249       } else if(ifx)
6250         jmpTrueOrFalse(ifx, tlbl);
6251     } else for(;(size--);offset++){
6252       // normal case
6253       // result = left & right
6254       if(AOP_TYPE(right) == AOP_LIT){
6255         int t = (lit >> (offset*8)) & 0x0FFL;
6256         switch(t) { 
6257         case 0x00:
6258           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offset));
6259           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6260           pic16_emitcode("movf","%s,w",
6261                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6262           pic16_emitcode("movwf","%s",
6263                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6264           break;
6265         case 0xff:
6266           pic16_emitpcode(POC_COMFW,pic16_popGet(AOP(left),offset));
6267           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6268           pic16_emitcode("comf","%s,w",
6269                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6270           pic16_emitcode("movwf","%s",
6271                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6272           break;
6273         default:
6274           pic16_emitpcode(POC_MOVLW, pic16_popGetLit(t));
6275           pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6276           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6277           pic16_emitcode("movlw","0x%x",t);
6278           pic16_emitcode("xorwf","%s,w",
6279                          pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6280           pic16_emitcode("movwf","%s",
6281                          pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6282
6283         }
6284         continue;
6285       }
6286
6287       // faster than result <- left, anl result,right
6288       // and better if result is SFR
6289       if (AOP_TYPE(left) == AOP_ACC) {
6290         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(right),offset));
6291         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6292       } else {
6293         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset));
6294         pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(left),offset));
6295         pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
6296         pic16_emitcode("xorwf","%s,w",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
6297       }
6298       if ( AOP_TYPE(result) != AOP_ACC){
6299         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset));
6300         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(result),offset,FALSE,FALSE));
6301       }
6302     }
6303   }
6304
6305   release :
6306     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6307   pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
6308   pic16_freeAsmop(result,NULL,ic,TRUE);     
6309 }
6310
6311 /*-----------------------------------------------------------------*/
6312 /* genInline - write the inline code out                           */
6313 /*-----------------------------------------------------------------*/
6314 static void genInline (iCode *ic)
6315 {
6316     char *buffer, *bp, *bp1;
6317     
6318     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6319
6320     _G.inLine += (!options.asmpeep);
6321
6322     buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
6323     strcpy(buffer,IC_INLINE(ic));
6324
6325     /* emit each line as a code */
6326     while (*bp) {
6327         if (*bp == '\n') {
6328             *bp++ = '\0';
6329
6330             if(*bp1)
6331               pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL));       //pic16_AssembleLine(bp1, 0));
6332                                         // inline directly, no process
6333             bp1 = bp;
6334         } else {
6335             if (*bp == ':') {
6336                 bp++;
6337                 *bp = '\0';
6338                 bp++;
6339                 pic16_emitcode(bp1,"");
6340                 bp1 = bp;
6341             } else
6342                 bp++;
6343         }
6344     }
6345     if ((bp1 != bp) && *bp1)
6346       pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir(bp1, NULL));               //pic16_AssembleLine(bp1, 0));
6347
6348     Safe_free(buffer);
6349
6350     _G.inLine -= (!options.asmpeep);
6351 }
6352
6353 /*-----------------------------------------------------------------*/
6354 /* genRRC - rotate right with carry                                */
6355 /*-----------------------------------------------------------------*/
6356 static void genRRC (iCode *ic)
6357 {
6358   operand *left , *result ;
6359   int size, offset = 0, same;
6360
6361   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6362
6363   /* rotate right with carry */
6364   left = IC_LEFT(ic);
6365   result=IC_RESULT(ic);
6366   pic16_aopOp (left,ic,FALSE);
6367   pic16_aopOp (result,ic,FALSE);
6368
6369   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6370
6371   same = pic16_sameRegs(AOP(result),AOP(left));
6372
6373   size = AOP_SIZE(result);    
6374
6375   DEBUGpic16_emitcode ("; ***","%s  %d size:%d same:%d",__FUNCTION__,__LINE__,size,same);
6376
6377   /* get the lsb and put it into the carry */
6378   pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),size-1));
6379
6380   offset = 0 ;
6381
6382   while(size--) {
6383
6384     if(same) {
6385       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),offset));
6386     } else {
6387       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offset));
6388       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6389     }
6390
6391     offset++;
6392   }
6393
6394   pic16_freeAsmop(left,NULL,ic,TRUE);
6395   pic16_freeAsmop(result,NULL,ic,TRUE);
6396 }
6397
6398 /*-----------------------------------------------------------------*/
6399 /* genRLC - generate code for rotate left with carry               */
6400 /*-----------------------------------------------------------------*/
6401 static void genRLC (iCode *ic)
6402 {    
6403   operand *left , *result ;
6404   int size, offset = 0;
6405   int same;
6406
6407   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6408   /* rotate right with carry */
6409   left = IC_LEFT(ic);
6410   result=IC_RESULT(ic);
6411   pic16_aopOp (left,ic,FALSE);
6412   pic16_aopOp (result,ic,FALSE);
6413
6414   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
6415
6416   same = pic16_sameRegs(AOP(result),AOP(left));
6417
6418   /* move it to the result */
6419   size = AOP_SIZE(result);    
6420
6421   /* get the msb and put it into the carry */
6422   pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),size-1));
6423
6424   offset = 0 ;
6425
6426   while(size--) {
6427
6428     if(same) {
6429       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),offset));
6430     } else {
6431       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offset));
6432       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
6433     }
6434
6435     offset++;
6436   }
6437
6438
6439   pic16_freeAsmop(left,NULL,ic,TRUE);
6440   pic16_freeAsmop(result,NULL,ic,TRUE);
6441 }
6442
6443 /*-----------------------------------------------------------------*/
6444 /* genGetHbit - generates code get highest order bit               */
6445 /*-----------------------------------------------------------------*/
6446 static void genGetHbit (iCode *ic)
6447 {
6448     operand *left, *result;
6449     left = IC_LEFT(ic);
6450     result=IC_RESULT(ic);
6451     pic16_aopOp (left,ic,FALSE);
6452     pic16_aopOp (result,ic,FALSE);
6453
6454     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6455     /* get the highest order byte into a */
6456     MOVA(pic16_aopGet(AOP(left),AOP_SIZE(left) - 1,FALSE,FALSE));
6457     if(AOP_TYPE(result) == AOP_CRY){
6458         pic16_emitcode("rlc","a");
6459         pic16_outBitC(result);
6460     }
6461     else{
6462         pic16_emitcode("rl","a");
6463         pic16_emitcode("anl","a,#0x01");
6464         pic16_outAcc(result);
6465     }
6466
6467
6468     pic16_freeAsmop(left,NULL,ic,TRUE);
6469     pic16_freeAsmop(result,NULL,ic,TRUE);
6470 }
6471
6472 /*-----------------------------------------------------------------*/
6473 /* AccRol - rotate left accumulator by known count                 */
6474 /*-----------------------------------------------------------------*/
6475 static void AccRol (int shCount)
6476 {
6477     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6478     shCount &= 0x0007;              // shCount : 0..7
6479     switch(shCount){
6480         case 0 :
6481             break;
6482         case 1 :
6483             pic16_emitcode("rl","a");
6484             break;
6485         case 2 :
6486             pic16_emitcode("rl","a");
6487             pic16_emitcode("rl","a");
6488             break;
6489         case 3 :
6490             pic16_emitcode("swap","a");
6491             pic16_emitcode("rr","a");
6492             break;
6493         case 4 :
6494             pic16_emitcode("swap","a");
6495             break;
6496         case 5 :
6497             pic16_emitcode("swap","a");
6498             pic16_emitcode("rl","a");
6499             break;
6500         case 6 :
6501             pic16_emitcode("rr","a");
6502             pic16_emitcode("rr","a");
6503             break;
6504         case 7 :
6505             pic16_emitcode("rr","a");
6506             break;
6507     }
6508 }
6509
6510 /*-----------------------------------------------------------------*/
6511 /* AccLsh - left shift accumulator by known count                  */
6512 /*-----------------------------------------------------------------*/
6513 static void AccLsh (int shCount)
6514 {
6515     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6516     switch(shCount){
6517         case 0 :
6518                         return;
6519             break;
6520         case 1 :
6521             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6522             break;
6523         case 2 :
6524             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6525             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6526             break;
6527         case 3 :
6528             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6529             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6530             break;
6531         case 4 :
6532             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6533             break;
6534         case 5 :
6535             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6536             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6537             break;
6538         case 6 :
6539             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6540             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6541             break;
6542         case 7 :
6543             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6544             break;
6545     }
6546     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SLMask[shCount]));
6547
6548 }
6549
6550 /*-----------------------------------------------------------------*/
6551 /* AccRsh - right shift accumulator by known count                 */
6552 /*-----------------------------------------------------------------*/
6553 static void AccRsh (int shCount)
6554 {
6555     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6556     switch(shCount){
6557         case 0 :
6558                         return;
6559             break;
6560         case 1 :
6561             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6562             break;
6563         case 2 :
6564             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6565             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6566             break;
6567         case 3 :
6568             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6569             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6570             break;
6571         case 4 :
6572             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6573             break;
6574         case 5 :
6575             pic16_emitpcode(POC_SWAPFW,pic16_popCopyReg(&pic16_pc_wreg));
6576             pic16_emitpcode(POC_RRNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6577             break;
6578         case 6 :
6579             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6580             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6581             break;
6582         case 7 :
6583             pic16_emitpcode(POC_RLNCFW,pic16_popCopyReg(&pic16_pc_wreg));
6584             break;
6585     }
6586     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(SRMask[shCount]));
6587 }
6588
6589 #if 0
6590 /*-----------------------------------------------------------------*/
6591 /* AccSRsh - signed right shift accumulator by known count                 */
6592 /*-----------------------------------------------------------------*/
6593 static void AccSRsh (int shCount)
6594 {
6595     symbol *tlbl ;
6596     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6597     if(shCount != 0){
6598         if(shCount == 1){
6599             pic16_emitcode("mov","c,acc.7");
6600             pic16_emitcode("rrc","a");
6601         } else if(shCount == 2){
6602             pic16_emitcode("mov","c,acc.7");
6603             pic16_emitcode("rrc","a");
6604             pic16_emitcode("mov","c,acc.7");
6605             pic16_emitcode("rrc","a");
6606         } else {
6607             tlbl = newiTempLabel(NULL);
6608             /* rotate right accumulator */
6609             AccRol(8 - shCount);
6610             /* and kill the higher order bits */
6611             pic16_emitcode("anl","a,#0x%02x", SRMask[shCount]);
6612             pic16_emitcode("jnb","acc.%d,%05d_DS_",7-shCount,tlbl->key+100);
6613             pic16_emitcode("orl","a,#0x%02x",
6614                      (unsigned char)~SRMask[shCount]);
6615             pic16_emitcode("","%05d_DS_:",tlbl->key+100);
6616         }
6617     }
6618 }
6619 #endif
6620 /*-----------------------------------------------------------------*/
6621 /* shiftR1Left2Result - shift right one byte from left to result   */
6622 /*-----------------------------------------------------------------*/
6623 static void shiftR1Left2ResultSigned (operand *left, int offl,
6624                                 operand *result, int offr,
6625                                 int shCount)
6626 {
6627   int same;
6628
6629   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6630
6631   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6632
6633   switch(shCount) {
6634   case 1:
6635     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6636     if(same) 
6637       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6638     else {
6639       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6640       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6641     }
6642
6643     break;
6644   case 2:
6645
6646     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6647     if(same) 
6648       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6649     else {
6650       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6651       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6652     }
6653     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
6654     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6655
6656     break;
6657
6658   case 3:
6659     if(same)
6660       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6661     else {
6662       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6663       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6664     }
6665
6666     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6667     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6668     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6669
6670     pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6671     pic16_emitpcode(POC_IORLW, pic16_popGetLit(0xe0));
6672
6673     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6674     break;
6675
6676   case 4:
6677     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6678     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x0f));
6679     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6680     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf0));
6681     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6682     break;
6683   case 5:
6684     if(same) {
6685       pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(result),offr));
6686     } else {
6687       pic16_emitpcode(POC_SWAPFW,  pic16_popGet(AOP(left),offl));
6688       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6689     }
6690     pic16_emitpcode(POC_RRCFW,   pic16_popGet(AOP(result),offr));
6691     pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0x07));
6692     pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),3,0));
6693     pic16_emitpcode(POC_IORLW,  pic16_popGetLit(0xf8));
6694     pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
6695     break;
6696
6697   case 6:
6698     if(same) {
6699       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6700       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6701       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xfe));
6702       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6703       pic16_emitpcode(POC_IORLW, pic16_popGetLit(0x01));
6704       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6705     } else {
6706       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6707       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6708       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6709       pic16_emitpcode(POC_BTFSS, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),6,0));
6710       pic16_emitpcode(POC_BCF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr,FALSE,FALSE),0,0));
6711     }
6712     break;
6713
6714   case 7:
6715     if(same) {
6716       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x00));
6717       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
6718       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
6719       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6720     } else {
6721       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),offr));
6722       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),offl,FALSE,FALSE),7,0));
6723       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(result),offr));
6724     }
6725
6726   default:
6727     break;
6728   }
6729 }
6730
6731 /*-----------------------------------------------------------------*/
6732 /* shiftR1Left2Result - shift right one byte from left to result   */
6733 /*-----------------------------------------------------------------*/
6734 static void shiftR1Left2Result (operand *left, int offl,
6735                                 operand *result, int offr,
6736                                 int shCount, int sign)
6737 {
6738   int same;
6739
6740   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6741
6742   same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
6743
6744   /* Copy the msb into the carry if signed. */
6745   if(sign) {
6746     shiftR1Left2ResultSigned(left,offl,result,offr,shCount);
6747     return;
6748   }
6749
6750
6751
6752   switch(shCount) {
6753   case 1:
6754     emitCLRC;
6755     if(same) 
6756       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6757     else {
6758       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6759       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6760     }
6761     break;
6762   case 2:
6763     emitCLRC;
6764     if(same) {
6765       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6766     } else {
6767       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6768       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6769     }
6770     emitCLRC;
6771     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6772
6773     break;
6774   case 3:
6775     if(same)
6776       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6777     else {
6778       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6779       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6780     }
6781
6782     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6783     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offr));
6784     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x1f));
6785     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6786     break;
6787       
6788   case 4:
6789     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6790     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6791     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6792     break;
6793
6794   case 5:
6795     pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),offl));
6796     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
6797     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6798     emitCLRC;
6799     pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
6800
6801     break;
6802   case 6:
6803
6804     pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl));
6805     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x80));
6806     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6807     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6808     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offr));
6809     break;
6810
6811   case 7:
6812
6813     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6814     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6815     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6816
6817     break;
6818
6819   default:
6820     break;
6821   }
6822 }
6823
6824 /*-----------------------------------------------------------------*/
6825 /* shiftL1Left2Result - shift left one byte from left to result    */
6826 /*-----------------------------------------------------------------*/
6827 static void shiftL1Left2Result (operand *left, int offl,
6828                                 operand *result, int offr, int shCount)
6829 {
6830   int same;
6831
6832   //    char *l;
6833   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6834
6835   same = ((left == result) || (AOP(left) == AOP(result))) && (offl==offr);
6836   DEBUGpic16_emitcode ("; ***","same =  %d",same);
6837     //    l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6838     //    MOVA(l);
6839     /* shift left accumulator */
6840     //AccLsh(shCount); // don't comment out just yet...
6841   //    pic16_aopPut(AOP(result),"a",offr);
6842
6843   switch(shCount) {
6844   case 1:
6845     /* Shift left 1 bit position */
6846     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6847     if(same) {
6848       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),offl));
6849     } else {
6850       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),offl));
6851       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6852     }
6853     break;
6854   case 2:
6855     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6856     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x7e));
6857     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6858     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6859     break;
6860   case 3:
6861     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
6862     pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x3e));
6863     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6864     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6865     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6866     break;
6867   case 4:
6868     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6869     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6870     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6871     break;
6872   case 5:
6873     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6874     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
6875     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6876     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6877     break;
6878   case 6:
6879     pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
6880     pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x30));
6881     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
6882     pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6883     pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
6884     break;
6885   case 7:
6886     pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
6887     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6888     pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6889     break;
6890
6891   default:
6892     DEBUGpic16_emitcode ("; ***","%s  %d, shift count is %d",__FUNCTION__,__LINE__,shCount);
6893   }
6894
6895 }
6896
6897 /*-----------------------------------------------------------------*/
6898 /* movLeft2Result - move byte from left to result                  */
6899 /*-----------------------------------------------------------------*/
6900 static void movLeft2Result (operand *left, int offl,
6901                             operand *result, int offr)
6902 {
6903   char *l;
6904   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
6905   if(!pic16_sameRegs(AOP(left),AOP(result)) || (offl != offr)){
6906     l = pic16_aopGet(AOP(left),offl,FALSE,FALSE);
6907
6908     if (*l == '@' && (IS_AOP_PREG(result))) {
6909       pic16_emitcode("mov","a,%s",l);
6910       pic16_aopPut(AOP(result),"a",offr);
6911     } else {
6912       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
6913       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
6914     }
6915   }
6916 }
6917
6918 /*-----------------------------------------------------------------*/
6919 /* shiftL2Left2Result - shift left two bytes from left to result   */
6920 /*-----------------------------------------------------------------*/
6921 static void shiftL2Left2Result (operand *left, int offl,
6922                                 operand *result, int offr, int shCount)
6923 {
6924   int same = pic16_sameRegs(AOP(result), AOP(left));
6925   int i;
6926
6927   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d offl:%d offr:%d",__FUNCTION__,__LINE__,shCount,same,offl,offr);
6928
6929   if (same && (offl != offr)) { // shift bytes
6930     if (offr > offl) {
6931        for(i=1;i>-1;i--) {
6932          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
6933          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
6934        }
6935     } else { // just treat as different later on
6936                 same = 0;
6937     }
6938   }
6939
6940   if(same) {
6941     switch(shCount) {
6942     case 0:
6943       break;
6944     case 1:
6945     case 2:
6946     case 3:
6947
6948       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offr));
6949       pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(result),offr));
6950       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
6951
6952       while(--shCount) {
6953                 emitCLRC;
6954                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6955                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6956       }
6957
6958       break;
6959     case 4:
6960     case 5:
6961       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0x0f));
6962       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr+MSB16));
6963       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
6964       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
6965       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr));
6966       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
6967       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
6968       if(shCount >=5) {
6969                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
6970                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
6971       }
6972       break;
6973     case 6:
6974       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6975       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6976       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
6977       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6978       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6979       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
6980       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6981       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
6982       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
6983       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6984       break;
6985     case 7:
6986       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
6987       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr));
6988       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
6989       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
6990       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
6991     }
6992
6993   } else {
6994     switch(shCount) {
6995     case 0:
6996       break;
6997     case 1:
6998     case 2:
6999     case 3:
7000       /* note, use a mov/add for the shift since the mov has a
7001          chance of getting optimized out */
7002       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),offl));
7003       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7004       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7005       pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),offl+MSB16));
7006       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7007
7008       while(--shCount) {
7009                 emitCLRC;
7010                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7011                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7012       }
7013       break;
7014
7015     case 4:
7016     case 5:
7017       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7018       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7019       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7020       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7021       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7022       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xF0));
7023       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr));
7024       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7025
7026
7027       if(shCount == 5) {
7028                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr));
7029                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),offr+MSB16));
7030       }
7031       break;
7032     case 6:
7033       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7034       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7035       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offl));
7036       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offr));
7037
7038       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr+MSB16));
7039       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7040       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(result),offr+MSB16));
7041       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0xc0));
7042       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7043       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr));
7044       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr));
7045       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7046       break;
7047     case 7:
7048       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7049       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7050       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7051       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr));
7052       pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),offr));
7053     }
7054   }
7055
7056 }
7057 /*-----------------------------------------------------------------*/
7058 /* shiftR2Left2Result - shift right two bytes from left to result  */
7059 /*-----------------------------------------------------------------*/
7060 static void shiftR2Left2Result (operand *left, int offl,
7061                                 operand *result, int offr,
7062                                 int shCount, int sign)
7063 {
7064   int same = pic16_sameRegs(AOP(result), AOP(left));
7065   int i;
7066   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d same:%d sign:%d",__FUNCTION__,__LINE__,shCount,same,sign);
7067
7068   if (same && (offl != offr)) { // shift right bytes
7069     if (offr < offl) {
7070        for(i=0;i<2;i++) {
7071          pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offl+i));
7072          pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+i));
7073        }
7074     } else { // just treat as different later on
7075                 same = 0;
7076     }
7077   }
7078
7079   switch(shCount) {
7080   case 0:
7081     break;
7082   case 1:
7083   case 2:
7084   case 3:
7085     if(sign)
7086       pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7087     else
7088       emitCLRC;
7089
7090     if(same) {
7091       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7092       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7093     } else {
7094       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl+MSB16));
7095       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7096       pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),offl));
7097       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7098     }
7099
7100     while(--shCount) {
7101       if(sign)
7102                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(result),offr+MSB16));
7103       else
7104                 emitCLRC;
7105       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr+MSB16));
7106       pic16_emitpcode(POC_RRCF,pic16_popGet(AOP(result),offr));
7107     }
7108     break;
7109   case 4:
7110   case 5:
7111     if(same) {
7112
7113       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0));
7114       pic16_emitpcode(POC_ANDWF, pic16_popGet(AOP(result),offr));
7115       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr));
7116
7117       pic16_emitpcode(POC_SWAPF, pic16_popGet(AOP(result),offr+MSB16));
7118       pic16_emitpcode(POC_ANDFW, pic16_popGet(AOP(result),offr+MSB16));
7119       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7120       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7121     } else {
7122       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl));
7123       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x0f));
7124       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr));
7125
7126       pic16_emitpcode(POC_SWAPFW,pic16_popGet(AOP(left),offl+MSB16));
7127       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offr+MSB16));
7128       pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0xf0));
7129       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),offr+MSB16));
7130       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr));
7131     }
7132
7133     if(shCount >=5) {
7134       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr+MSB16));
7135       pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(result),offr));
7136     }
7137
7138     if(sign) {
7139       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xf0 + (shCount-4)*8 ));
7140       pic16_emitpcode(POC_BTFSC, 
7141                 pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),7-shCount,0));
7142       pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),offr+MSB16));
7143     }
7144
7145     break;
7146
7147   case 6:
7148     if(same) {
7149
7150       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7151       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7152
7153       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7154       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7155       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr));
7156       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7157       if(sign) {
7158         pic16_emitpcode(POC_BTFSC, 
7159                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),1,0));
7160         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7161       }
7162       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7163       pic16_emitpcode(POC_XORWF,pic16_popGet(AOP(result),offr+MSB16));
7164       pic16_emitpcode(POC_XORFW,pic16_popGet(AOP(result),offr+MSB16));
7165       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7166     } else {
7167       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7168       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7169       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7170       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7171       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7172       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7173       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(result),offr+MSB16));
7174       pic16_emitpcode(POC_ANDLW,pic16_popGetLit(0x03));
7175       if(sign) {
7176         pic16_emitpcode(POC_BTFSC, 
7177                   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offr+MSB16,FALSE,FALSE),0,0));
7178         pic16_emitpcode(POC_IORLW,pic16_popGetLit(0xfc));
7179       }
7180       pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr+MSB16));
7181       //pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr));
7182
7183         
7184     }
7185
7186     break;
7187   case 7:
7188     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl));
7189     pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),offl+MSB16));
7190     pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offr));
7191     pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offr+MSB16));
7192     if(sign) {
7193       emitSKPNC;
7194       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),offr+MSB16));
7195     } else 
7196       pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),offr+MSB16));
7197   }
7198 }
7199
7200
7201 /*-----------------------------------------------------------------*/
7202 /* shiftLLeftOrResult - shift left one byte from left, or to result*/
7203 /*-----------------------------------------------------------------*/
7204 static void shiftLLeftOrResult (operand *left, int offl,
7205                                 operand *result, int offr, int shCount)
7206 {
7207     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7208
7209     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7210     /* shift left accumulator */
7211     AccLsh(shCount);
7212     /* or with result */
7213     /* back to result */
7214     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7215 }
7216
7217 /*-----------------------------------------------------------------*/
7218 /* shiftRLeftOrResult - shift right one byte from left,or to result*/
7219 /*-----------------------------------------------------------------*/
7220 static void shiftRLeftOrResult (operand *left, int offl,
7221                                 operand *result, int offr, int shCount)
7222 {
7223     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7224     
7225     pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),offl));
7226     /* shift right accumulator */
7227     AccRsh(shCount);
7228     /* or with result */
7229     /* back to result */
7230     pic16_emitpcode(POC_IORWF,pic16_popGet(AOP(result),offr));
7231 }
7232
7233 /*-----------------------------------------------------------------*/
7234 /* genlshOne - left shift a one byte quantity by known count       */
7235 /*-----------------------------------------------------------------*/
7236 static void genlshOne (operand *result, operand *left, int shCount)
7237 {       
7238     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7239     shiftL1Left2Result(left, LSB, result, LSB, shCount);
7240 }
7241
7242 /*-----------------------------------------------------------------*/
7243 /* genlshTwo - left shift two bytes by known amount != 0           */
7244 /*-----------------------------------------------------------------*/
7245 static void genlshTwo (operand *result,operand *left, int shCount)
7246 {
7247     int size;
7248     
7249     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7250     size = pic16_getDataSize(result);
7251
7252     /* if shCount >= 8 */
7253     if (shCount >= 8) {
7254         shCount -= 8 ;
7255
7256         if (size > 1){
7257             if (shCount)
7258                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7259             else 
7260                 movLeft2Result(left, LSB, result, MSB16);
7261         }
7262         pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7263     }
7264
7265     /*  1 <= shCount <= 7 */
7266     else {  
7267         if(size == 1)
7268             shiftL1Left2Result(left, LSB, result, LSB, shCount); 
7269         else 
7270             shiftL2Left2Result(left, LSB, result, LSB, shCount);
7271     }
7272 }
7273
7274 /*-----------------------------------------------------------------*/
7275 /* shiftLLong - shift left one long from left to result            */
7276 /* offr = LSB or MSB16                                             */
7277 /*-----------------------------------------------------------------*/
7278 static void shiftLLong (operand *left, operand *result, int offr )
7279 {
7280     int size = AOP_SIZE(result);
7281     int same = pic16_sameRegs(AOP(left),AOP(result));
7282         int i;
7283
7284     DEBUGpic16_emitcode ("; ***","%s  %d  offr:%d size:%d",__FUNCTION__,__LINE__,offr,size);
7285
7286         if (same && (offr == MSB16)) { //shift one byte
7287                 for(i=size-1;i>=MSB16;i--) {
7288                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i-1));
7289                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i));
7290                 }
7291         } else {
7292                 pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),LSB+offr));
7293         }
7294         
7295     if (size >= LSB+offr ){
7296                 if (same) {
7297                         pic16_emitpcode(POC_ADDWF,pic16_popGet(AOP(left),LSB+offr));
7298                 } else {
7299                         pic16_emitpcode(POC_ADDFW,pic16_popGet(AOP(left),LSB));
7300                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),LSB+offr));
7301                 }
7302          }
7303
7304     if(size >= MSB16+offr){
7305                 if (same) {
7306                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB16+offr));
7307                 } else {
7308                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB16));
7309                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB16+offr));
7310                 }
7311     }
7312
7313     if(size >= MSB24+offr){
7314                 if (same) {
7315                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB24+offr));
7316                 } else {
7317                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB24));
7318                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB24+offr));
7319                 }
7320     }
7321
7322     if(size > MSB32+offr){
7323                 if (same) {
7324                         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),MSB32+offr));
7325                 } else {
7326                         pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left),MSB32));
7327                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),MSB32+offr));
7328                 }
7329     }
7330     if(offr != LSB)
7331                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7332
7333 }
7334
7335 /*-----------------------------------------------------------------*/
7336 /* genlshFour - shift four byte by a known amount != 0             */
7337 /*-----------------------------------------------------------------*/
7338 static void genlshFour (operand *result, operand *left, int shCount)
7339 {
7340     int size;
7341
7342     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7343     size = AOP_SIZE(result);
7344
7345     /* if shifting more that 3 bytes */
7346     if (shCount >= 24 ) {
7347         shCount -= 24;
7348         if (shCount)
7349             /* lowest order of left goes to the highest
7350             order of the destination */
7351             shiftL1Left2Result(left, LSB, result, MSB32, shCount);
7352         else
7353             movLeft2Result(left, LSB, result, MSB32);
7354
7355                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7356                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7357                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB24));
7358
7359         return;
7360     }
7361
7362     /* more than two bytes */
7363     else if ( shCount >= 16 ) {
7364         /* lower order two bytes goes to higher order two bytes */
7365         shCount -= 16;
7366         /* if some more remaining */
7367         if (shCount)
7368             shiftL2Left2Result(left, LSB, result, MSB24, shCount);
7369         else {
7370             movLeft2Result(left, MSB16, result, MSB32);
7371             movLeft2Result(left, LSB, result, MSB24);
7372         }
7373                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7374                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7375         return;
7376     }    
7377
7378     /* if more than 1 byte */
7379     else if ( shCount >= 8 ) {
7380         /* lower order three bytes goes to higher order  three bytes */
7381         shCount -= 8;
7382         if(size == 2){
7383             if(shCount)
7384                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7385             else
7386                 movLeft2Result(left, LSB, result, MSB16);
7387         }
7388         else{   /* size = 4 */
7389             if(shCount == 0){
7390                 movLeft2Result(left, MSB24, result, MSB32);
7391                 movLeft2Result(left, MSB16, result, MSB24);
7392                 movLeft2Result(left, LSB, result, MSB16);
7393                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7394             }
7395             else if(shCount == 1)
7396                 shiftLLong(left, result, MSB16);
7397             else{
7398                 shiftL2Left2Result(left, MSB16, result, MSB24, shCount);
7399                 shiftL1Left2Result(left, LSB, result, MSB16, shCount);
7400                 shiftRLeftOrResult(left, LSB, result, MSB24, 8 - shCount);
7401                                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),LSB));
7402             }
7403         }
7404     }
7405
7406     /* 1 <= shCount <= 7 */
7407     else if(shCount <= 3)
7408     { 
7409         shiftLLong(left, result, LSB);
7410         while(--shCount >= 1)
7411             shiftLLong(result, result, LSB);
7412     }
7413     /* 3 <= shCount <= 7, optimize */
7414     else{
7415         shiftL2Left2Result(left, MSB24, result, MSB24, shCount);
7416         shiftRLeftOrResult(left, MSB16, result, MSB24, 8 - shCount);
7417         shiftL2Left2Result(left, LSB, result, LSB, shCount);
7418     }
7419 }
7420
7421 /*-----------------------------------------------------------------*/
7422 /* genLeftShiftLiteral - left shifting by known count              */
7423 /*-----------------------------------------------------------------*/
7424 static void genLeftShiftLiteral (operand *left,
7425                                  operand *right,
7426                                  operand *result,
7427                                  iCode *ic)
7428 {    
7429     int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7430     int size;
7431
7432     DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7433     pic16_freeAsmop(right,NULL,ic,TRUE);
7434
7435     pic16_aopOp(left,ic,FALSE);
7436     pic16_aopOp(result,ic,FALSE);
7437
7438     size = getSize(operandType(result));
7439
7440 #if VIEW_SIZE
7441     pic16_emitcode("; shift left ","result %d, left %d",size,
7442              AOP_SIZE(left));
7443 #endif
7444
7445     /* I suppose that the left size >= result size */
7446     if(shCount == 0){
7447         while(size--){
7448             movLeft2Result(left, size, result, size);
7449         }
7450     }
7451
7452     else if(shCount >= (size * 8))
7453         while(size--)
7454             pic16_aopPut(AOP(result),zero,size);
7455     else{
7456         switch (size) {
7457             case 1:
7458                 genlshOne (result,left,shCount);
7459                 break;
7460
7461             case 2:
7462             case 3:
7463                 genlshTwo (result,left,shCount);
7464                 break;
7465
7466             case 4:
7467                 genlshFour (result,left,shCount);
7468                 break;
7469         }
7470     }
7471     pic16_freeAsmop(left,NULL,ic,TRUE);
7472     pic16_freeAsmop(result,NULL,ic,TRUE);
7473 }
7474
7475 /*-----------------------------------------------------------------*
7476  * genMultiAsm - repeat assembly instruction for size of register.
7477  * if endian == 1, then the high byte (i.e base address + size of 
7478  * register) is used first else the low byte is used first;
7479  *-----------------------------------------------------------------*/
7480 static void genMultiAsm( PIC_OPCODE poc, operand *reg, int size, int endian)
7481 {
7482
7483   int offset = 0;
7484
7485   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7486
7487   if(!reg)
7488     return;
7489
7490   if(!endian) {
7491     endian = 1;
7492   } else {
7493     endian = -1;
7494     offset = size-1;
7495   }
7496
7497   while(size--) {
7498     pic16_emitpcode(poc,    pic16_popGet(AOP(reg),offset));
7499     offset += endian;
7500   }
7501
7502 }
7503 /*-----------------------------------------------------------------*/
7504 /* genLeftShift - generates code for left shifting                 */
7505 /*-----------------------------------------------------------------*/
7506 static void genLeftShift (iCode *ic)
7507 {
7508   operand *left,*right, *result;
7509   int size, offset;
7510   char *l;
7511   symbol *tlbl , *tlbl1;
7512   pCodeOp *pctemp;
7513
7514   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7515
7516   right = IC_RIGHT(ic);
7517   left  = IC_LEFT(ic);
7518   result = IC_RESULT(ic);
7519
7520   pic16_aopOp(right,ic,FALSE);
7521
7522   /* if the shift count is known then do it 
7523      as efficiently as possible */
7524   if (AOP_TYPE(right) == AOP_LIT) {
7525     genLeftShiftLiteral (left,right,result,ic);
7526     return ;
7527   }
7528
7529   /* shift count is unknown then we have to form 
7530      a loop get the loop count in B : Note: we take
7531      only the lower order byte since shifting
7532      more that 32 bits make no sense anyway, ( the
7533      largest size of an object can be only 32 bits ) */  
7534
7535     
7536   pic16_aopOp(left,ic,FALSE);
7537   pic16_aopOp(result,ic,FALSE);
7538
7539   /* now move the left to the result if they are not the
7540      same */
7541   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7542       AOP_SIZE(result) > 1) {
7543
7544     size = AOP_SIZE(result);
7545     offset=0;
7546     while (size--) {
7547       l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7548       if (*l == '@' && (IS_AOP_PREG(result))) {
7549
7550         pic16_emitcode("mov","a,%s",l);
7551         pic16_aopPut(AOP(result),"a",offset);
7552       } else {
7553         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7554         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7555         //pic16_aopPut(AOP(result),l,offset);
7556       }
7557       offset++;
7558     }
7559   }
7560
7561   size = AOP_SIZE(result);
7562
7563   /* if it is only one byte then */
7564   if (size == 1) {
7565     if(optimized_for_speed) {
7566       pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
7567       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
7568       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),2,0));
7569       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7570       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7571       pic16_emitpcode(POC_BTFSS,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
7572       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7573       pic16_emitpcode(POC_RLCFW,   pic16_popGet(AOP(result),0));
7574       pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xfe));
7575       pic16_emitpcode(POC_ADDFW,  pic16_popGet(AOP(result),0));
7576       pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),1,0));
7577       pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(result),0));
7578     } else {
7579
7580       tlbl = newiTempLabel(NULL);
7581       if (!pic16_sameRegs(AOP(left),AOP(result))) {
7582                 pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
7583                 pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
7584       }
7585
7586       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7587       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
7588       pic16_emitpLabel(tlbl->key);
7589       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
7590       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7591       emitSKPC;
7592       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7593     }
7594     goto release ;
7595   }
7596     
7597   if (pic16_sameRegs(AOP(left),AOP(result))) {
7598
7599     tlbl = newiTempLabel(NULL);
7600     pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
7601     genMultiAsm(POC_RRCF, result, size,1);
7602     pic16_emitpLabel(tlbl->key);
7603     genMultiAsm(POC_RLCF, result, size,0);
7604     pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
7605     emitSKPC;
7606     pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7607     goto release;
7608   }
7609
7610   //tlbl = newiTempLabel(NULL);
7611   //offset = 0 ;   
7612   //tlbl1 = newiTempLabel(NULL);
7613
7614   //reAdjustPreg(AOP(result));    
7615     
7616   //pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100); 
7617   //pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
7618   //l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7619   //MOVA(l);
7620   //pic16_emitcode("add","a,acc");         
7621   //pic16_aopPut(AOP(result),"a",offset++);
7622   //while (--size) {
7623   //  l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
7624   //  MOVA(l);
7625   //  pic16_emitcode("rlc","a");         
7626   //  pic16_aopPut(AOP(result),"a",offset++);
7627   //}
7628   //reAdjustPreg(AOP(result));
7629
7630   //pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
7631   //pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
7632
7633
7634   tlbl = newiTempLabel(NULL);
7635   tlbl1= newiTempLabel(NULL);
7636
7637   size = AOP_SIZE(result);
7638   offset = 1;
7639
7640   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7641
7642   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7643
7644   /* offset should be 0, 1 or 3 */
7645   
7646   pic16_emitpcode(POC_ANDLW, pic16_popGetLit((size<<3)-1));
7647   emitSKPNZ;
7648   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7649
7650   pic16_emitpcode(POC_MOVWF, pctemp);
7651
7652
7653   pic16_emitpLabel(tlbl->key);
7654
7655   emitCLRC;
7656   pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(result),0));
7657   while(--size)
7658     pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(result),offset++));
7659
7660   pic16_emitpcode(POC_DECFSZ,  pctemp);
7661   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
7662   pic16_emitpLabel(tlbl1->key);
7663
7664   pic16_popReleaseTempReg(pctemp);
7665
7666
7667  release:
7668   pic16_freeAsmop (right,NULL,ic,TRUE);
7669   pic16_freeAsmop(left,NULL,ic,TRUE);
7670   pic16_freeAsmop(result,NULL,ic,TRUE);
7671 }
7672
7673 /*-----------------------------------------------------------------*/
7674 /* genrshOne - right shift a one byte quantity by known count      */
7675 /*-----------------------------------------------------------------*/
7676 static void genrshOne (operand *result, operand *left,
7677                        int shCount, int sign)
7678 {
7679     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7680     shiftR1Left2Result(left, LSB, result, LSB, shCount, sign);
7681 }
7682
7683 /*-----------------------------------------------------------------*/
7684 /* genrshTwo - right shift two bytes by known amount != 0          */
7685 /*-----------------------------------------------------------------*/
7686 static void genrshTwo (operand *result,operand *left,
7687                        int shCount, int sign)
7688 {
7689   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d",__FUNCTION__,__LINE__,shCount);
7690   /* if shCount >= 8 */
7691   if (shCount >= 8) {
7692     shCount -= 8 ;
7693     if (shCount)
7694       shiftR1Left2Result(left, MSB16, result, LSB,
7695                          shCount, sign);
7696     else
7697       movLeft2Result(left, MSB16, result, LSB);
7698
7699     pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),MSB16));
7700
7701     if(sign) {
7702       pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),LSB,FALSE,FALSE),7,0));
7703       pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),MSB16));
7704     }
7705   }
7706
7707   /*  1 <= shCount <= 7 */
7708   else
7709     shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
7710 }
7711
7712 /*-----------------------------------------------------------------*/
7713 /* shiftRLong - shift right one long from left to result           */
7714 /* offl = LSB or MSB16                                             */
7715 /*-----------------------------------------------------------------*/
7716 static void shiftRLong (operand *left, int offl,
7717                         operand *result, int sign)
7718 {
7719     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7720     int size = AOP_SIZE(result);
7721     int same = pic16_sameRegs(AOP(left),AOP(result));
7722         int i;
7723
7724     DEBUGpic16_emitcode ("; ***","%s  %d  offl:%d size:%d",__FUNCTION__,__LINE__,offl,size);
7725
7726         if (same && (offl == MSB16)) { //shift one byte right
7727                 for(i=MSB16;i<size;i++) {
7728                         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),i));
7729                         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(left),i-1));
7730                 }
7731         }
7732
7733     if(sign)
7734                 pic16_emitpcode(POC_RLCFW,pic16_popGet(AOP(left),MSB32));
7735         else
7736                 emitCLRC;
7737
7738         if (same) {
7739                 if (offl == LSB)
7740                 pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB32));
7741         } else {
7742         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB32));
7743         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB32-offl));
7744         }
7745
7746     if(offl == MSB16) {
7747         /* add sign of "a" */
7748         pic16_addSign(result, MSB32, sign);
7749         }
7750
7751         if (same) {
7752         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB24));
7753         } else {
7754         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB24));
7755         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB24-offl));
7756         }
7757         
7758         if (same) {
7759         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),MSB16));
7760         } else {
7761         pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),MSB16));
7762         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),MSB16-offl));
7763         }
7764
7765         if (same) {
7766         pic16_emitpcode(POC_RRCF, pic16_popGet(AOP(left),LSB));
7767         } else {
7768         if(offl == LSB){
7769                 pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),LSB));
7770                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),LSB));
7771         }
7772         }
7773 }
7774
7775 /*-----------------------------------------------------------------*/
7776 /* genrshFour - shift four byte by a known amount != 0             */
7777 /*-----------------------------------------------------------------*/
7778 static void genrshFour (operand *result, operand *left,
7779                         int shCount, int sign)
7780 {
7781   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7782   /* if shifting more that 3 bytes */
7783   if(shCount >= 24 ) {
7784     shCount -= 24;
7785     if(shCount)
7786       shiftR1Left2Result(left, MSB32, result, LSB, shCount, sign);
7787     else
7788       movLeft2Result(left, MSB32, result, LSB);
7789
7790     pic16_addSign(result, MSB16, sign);
7791   }
7792   else if(shCount >= 16){
7793     shCount -= 16;
7794     if(shCount)
7795       shiftR2Left2Result(left, MSB24, result, LSB, shCount, sign);
7796     else{
7797       movLeft2Result(left, MSB24, result, LSB);
7798       movLeft2Result(left, MSB32, result, MSB16);
7799     }
7800     pic16_addSign(result, MSB24, sign);
7801   }
7802   else if(shCount >= 8){
7803     shCount -= 8;
7804     if(shCount == 1)
7805       shiftRLong(left, MSB16, result, sign);
7806     else if(shCount == 0){
7807       movLeft2Result(left, MSB16, result, LSB);
7808       movLeft2Result(left, MSB24, result, MSB16);
7809       movLeft2Result(left, MSB32, result, MSB24);
7810       pic16_addSign(result, MSB32, sign);
7811     }
7812     else{ //shcount >= 2
7813       shiftR2Left2Result(left, MSB16, result, LSB, shCount, 0);
7814       shiftLLeftOrResult(left, MSB32, result, MSB16, 8 - shCount);
7815       /* the last shift is signed */
7816       shiftR1Left2Result(left, MSB32, result, MSB24, shCount, sign);
7817       pic16_addSign(result, MSB32, sign);
7818     }
7819   }
7820   else{   /* 1 <= shCount <= 7 */
7821     if(shCount <= 2){
7822       shiftRLong(left, LSB, result, sign);
7823       if(shCount == 2)
7824         shiftRLong(result, LSB, result, sign);
7825     }
7826     else{
7827       shiftR2Left2Result(left, LSB, result, LSB, shCount, 0);
7828       shiftLLeftOrResult(left, MSB24, result, MSB16, 8 - shCount);
7829       shiftR2Left2Result(left, MSB24, result, MSB24, shCount, sign);
7830     }
7831   }
7832 }
7833
7834 /*-----------------------------------------------------------------*/
7835 /* genRightShiftLiteral - right shifting by known count            */
7836 /*-----------------------------------------------------------------*/
7837 static void genRightShiftLiteral (operand *left,
7838                                   operand *right,
7839                                   operand *result,
7840                                   iCode *ic,
7841                                   int sign)
7842 {    
7843   int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
7844   int lsize,res_size;
7845
7846   pic16_freeAsmop(right,NULL,ic,TRUE);
7847
7848   pic16_aopOp(left,ic,FALSE);
7849   pic16_aopOp(result,ic,FALSE);
7850
7851   DEBUGpic16_emitcode ("; ***","%s  %d shCount:%d result:%d left:%d",__FUNCTION__,__LINE__,shCount,AOP_SIZE(result),AOP_SIZE(left));
7852
7853 #if VIEW_SIZE
7854   pic16_emitcode("; shift right ","result %d, left %d",AOP_SIZE(result),
7855                  AOP_SIZE(left));
7856 #endif
7857
7858   lsize = pic16_getDataSize(left);
7859   res_size = pic16_getDataSize(result);
7860   /* test the LEFT size !!! */
7861
7862   /* I suppose that the left size >= result size */
7863   if(shCount == 0){
7864     while(res_size--)
7865       movLeft2Result(left, lsize, result, res_size);
7866   }
7867
7868   else if(shCount >= (lsize * 8)){
7869
7870     if(res_size == 1) {
7871       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),LSB));
7872       if(sign) {
7873         pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7874         pic16_emitpcode(POC_DECF, pic16_popGet(AOP(result),LSB));
7875       }
7876     } else {
7877
7878       if(sign) {
7879         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
7880         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),lsize-1,FALSE,FALSE),7,0));
7881         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
7882         while(res_size--)
7883           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),res_size));
7884
7885       } else {
7886
7887         while(res_size--)
7888           pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),res_size));
7889       }
7890     }
7891   } else {
7892
7893     switch (res_size) {
7894     case 1:
7895       genrshOne (result,left,shCount,sign);
7896       break;
7897
7898     case 2:
7899       genrshTwo (result,left,shCount,sign);
7900       break;
7901
7902     case 4:
7903       genrshFour (result,left,shCount,sign);
7904       break;
7905     default :
7906       break;
7907     }
7908
7909   }
7910
7911   pic16_freeAsmop(left,NULL,ic,TRUE);
7912   pic16_freeAsmop(result,NULL,ic,TRUE);
7913 }
7914
7915 /*-----------------------------------------------------------------*/
7916 /* genSignedRightShift - right shift of signed number              */
7917 /*-----------------------------------------------------------------*/
7918 static void genSignedRightShift (iCode *ic)
7919 {
7920   operand *right, *left, *result;
7921   int size, offset;
7922   //  char *l;
7923   symbol *tlbl, *tlbl1 ;
7924   pCodeOp *pctemp;
7925
7926   //same = ((left == result) || (AOP(left) == AOP(result))) && (offl == offr);
7927
7928   /* we do it the hard way put the shift count in b
7929      and loop thru preserving the sign */
7930   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
7931
7932   right = IC_RIGHT(ic);
7933   left  = IC_LEFT(ic);
7934   result = IC_RESULT(ic);
7935
7936   pic16_aopOp(right,ic,FALSE);  
7937   pic16_aopOp(left,ic,FALSE);
7938   pic16_aopOp(result,ic,FALSE);
7939
7940
7941   if ( AOP_TYPE(right) == AOP_LIT) {
7942     genRightShiftLiteral (left,right,result,ic,1);
7943     return ;
7944   }
7945   /* shift count is unknown then we have to form 
7946      a loop get the loop count in B : Note: we take
7947      only the lower order byte since shifting
7948      more that 32 bits make no sense anyway, ( the
7949      largest size of an object can be only 32 bits ) */  
7950
7951   //pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
7952   //pic16_emitcode("inc","b");
7953   //pic16_freeAsmop (right,NULL,ic,TRUE);
7954   //pic16_aopOp(left,ic,FALSE);
7955   //pic16_aopOp(result,ic,FALSE);
7956
7957   /* now move the left to the result if they are not the
7958      same */
7959   if (!pic16_sameRegs(AOP(left),AOP(result)) && 
7960       AOP_SIZE(result) > 1) {
7961
7962     size = AOP_SIZE(result);
7963     offset=0;
7964     while (size--) { 
7965       /*
7966         l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
7967         if (*l == '@' && IS_AOP_PREG(result)) {
7968
7969         pic16_emitcode("mov","a,%s",l);
7970         pic16_aopPut(AOP(result),"a",offset);
7971         } else
7972         pic16_aopPut(AOP(result),l,offset);
7973       */
7974       pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),offset));
7975       pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),offset));
7976
7977       offset++;
7978     }
7979   }
7980
7981   /* mov the highest order bit to OVR */    
7982   tlbl = newiTempLabel(NULL);
7983   tlbl1= newiTempLabel(NULL);
7984
7985   size = AOP_SIZE(result);
7986   offset = size - 1;
7987
7988   pctemp = pic16_popGetTempReg();  /* grab a temporary working register. */
7989
7990   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
7991
7992   /* offset should be 0, 1 or 3 */
7993   pic16_emitpcode(POC_ANDLW, pic16_popGetLit(0x07 + ((offset&3) << 3)));
7994   emitSKPNZ;
7995   pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl1->key));
7996
7997   pic16_emitpcode(POC_MOVWF, pctemp);
7998
7999
8000   pic16_emitpLabel(tlbl->key);
8001
8002   pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(result),offset));
8003   pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),offset));
8004
8005   while(--size) {
8006     pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(result),--offset));
8007   }
8008
8009   pic16_emitpcode(POC_DECFSZ,  pctemp);
8010   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8011   pic16_emitpLabel(tlbl1->key);
8012
8013   pic16_popReleaseTempReg(pctemp);
8014 #if 0
8015   size = AOP_SIZE(result);
8016   offset = size - 1;
8017   pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(left),offset,FALSE,FALSE));
8018   pic16_emitcode("rlc","a");
8019   pic16_emitcode("mov","ov,c");
8020   /* if it is only one byte then */
8021   if (size == 1) {
8022     l = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8023     MOVA(l);
8024     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8025     pic16_emitcode("","%05d_DS_:",tlbl->key+100);
8026     pic16_emitcode("mov","c,ov");
8027     pic16_emitcode("rrc","a");
8028     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8029     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8030     pic16_aopPut(AOP(result),"a",0);
8031     goto release ;
8032   }
8033
8034   reAdjustPreg(AOP(result));
8035   pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8036   pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8037   pic16_emitcode("mov","c,ov");
8038   while (size--) {
8039     l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8040     MOVA(l);
8041     pic16_emitcode("rrc","a");         
8042     pic16_aopPut(AOP(result),"a",offset--);
8043   }
8044   reAdjustPreg(AOP(result));
8045   pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8046   pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8047
8048  release:
8049 #endif
8050
8051   pic16_freeAsmop(left,NULL,ic,TRUE);
8052   pic16_freeAsmop(result,NULL,ic,TRUE);
8053   pic16_freeAsmop(right,NULL,ic,TRUE);
8054 }
8055
8056 /*-----------------------------------------------------------------*/
8057 /* genRightShift - generate code for right shifting                */
8058 /*-----------------------------------------------------------------*/
8059 static void genRightShift (iCode *ic)
8060 {
8061     operand *right, *left, *result;
8062     sym_link *letype ;
8063     int size, offset;
8064     char *l;
8065     symbol *tlbl, *tlbl1 ;
8066
8067     /* if signed then we do it the hard way preserve the
8068     sign bit moving it inwards */
8069     letype = getSpec(operandType(IC_LEFT(ic)));
8070     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8071
8072     if (!SPEC_USIGN(letype)) {
8073         genSignedRightShift (ic);
8074         return ;
8075     }
8076
8077     /* signed & unsigned types are treated the same : i.e. the
8078     signed is NOT propagated inwards : quoting from the
8079     ANSI - standard : "for E1 >> E2, is equivalent to division
8080     by 2**E2 if unsigned or if it has a non-negative value,
8081     otherwise the result is implementation defined ", MY definition
8082     is that the sign does not get propagated */
8083
8084     right = IC_RIGHT(ic);
8085     left  = IC_LEFT(ic);
8086     result = IC_RESULT(ic);
8087
8088     pic16_aopOp(right,ic,FALSE);
8089
8090     /* if the shift count is known then do it 
8091     as efficiently as possible */
8092     if (AOP_TYPE(right) == AOP_LIT) {
8093         genRightShiftLiteral (left,right,result,ic, 0);
8094         return ;
8095     }
8096
8097     /* shift count is unknown then we have to form 
8098     a loop get the loop count in B : Note: we take
8099     only the lower order byte since shifting
8100     more that 32 bits make no sense anyway, ( the
8101     largest size of an object can be only 32 bits ) */  
8102
8103     pic16_emitcode("mov","b,%s",pic16_aopGet(AOP(right),0,FALSE,FALSE));
8104     pic16_emitcode("inc","b");
8105     pic16_aopOp(left,ic,FALSE);
8106     pic16_aopOp(result,ic,FALSE);
8107
8108     /* now move the left to the result if they are not the
8109     same */
8110     if (!pic16_sameRegs(AOP(left),AOP(result)) && 
8111         AOP_SIZE(result) > 1) {
8112
8113         size = AOP_SIZE(result);
8114         offset=0;
8115         while (size--) {
8116             l = pic16_aopGet(AOP(left),offset,FALSE,TRUE);
8117             if (*l == '@' && IS_AOP_PREG(result)) {
8118
8119                 pic16_emitcode("mov","a,%s",l);
8120                 pic16_aopPut(AOP(result),"a",offset);
8121             } else
8122                 pic16_aopPut(AOP(result),l,offset);
8123             offset++;
8124         }
8125     }
8126
8127     tlbl = newiTempLabel(NULL);
8128     tlbl1= newiTempLabel(NULL);
8129     size = AOP_SIZE(result);
8130     offset = size - 1;
8131
8132     /* if it is only one byte then */
8133     if (size == 1) {
8134
8135       tlbl = newiTempLabel(NULL);
8136       if (!pic16_sameRegs(AOP(left),AOP(result))) {
8137         pic16_emitpcode(POC_MOVFW,  pic16_popGet(AOP(left),0));
8138         pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),0));
8139       }
8140
8141       pic16_emitpcode(POC_COMFW,  pic16_popGet(AOP(right),0));
8142       pic16_emitpcode(POC_RLCF,    pic16_popGet(AOP(result),0));
8143       pic16_emitpLabel(tlbl->key);
8144       pic16_emitpcode(POC_RRCF,    pic16_popGet(AOP(result),0));
8145       pic16_emitpcode(POC_ADDLW,  pic16_popGetLit(1));
8146       emitSKPC;
8147       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(tlbl->key));
8148
8149       goto release ;
8150     }
8151
8152     reAdjustPreg(AOP(result));
8153     pic16_emitcode("sjmp","%05d_DS_",tlbl1->key+100);
8154     pic16_emitcode("","%05d_DS_:",tlbl->key+100);    
8155     CLRC;
8156     while (size--) {
8157         l = pic16_aopGet(AOP(result),offset,FALSE,FALSE);
8158         MOVA(l);
8159         pic16_emitcode("rrc","a");         
8160         pic16_aopPut(AOP(result),"a",offset--);
8161     }
8162     reAdjustPreg(AOP(result));
8163
8164     pic16_emitcode("","%05d_DS_:",tlbl1->key+100);
8165     pic16_emitcode("djnz","b,%05d_DS_",tlbl->key+100);
8166
8167 release:
8168     pic16_freeAsmop(left,NULL,ic,TRUE);
8169     pic16_freeAsmop (right,NULL,ic,TRUE);
8170     pic16_freeAsmop(result,NULL,ic,TRUE);
8171 }
8172
8173 /*-----------------------------------------------------------------*/
8174 /* genUnpackBits - generates code for unpacking bits               */
8175 /*-----------------------------------------------------------------*/
8176 static void genUnpackBits (operand *result, char *rname, int ptype)
8177 {    
8178     int shCnt ;
8179     int rlen = 0 ;
8180     sym_link *etype;
8181     int offset = 0 ;
8182
8183     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8184     etype = getSpec(operandType(result));
8185
8186     /* read the first byte  */
8187     switch (ptype) {
8188
8189     case POINTER:
8190     case IPOINTER:
8191         pic16_emitcode("mov","a,@%s",rname);
8192         break;
8193         
8194     case PPOINTER:
8195         pic16_emitcode("movx","a,@%s",rname);
8196         break;
8197         
8198     case FPOINTER:
8199         pic16_emitcode("movx","a,@dptr");
8200         break;
8201
8202     case CPOINTER:
8203         pic16_emitcode("clr","a");
8204         pic16_emitcode("movc","a","@a+dptr");
8205         break;
8206
8207     case GPOINTER:
8208         pic16_emitcode("lcall","__gptrget");
8209         break;
8210     }
8211
8212     /* if we have bitdisplacement then it fits   */
8213     /* into this byte completely or if length is */
8214     /* less than a byte                          */
8215     if ((shCnt = SPEC_BSTR(etype)) || 
8216         (SPEC_BLEN(etype) <= 8))  {
8217
8218         /* shift right acc */
8219         AccRsh(shCnt);
8220
8221         pic16_emitcode("anl","a,#0x%02x",
8222                  ((unsigned char) -1)>>(8 - SPEC_BLEN(etype)));
8223         pic16_aopPut(AOP(result),"a",offset);
8224         return ;
8225     }
8226
8227     /* bit field did not fit in a byte  */
8228     rlen = SPEC_BLEN(etype) - 8;
8229     pic16_aopPut(AOP(result),"a",offset++);
8230
8231     while (1)  {
8232
8233         switch (ptype) {
8234         case POINTER:
8235         case IPOINTER:
8236             pic16_emitcode("inc","%s",rname);
8237             pic16_emitcode("mov","a,@%s",rname);
8238             break;
8239             
8240         case PPOINTER:
8241             pic16_emitcode("inc","%s",rname);
8242             pic16_emitcode("movx","a,@%s",rname);
8243             break;
8244
8245         case FPOINTER:
8246             pic16_emitcode("inc","dptr");
8247             pic16_emitcode("movx","a,@dptr");
8248             break;
8249             
8250         case CPOINTER:
8251             pic16_emitcode("clr","a");
8252             pic16_emitcode("inc","dptr");
8253             pic16_emitcode("movc","a","@a+dptr");
8254             break;
8255             
8256         case GPOINTER:
8257             pic16_emitcode("inc","dptr");
8258             pic16_emitcode("lcall","__gptrget");
8259             break;
8260         }
8261
8262         rlen -= 8;            
8263         /* if we are done */
8264         if ( rlen <= 0 )
8265             break ;
8266         
8267         pic16_aopPut(AOP(result),"a",offset++);
8268                               
8269     }
8270     
8271     if (rlen) {
8272         pic16_emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(-rlen));
8273         pic16_aopPut(AOP(result),"a",offset);          
8274     }
8275     
8276     return ;
8277 }
8278
8279 #if 0
8280 /*-----------------------------------------------------------------*/
8281 /* genDataPointerGet - generates code when ptr offset is known     */
8282 /*-----------------------------------------------------------------*/
8283 static void genDataPointerGet (operand *left, 
8284                                operand *result, 
8285                                iCode *ic)
8286 {
8287   int size , offset = 0;
8288
8289
8290   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8291
8292
8293   /* optimization - most of the time, left and result are the same
8294    * address, but different types. for the pic code, we could omit
8295    * the following
8296    */
8297
8298   pic16_aopOp(result,ic,TRUE);
8299
8300   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8301
8302   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
8303
8304   size = AOP_SIZE(result);
8305
8306   while (size--) {
8307     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
8308     offset++;
8309   }
8310
8311   pic16_freeAsmop(left,NULL,ic,TRUE);
8312   pic16_freeAsmop(result,NULL,ic,TRUE);
8313 }
8314 #endif
8315 /*-----------------------------------------------------------------*/
8316 /* genNearPointerGet - pic16_emitcode for near pointer fetch             */
8317 /*-----------------------------------------------------------------*/
8318 static void genNearPointerGet (operand *left, 
8319                                operand *result, 
8320                                iCode *ic)
8321 {
8322     asmop *aop = NULL;
8323     //regs *preg = NULL ;
8324     char *rname ;
8325     sym_link *rtype, *retype;
8326     sym_link *ltype = operandType(left);    
8327     //char buffer[80];
8328
8329     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8330
8331     rtype = operandType(result);
8332     retype= getSpec(rtype);
8333     
8334     pic16_aopOp(left,ic,FALSE);
8335     
8336     /* if left is rematerialisable and
8337        result is not bit variable type and
8338        the left is pointer to data space i.e
8339        lower 128 bytes of space */
8340     if (AOP_TYPE(left) == AOP_PCODE &&  //AOP_TYPE(left) == AOP_IMMD &&
8341         !IS_BITVAR(retype)         &&
8342         DCL_TYPE(ltype) == POINTER) {
8343       //genDataPointerGet (left,result,ic);
8344         return ;
8345     }
8346     
8347     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8348
8349         /* if the value is already in a pointer register
8350        then don't need anything more */
8351     if (!AOP_INPREG(AOP(left))) {
8352         /* otherwise get a free pointer register */
8353     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8354 /*
8355         aop = newAsmop(0);
8356         preg = getFreePtr(ic,&aop,FALSE);
8357         pic16_emitcode("mov","%s,%s",
8358                 preg->name,
8359                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8360         rname = preg->name ;
8361 */
8362     rname ="BAD";
8363     } else
8364         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8365     
8366     pic16_aopOp (result,ic,FALSE);
8367     
8368       /* if bitfield then unpack the bits */
8369     if (IS_BITVAR(retype)) 
8370         genUnpackBits (result,rname,POINTER);
8371     else {
8372         /* we have can just get the values */
8373       int size = AOP_SIZE(result);
8374       int offset = 0 ;  
8375         
8376       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8377
8378       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8379       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8380       while(size--) {
8381         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8382         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8383         if(size)
8384           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8385       }
8386 /*
8387         while (size--) {
8388             if (IS_AOP_PREG(result) || AOP_TYPE(result) == AOP_STK ) {
8389
8390                 pic16_emitcode("mov","a,@%s",rname);
8391                 pic16_aopPut(AOP(result),"a",offset);
8392             } else {
8393                 sprintf(buffer,"@%s",rname);
8394                 pic16_aopPut(AOP(result),buffer,offset);
8395             }
8396             offset++ ;
8397             if (size)
8398                 pic16_emitcode("inc","%s",rname);
8399         }
8400 */
8401     }
8402
8403     /* now some housekeeping stuff */
8404     if (aop) {
8405         /* we had to allocate for this iCode */
8406     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8407         pic16_freeAsmop(NULL,aop,ic,TRUE);
8408     } else { 
8409         /* we did not allocate which means left
8410            already in a pointer register, then
8411            if size > 0 && this could be used again
8412            we have to point it back to where it 
8413            belongs */
8414     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8415         if (AOP_SIZE(result) > 1 &&
8416             !OP_SYMBOL(left)->remat &&
8417             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8418               ic->depth )) {
8419             int size = AOP_SIZE(result) - 1;
8420             while (size--)
8421                 pic16_emitcode("dec","%s",rname);
8422         }
8423     }
8424
8425     /* done */
8426     pic16_freeAsmop(left,NULL,ic,TRUE);
8427     pic16_freeAsmop(result,NULL,ic,TRUE);
8428      
8429 }
8430
8431 /*-----------------------------------------------------------------*/
8432 /* genPagedPointerGet - pic16_emitcode for paged pointer fetch           */
8433 /*-----------------------------------------------------------------*/
8434 static void genPagedPointerGet (operand *left, 
8435                                operand *result, 
8436                                iCode *ic)
8437 {
8438     asmop *aop = NULL;
8439     regs *preg = NULL ;
8440     char *rname ;
8441     sym_link *rtype, *retype;    
8442
8443     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8444
8445     rtype = operandType(result);
8446     retype= getSpec(rtype);
8447     
8448     pic16_aopOp(left,ic,FALSE);
8449
8450   /* if the value is already in a pointer register
8451        then don't need anything more */
8452     if (!AOP_INPREG(AOP(left))) {
8453         /* otherwise get a free pointer register */
8454         aop = newAsmop(0);
8455         preg = getFreePtr(ic,&aop,FALSE);
8456         pic16_emitcode("mov","%s,%s",
8457                 preg->name,
8458                 pic16_aopGet(AOP(left),0,FALSE,TRUE));
8459         rname = preg->name ;
8460     } else
8461         rname = pic16_aopGet(AOP(left),0,FALSE,FALSE);
8462     
8463     pic16_freeAsmop(left,NULL,ic,TRUE);
8464     pic16_aopOp (result,ic,FALSE);
8465
8466     /* if bitfield then unpack the bits */
8467     if (IS_BITVAR(retype)) 
8468         genUnpackBits (result,rname,PPOINTER);
8469     else {
8470         /* we have can just get the values */
8471         int size = AOP_SIZE(result);
8472         int offset = 0 ;        
8473         
8474         while (size--) {
8475             
8476             pic16_emitcode("movx","a,@%s",rname);
8477             pic16_aopPut(AOP(result),"a",offset);
8478             
8479             offset++ ;
8480             
8481             if (size)
8482                 pic16_emitcode("inc","%s",rname);
8483         }
8484     }
8485
8486     /* now some housekeeping stuff */
8487     if (aop) {
8488         /* we had to allocate for this iCode */
8489         pic16_freeAsmop(NULL,aop,ic,TRUE);
8490     } else { 
8491         /* we did not allocate which means left
8492            already in a pointer register, then
8493            if size > 0 && this could be used again
8494            we have to point it back to where it 
8495            belongs */
8496         if (AOP_SIZE(result) > 1 &&
8497             !OP_SYMBOL(left)->remat &&
8498             ( OP_SYMBOL(left)->liveTo > ic->seq ||
8499               ic->depth )) {
8500             int size = AOP_SIZE(result) - 1;
8501             while (size--)
8502                 pic16_emitcode("dec","%s",rname);
8503         }
8504     }
8505
8506     /* done */
8507     pic16_freeAsmop(result,NULL,ic,TRUE);
8508     
8509         
8510 }
8511
8512 /*-----------------------------------------------------------------*/
8513 /* genFarPointerGet - gget value from far space                    */
8514 /*-----------------------------------------------------------------*/
8515 static void genFarPointerGet (operand *left,
8516                               operand *result, iCode *ic)
8517 {
8518     int size, offset ;
8519     sym_link *retype = getSpec(operandType(result));
8520
8521     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8522
8523     pic16_aopOp(left,ic,FALSE);
8524
8525     /* if the operand is already in dptr 
8526     then we do nothing else we move the value to dptr */
8527     if (AOP_TYPE(left) != AOP_STR) {
8528         /* if this is remateriazable */
8529         if (AOP_TYPE(left) == AOP_IMMD)
8530             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8531         else { /* we need to get it byte by byte */
8532             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8533             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8534             if (options.model == MODEL_FLAT24)
8535             {
8536                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8537             }
8538         }
8539     }
8540     /* so dptr know contains the address */
8541     pic16_freeAsmop(left,NULL,ic,TRUE);
8542     pic16_aopOp(result,ic,FALSE);
8543
8544     /* if bit then unpack */
8545     if (IS_BITVAR(retype)) 
8546         genUnpackBits(result,"dptr",FPOINTER);
8547     else {
8548         size = AOP_SIZE(result);
8549         offset = 0 ;
8550
8551         while (size--) {
8552             pic16_emitcode("movx","a,@dptr");
8553             pic16_aopPut(AOP(result),"a",offset++);
8554             if (size)
8555                 pic16_emitcode("inc","dptr");
8556         }
8557     }
8558
8559     pic16_freeAsmop(result,NULL,ic,TRUE);
8560 }
8561 #if 0
8562 /*-----------------------------------------------------------------*/
8563 /* genCodePointerGet - get value from code space                  */
8564 /*-----------------------------------------------------------------*/
8565 static void genCodePointerGet (operand *left,
8566                                 operand *result, iCode *ic)
8567 {
8568     int size, offset ;
8569     sym_link *retype = getSpec(operandType(result));
8570
8571     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8572
8573     pic16_aopOp(left,ic,FALSE);
8574
8575     /* if the operand is already in dptr 
8576     then we do nothing else we move the value to dptr */
8577     if (AOP_TYPE(left) != AOP_STR) {
8578         /* if this is remateriazable */
8579         if (AOP_TYPE(left) == AOP_IMMD)
8580             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8581         else { /* we need to get it byte by byte */
8582             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(left),0,FALSE,FALSE));
8583             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(left),1,FALSE,FALSE));
8584             if (options.model == MODEL_FLAT24)
8585             {
8586                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(left),2,FALSE,FALSE));
8587             }
8588         }
8589     }
8590     /* so dptr know contains the address */
8591     pic16_freeAsmop(left,NULL,ic,TRUE);
8592     pic16_aopOp(result,ic,FALSE);
8593
8594     /* if bit then unpack */
8595     if (IS_BITVAR(retype)) 
8596         genUnpackBits(result,"dptr",CPOINTER);
8597     else {
8598         size = AOP_SIZE(result);
8599         offset = 0 ;
8600
8601         while (size--) {
8602             pic16_emitcode("clr","a");
8603             pic16_emitcode("movc","a,@a+dptr");
8604             pic16_aopPut(AOP(result),"a",offset++);
8605             if (size)
8606                 pic16_emitcode("inc","dptr");
8607         }
8608     }
8609
8610     pic16_freeAsmop(result,NULL,ic,TRUE);
8611 }
8612 #endif
8613 /*-----------------------------------------------------------------*/
8614 /* genGenPointerGet - gget value from generic pointer space        */
8615 /*-----------------------------------------------------------------*/
8616 static void genGenPointerGet (operand *left,
8617                               operand *result, iCode *ic)
8618 {
8619   int size, offset ;
8620   sym_link *retype = getSpec(operandType(result));
8621
8622   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8623   pic16_aopOp(left,ic,FALSE);
8624   pic16_aopOp(result,ic,FALSE);
8625
8626
8627   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8628
8629   /* if the operand is already in dptr 
8630      then we do nothing else we move the value to dptr */
8631   //  if (AOP_TYPE(left) != AOP_STR) {
8632     /* if this is remateriazable */
8633     if (AOP_TYPE(left) == AOP_IMMD) {
8634       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(left),0,TRUE,FALSE));
8635       pic16_emitcode("mov","b,#%d",pointerCode(retype));
8636     }
8637     else { /* we need to get it byte by byte */
8638
8639       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(left),0));
8640       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
8641
8642       size = AOP_SIZE(result);
8643       offset = 0 ;
8644
8645       while(size--) {
8646         pic16_emitpcode(POC_MOVFW,pic16_popCopyReg(&pic16_pc_indf0));
8647         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),offset++));
8648         if(size)
8649           pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
8650       }
8651       goto release;
8652     }
8653     //}
8654   /* so dptr know contains the address */
8655
8656   /* if bit then unpack */
8657         if (IS_BITVAR(retype)) 
8658         genUnpackBits(result,"BAD",GPOINTER);
8659
8660  release:
8661   pic16_freeAsmop(left,NULL,ic,TRUE);
8662   pic16_freeAsmop(result,NULL,ic,TRUE);
8663
8664 }
8665
8666 /*-----------------------------------------------------------------*/
8667 /* genConstPointerGet - get value from const generic pointer space */
8668 /*-----------------------------------------------------------------*/
8669 static void genConstPointerGet (operand *left,
8670                                 operand *result, iCode *ic)
8671 {
8672   //sym_link *retype = getSpec(operandType(result));
8673   symbol *albl = newiTempLabel(NULL);
8674   symbol *blbl = newiTempLabel(NULL);
8675   PIC_OPCODE poc;
8676
8677   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8678   pic16_aopOp(left,ic,FALSE);
8679   pic16_aopOp(result,ic,FALSE);
8680
8681
8682   DEBUGpic16_pic16_AopType(__LINE__,left,NULL,result);
8683
8684   DEBUGpic16_emitcode ("; "," %d getting const pointer",__LINE__);
8685
8686   pic16_emitpcode(POC_CALL,pic16_popGetLabel(albl->key));
8687   pic16_emitpcode(POC_GOTO,pic16_popGetLabel(blbl->key));
8688   pic16_emitpLabel(albl->key);
8689
8690   poc = ( (AOP_TYPE(left) == AOP_PCODE) ? POC_MOVLW : POC_MOVFW);
8691     
8692   /* this performs a goto to the specified address -- Why not to use pointer? -- VR */
8693   pic16_emitpcode(poc,pic16_popGet(AOP(left),1));
8694   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pclath));
8695   pic16_emitpcode(poc,pic16_popGet(AOP(left),0));
8696   pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_pcl));
8697
8698   pic16_emitpLabel(blbl->key);
8699
8700   pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
8701
8702
8703   pic16_freeAsmop(left,NULL,ic,TRUE);
8704   pic16_freeAsmop(result,NULL,ic,TRUE);
8705
8706 }
8707 /*-----------------------------------------------------------------*/
8708 /* genPointerGet - generate code for pointer get                   */
8709 /*-----------------------------------------------------------------*/
8710 static void genPointerGet (iCode *ic)
8711 {
8712     operand *left, *result ;
8713     sym_link *type, *etype;
8714     int p_type;
8715
8716     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8717
8718     left = IC_LEFT(ic);
8719     result = IC_RESULT(ic) ;
8720
8721     /* depending on the type of pointer we need to
8722     move it to the correct pointer register */
8723     type = operandType(left);
8724     etype = getSpec(type);
8725
8726 #if 0
8727     if (IS_PTR_CONST(type))
8728 #else
8729     if (IS_CODEPTR(type))
8730 #endif
8731       DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
8732
8733     /* if left is of type of pointer then it is simple */
8734     if (IS_PTR(type) && !IS_FUNC(type->next)) 
8735         p_type = DCL_TYPE(type);
8736     else {
8737         /* we have to go by the storage class */
8738         p_type = PTR_TYPE(SPEC_OCLS(etype));
8739
8740         DEBUGpic16_emitcode ("; ***","%d - resolve pointer by storage class",__LINE__);
8741
8742         if (SPEC_OCLS(etype)->codesp ) {
8743           DEBUGpic16_emitcode ("; ***","%d - cpointer",__LINE__);
8744           //p_type = CPOINTER ; 
8745         }
8746         else
8747             if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged)
8748               DEBUGpic16_emitcode ("; ***","%d - fpointer",__LINE__);
8749                /*p_type = FPOINTER ;*/ 
8750             else
8751                 if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged)
8752                   DEBUGpic16_emitcode ("; ***","%d - ppointer",__LINE__);
8753 /*                  p_type = PPOINTER; */
8754                 else
8755                     if (SPEC_OCLS(etype) == idata )
8756                       DEBUGpic16_emitcode ("; ***","%d - ipointer",__LINE__);
8757 /*                      p_type = IPOINTER; */
8758                     else
8759                       DEBUGpic16_emitcode ("; ***","%d - pointer",__LINE__);
8760 /*                      p_type = POINTER ; */
8761     }
8762
8763     /* now that we have the pointer type we assign
8764     the pointer values */
8765     switch (p_type) {
8766
8767     case POINTER:       
8768     case IPOINTER:
8769         genNearPointerGet (left,result,ic);
8770         break;
8771
8772     case PPOINTER:
8773         genPagedPointerGet(left,result,ic);
8774         break;
8775
8776     case FPOINTER:
8777         genFarPointerGet (left,result,ic);
8778         break;
8779
8780     case CPOINTER:
8781         genConstPointerGet (left,result,ic);
8782         //pic16_emitcodePointerGet (left,result,ic);
8783         break;
8784
8785     case GPOINTER:
8786 #if 0
8787       if (IS_PTR_CONST(type))
8788         genConstPointerGet (left,result,ic);
8789       else
8790 #endif
8791         genGenPointerGet (left,result,ic);
8792       break;
8793     }
8794
8795 }
8796
8797 /*-----------------------------------------------------------------*/
8798 /* genPackBits - generates code for packed bit storage             */
8799 /*-----------------------------------------------------------------*/
8800 static void genPackBits (sym_link    *etype ,
8801                          operand *right ,
8802                          char *rname, int p_type)
8803 {
8804     int shCount = 0 ;
8805     int offset = 0  ;
8806     int rLen = 0 ;
8807     int blen, bstr ;   
8808     char *l ;
8809
8810     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8811     blen = SPEC_BLEN(etype);
8812     bstr = SPEC_BSTR(etype);
8813
8814     l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
8815     MOVA(l);   
8816
8817     /* if the bit lenth is less than or    */
8818     /* it exactly fits a byte then         */
8819     if (SPEC_BLEN(etype) <= 8 )  {
8820         shCount = SPEC_BSTR(etype) ;
8821
8822         /* shift left acc */
8823         AccLsh(shCount);
8824
8825         if (SPEC_BLEN(etype) < 8 ) { /* if smaller than a byte */
8826
8827
8828             switch (p_type) {
8829                 case POINTER:
8830                     pic16_emitcode ("mov","b,a");
8831                     pic16_emitcode("mov","a,@%s",rname);
8832                     break;
8833
8834                 case FPOINTER:
8835                     pic16_emitcode ("mov","b,a");
8836                     pic16_emitcode("movx","a,@dptr");
8837                     break;
8838
8839                 case GPOINTER:
8840                     pic16_emitcode ("push","b");
8841                     pic16_emitcode ("push","acc");
8842                     pic16_emitcode ("lcall","__gptrget");
8843                     pic16_emitcode ("pop","b");
8844                     break;
8845             }
8846
8847             pic16_emitcode ("anl","a,#0x%02x",(unsigned char)
8848                       ((unsigned char)(0xFF << (blen+bstr)) | 
8849                        (unsigned char)(0xFF >> (8-bstr)) ) );
8850             pic16_emitcode ("orl","a,b");
8851             if (p_type == GPOINTER)
8852                 pic16_emitcode("pop","b");
8853         }
8854     }
8855
8856     switch (p_type) {
8857         case POINTER:
8858             pic16_emitcode("mov","@%s,a",rname);
8859             break;
8860
8861         case FPOINTER:
8862             pic16_emitcode("movx","@dptr,a");
8863             break;
8864
8865         case GPOINTER:
8866             DEBUGpic16_emitcode(";lcall","__gptrput");
8867             break;
8868     }
8869
8870     /* if we r done */
8871     if ( SPEC_BLEN(etype) <= 8 )
8872         return ;
8873
8874     pic16_emitcode("inc","%s",rname);
8875     rLen = SPEC_BLEN(etype) ;     
8876
8877     /* now generate for lengths greater than one byte */
8878     while (1) {
8879
8880         l = pic16_aopGet(AOP(right),offset++,FALSE,TRUE);
8881
8882         rLen -= 8 ;
8883         if (rLen <= 0 )
8884             break ;
8885
8886         switch (p_type) {
8887             case POINTER:
8888                 if (*l == '@') {
8889                     MOVA(l);
8890                     pic16_emitcode("mov","@%s,a",rname);
8891                 } else
8892                     pic16_emitcode("mov","@%s,%s",rname,l);
8893                 break;
8894
8895             case FPOINTER:
8896                 MOVA(l);
8897                 pic16_emitcode("movx","@dptr,a");
8898                 break;
8899
8900             case GPOINTER:
8901                 MOVA(l);
8902                 DEBUGpic16_emitcode(";lcall","__gptrput");
8903                 break;  
8904         }   
8905         pic16_emitcode ("inc","%s",rname);
8906     }
8907
8908     MOVA(l);
8909
8910     /* last last was not complete */
8911     if (rLen)   {
8912         /* save the byte & read byte */
8913         switch (p_type) {
8914             case POINTER:
8915                 pic16_emitcode ("mov","b,a");
8916                 pic16_emitcode("mov","a,@%s",rname);
8917                 break;
8918
8919             case FPOINTER:
8920                 pic16_emitcode ("mov","b,a");
8921                 pic16_emitcode("movx","a,@dptr");
8922                 break;
8923
8924             case GPOINTER:
8925                 pic16_emitcode ("push","b");
8926                 pic16_emitcode ("push","acc");
8927                 pic16_emitcode ("lcall","__gptrget");
8928                 pic16_emitcode ("pop","b");
8929                 break;
8930         }
8931
8932         pic16_emitcode ("anl","a,#0x%02x",((unsigned char)-1 << -rLen) );
8933         pic16_emitcode ("orl","a,b");
8934     }
8935
8936     if (p_type == GPOINTER)
8937         pic16_emitcode("pop","b");
8938
8939     switch (p_type) {
8940
8941     case POINTER:
8942         pic16_emitcode("mov","@%s,a",rname);
8943         break;
8944         
8945     case FPOINTER:
8946         pic16_emitcode("movx","@dptr,a");
8947         break;
8948         
8949     case GPOINTER:
8950         DEBUGpic16_emitcode(";lcall","__gptrput");
8951         break;                  
8952     }
8953 }
8954 /*-----------------------------------------------------------------*/
8955 /* genDataPointerSet - remat pointer to data space                 */
8956 /*-----------------------------------------------------------------*/
8957 static void genDataPointerSet(operand *right,
8958                               operand *result,
8959                               iCode *ic)
8960 {
8961     int size, offset = 0 ;
8962     char *l, buffer[256];
8963
8964     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
8965     pic16_aopOp(right,ic,FALSE);
8966     
8967     l = pic16_aopGet(AOP(result),0,FALSE,TRUE);
8968     size = AOP_SIZE(right);
8969 /*
8970     if ( AOP_TYPE(result) == AOP_PCODE) {
8971       fprintf(stderr,"genDataPointerSet   %s, %d\n",
8972               AOP(result)->aopu.pcop->name,
8973               PCOI(AOP(result)->aopu.pcop)->offset);
8974     }
8975 */
8976
8977     // tsd, was l+1 - the underline `_' prefix was being stripped
8978     while (size--) {
8979       if (offset) {
8980         sprintf(buffer,"(%s + %d)",l,offset);
8981         fprintf(stderr,"%s:%d: oops  %s\n",__FILE__, __LINE__, buffer);
8982       } else
8983         sprintf(buffer,"%s",l);
8984
8985         if (AOP_TYPE(right) == AOP_LIT) {
8986           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
8987           lit = lit >> (8*offset);
8988           if(lit&0xff) {
8989             pic16_emitcode("movlw","%d",lit);
8990             pic16_emitcode("movwf","%s",buffer);
8991
8992             pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit&0xff));
8993             //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
8994             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
8995
8996           } else {
8997             pic16_emitcode("clrf","%s",buffer);
8998             //pic16_emitpcode(POC_CLRF, pic16_popRegFromString(buffer));
8999             pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
9000           }
9001         }else {
9002           pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(right),offset,FALSE,FALSE));
9003           pic16_emitcode("movwf","%s",buffer);
9004
9005           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9006           //pic16_emitpcode(POC_MOVWF, pic16_popRegFromString(buffer));
9007           pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9008
9009         }
9010
9011         offset++;
9012     }
9013
9014     pic16_freeAsmop(right,NULL,ic,TRUE);
9015     pic16_freeAsmop(result,NULL,ic,TRUE);
9016 }
9017
9018 /*-----------------------------------------------------------------*/
9019 /* genNearPointerSet - pic16_emitcode for near pointer put                */
9020 /*-----------------------------------------------------------------*/
9021 static void genNearPointerSet (operand *right,
9022                                operand *result, 
9023                                iCode *ic)
9024 {
9025   asmop *aop = NULL;
9026   char *l;
9027   sym_link *retype;
9028   sym_link *ptype = operandType(result);
9029
9030     
9031   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9032   retype= getSpec(operandType(right));
9033
9034   pic16_aopOp(result,ic,FALSE);
9035
9036     
9037   /* if the result is rematerializable &
9038      in data space & not a bit variable */
9039   //if (AOP_TYPE(result) == AOP_IMMD &&
9040   if (AOP_TYPE(result) == AOP_PCODE &&  //AOP_TYPE(result) == AOP_IMMD &&
9041       DCL_TYPE(ptype) == POINTER   &&
9042       !IS_BITVAR(retype)) {
9043     genDataPointerSet (right,result,ic);
9044     pic16_freeAsmop(result,NULL,ic,TRUE);
9045     return;
9046   }
9047
9048   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9049   pic16_aopOp(right,ic,FALSE);
9050   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9051
9052   /* if the value is already in a pointer register
9053      then don't need anything more */
9054   if (!AOP_INPREG(AOP(result))) {
9055     /* otherwise get a free pointer register */
9056     //aop = newAsmop(0);
9057     //preg = getFreePtr(ic,&aop,FALSE);
9058     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9059     //pic16_emitcode("mov","%s,%s",
9060     //         preg->name,
9061     //         pic16_aopGet(AOP(result),0,FALSE,TRUE));
9062     //rname = preg->name ;
9063     //pic16_emitcode("movwf","fsr0");
9064     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(result),0));
9065     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_fsr0));
9066     pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
9067     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_indf0));
9068     goto release;
9069
9070   }// else
9071 //      rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9072
9073   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9074
9075   /* if bitfield then unpack the bits */
9076   if (IS_BITVAR(retype)) {
9077     werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
9078            "The programmer is obviously confused");
9079 //      genPackBits (retype,right,"BAD",POINTER);
9080     exit(1);
9081   }
9082   else {
9083     /* we have can just get the values */
9084     int size = AOP_SIZE(right);
9085     int offset = 0 ;    
9086
9087     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9088     while (size--) {
9089       l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9090       if (*l == '@' ) {
9091         //MOVA(l);
9092         //pic16_emitcode("mov","@%s,a",rname);
9093         pic16_emitcode("movf","indf0,w ;1");
9094       } else {
9095
9096         if (AOP_TYPE(right) == AOP_LIT) {
9097           unsigned int lit = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit);
9098           if(lit) {
9099             pic16_emitcode("movlw","%s",l);
9100             pic16_emitcode("movwf","indf0 ;2");
9101           } else 
9102             pic16_emitcode("clrf","indf0");
9103         }else {
9104           pic16_emitcode("movf","%s,w",l);
9105           pic16_emitcode("movwf","indf0 ;2");
9106         }
9107         //pic16_emitcode("mov","@%s,%s",rname,l);
9108       }
9109       if (size)
9110         pic16_emitcode("incf","fsr0,f ;3");
9111       //pic16_emitcode("inc","%s",rname);
9112       offset++;
9113     }
9114   }
9115
9116   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9117   /* now some housekeeping stuff */
9118   if (aop) {
9119     /* we had to allocate for this iCode */
9120     pic16_freeAsmop(NULL,aop,ic,TRUE);
9121   } else { 
9122     /* we did not allocate which means left
9123        already in a pointer register, then
9124        if size > 0 && this could be used again
9125        we have to point it back to where it 
9126        belongs */
9127     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9128     if (AOP_SIZE(right) > 1 &&
9129         !OP_SYMBOL(result)->remat &&
9130         ( OP_SYMBOL(result)->liveTo > ic->seq ||
9131           ic->depth )) {
9132       int size = AOP_SIZE(right) - 1;
9133       while (size--)
9134         pic16_emitcode("decf","fsr0,f");
9135       //pic16_emitcode("dec","%s",rname);
9136     }
9137   }
9138
9139   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9140   /* done */
9141  release:
9142   pic16_freeAsmop(right,NULL,ic,TRUE);
9143   pic16_freeAsmop(result,NULL,ic,TRUE);
9144 }
9145
9146 /*-----------------------------------------------------------------*/
9147 /* genPagedPointerSet - pic16_emitcode for Paged pointer put             */
9148 /*-----------------------------------------------------------------*/
9149 static void genPagedPointerSet (operand *right,
9150                                operand *result, 
9151                                iCode *ic)
9152 {
9153     asmop *aop = NULL;
9154     regs *preg = NULL ;
9155     char *rname , *l;
9156     sym_link *retype;
9157        
9158     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9159
9160     retype= getSpec(operandType(right));
9161     
9162     pic16_aopOp(result,ic,FALSE);
9163     
9164     /* if the value is already in a pointer register
9165        then don't need anything more */
9166     if (!AOP_INPREG(AOP(result))) {
9167         /* otherwise get a free pointer register */
9168         aop = newAsmop(0);
9169         preg = getFreePtr(ic,&aop,FALSE);
9170         pic16_emitcode("mov","%s,%s",
9171                 preg->name,
9172                 pic16_aopGet(AOP(result),0,FALSE,TRUE));
9173         rname = preg->name ;
9174     } else
9175         rname = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9176     
9177     pic16_freeAsmop(result,NULL,ic,TRUE);
9178     pic16_aopOp (right,ic,FALSE);
9179
9180     /* if bitfield then unpack the bits */
9181     if (IS_BITVAR(retype)) 
9182         genPackBits (retype,right,rname,PPOINTER);
9183     else {
9184         /* we have can just get the values */
9185         int size = AOP_SIZE(right);
9186         int offset = 0 ;        
9187         
9188         while (size--) {
9189             l = pic16_aopGet(AOP(right),offset,FALSE,TRUE);
9190             
9191             MOVA(l);
9192             pic16_emitcode("movx","@%s,a",rname);
9193
9194             if (size)
9195                 pic16_emitcode("inc","%s",rname);
9196
9197             offset++;
9198         }
9199     }
9200     
9201     /* now some housekeeping stuff */
9202     if (aop) {
9203         /* we had to allocate for this iCode */
9204         pic16_freeAsmop(NULL,aop,ic,TRUE);
9205     } else { 
9206         /* we did not allocate which means left
9207            already in a pointer register, then
9208            if size > 0 && this could be used again
9209            we have to point it back to where it 
9210            belongs */
9211         if (AOP_SIZE(right) > 1 &&
9212             !OP_SYMBOL(result)->remat &&
9213             ( OP_SYMBOL(result)->liveTo > ic->seq ||
9214               ic->depth )) {
9215             int size = AOP_SIZE(right) - 1;
9216             while (size--)
9217                 pic16_emitcode("dec","%s",rname);
9218         }
9219     }
9220
9221     /* done */
9222     pic16_freeAsmop(right,NULL,ic,TRUE);
9223     
9224         
9225 }
9226
9227 /*-----------------------------------------------------------------*/
9228 /* genFarPointerSet - set value from far space                     */
9229 /*-----------------------------------------------------------------*/
9230 static void genFarPointerSet (operand *right,
9231                               operand *result, iCode *ic)
9232 {
9233     int size, offset ;
9234     sym_link *retype = getSpec(operandType(right));
9235
9236     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9237     pic16_aopOp(result,ic,FALSE);
9238
9239     /* if the operand is already in dptr 
9240     then we do nothing else we move the value to dptr */
9241     if (AOP_TYPE(result) != AOP_STR) {
9242         /* if this is remateriazable */
9243         if (AOP_TYPE(result) == AOP_IMMD)
9244             pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9245         else { /* we need to get it byte by byte */
9246             pic16_emitcode("mov","dpl,%s",pic16_aopGet(AOP(result),0,FALSE,FALSE));
9247             pic16_emitcode("mov","dph,%s",pic16_aopGet(AOP(result),1,FALSE,FALSE));
9248             if (options.model == MODEL_FLAT24)
9249             {
9250                pic16_emitcode("mov", "dpx,%s",pic16_aopGet(AOP(result),2,FALSE,FALSE));
9251             }
9252         }
9253     }
9254     /* so dptr know contains the address */
9255     pic16_freeAsmop(result,NULL,ic,TRUE);
9256     pic16_aopOp(right,ic,FALSE);
9257
9258     /* if bit then unpack */
9259     if (IS_BITVAR(retype)) 
9260         genPackBits(retype,right,"dptr",FPOINTER);
9261     else {
9262         size = AOP_SIZE(right);
9263         offset = 0 ;
9264
9265         while (size--) {
9266             char *l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9267             MOVA(l);
9268             pic16_emitcode("movx","@dptr,a");
9269             if (size)
9270                 pic16_emitcode("inc","dptr");
9271         }
9272     }
9273
9274     pic16_freeAsmop(right,NULL,ic,TRUE);
9275 }
9276
9277 /*-----------------------------------------------------------------*/
9278 /* genGenPointerSet - set value from generic pointer space         */
9279 /*-----------------------------------------------------------------*/
9280 static void genGenPointerSet (operand *right,
9281                               operand *result, iCode *ic)
9282 {
9283   int size, offset ;
9284   sym_link *retype = getSpec(operandType(right));
9285
9286   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9287
9288   pic16_aopOp(result,ic,FALSE);
9289   pic16_aopOp(right,ic,FALSE);
9290   size = AOP_SIZE(right);
9291
9292   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9293
9294   /* if the operand is already in dptr 
9295      then we do nothing else we move the value to dptr */
9296   if (AOP_TYPE(result) != AOP_STR) {
9297     /* if this is remateriazable */
9298     if (AOP_TYPE(result) == AOP_IMMD) {
9299       pic16_emitcode("mov","dptr,%s",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9300       pic16_emitcode("mov","b,%s + 1",pic16_aopGet(AOP(result),0,TRUE,FALSE));
9301     }
9302     else { /* we need to get it byte by byte */
9303       //char *l = pic16_aopGet(AOP(result),0,FALSE,FALSE);
9304       size = AOP_SIZE(right);
9305       offset = 0 ;
9306
9307       /* hack hack! see if this the FSR. If so don't load W */
9308       if(AOP_TYPE(right) != AOP_ACC) {
9309
9310 //      pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(result), pic16_popCopyReg(&pic16_pc_fsr0), 0));
9311
9312         pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),0));
9313         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9314
9315         if(AOP_SIZE(result) > 1) {
9316           pic16_emitpcode(POC_BCF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9317           pic16_emitpcode(POC_BTFSC,pic16_newpCodeOpBit(pic16_aopGet(AOP(result),1,FALSE,FALSE),0,0));
9318           pic16_emitpcode(POC_BSF,  pic16_popCopyGPR2Bit(PCOP(&pic16_pc_status),PIC_IRP_BIT));
9319
9320         }
9321
9322         //if(size==2)
9323         //pic16_emitpcode(POC_DECF,pic16_popCopyReg(&pic16_pc_fsr0));
9324         //if(size==4) {
9325         //  pic16_emitpcode(POC_MOVLW,pic16_popGetLit(0xfd));
9326         //  pic16_emitpcode(POC_ADDWF,pic16_popCopyReg(&pic16_pc_fsr0));
9327         //}
9328
9329         while(size--) {
9330           pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(right),offset++));
9331           pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9332           
9333           if(size)
9334             pic16_emitpcode(POC_INCF,pic16_popCopyReg(&pic16_pc_fsr0));
9335         }
9336
9337
9338         goto release;
9339       } 
9340
9341       if(aopIdx(AOP(result),0) != 4) {
9342
9343         pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9344         goto release;
9345       }
9346
9347       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9348       goto release;
9349
9350     }
9351   }
9352   /* so dptr know contains the address */
9353
9354
9355   /* if bit then unpack */
9356   if (IS_BITVAR(retype)) 
9357     genPackBits(retype,right,"dptr",GPOINTER);
9358   else {
9359     size = AOP_SIZE(right);
9360     offset = 0 ;
9361
9362   DEBUGpic16_emitcode ("; ***","%s  %d size=%d",__FUNCTION__,__LINE__,size);
9363
9364     while (size--) {
9365
9366       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(result),offset));
9367       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_fsr0));
9368
9369       if (AOP_TYPE(right) == AOP_LIT) 
9370         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
9371       else
9372         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9373
9374       pic16_emitpcode(POC_MOVWF,pic16_popCopyReg(&pic16_pc_indf0));
9375
9376       offset++;
9377     }
9378   }
9379
9380  release:
9381   pic16_freeAsmop(right,NULL,ic,TRUE);
9382   pic16_freeAsmop(result,NULL,ic,TRUE);
9383 }
9384
9385 /*-----------------------------------------------------------------*/
9386 /* genPointerSet - stores the value into a pointer location        */
9387 /*-----------------------------------------------------------------*/
9388 static void genPointerSet (iCode *ic)
9389 {    
9390     operand *right, *result ;
9391     sym_link *type, *etype;
9392     int p_type;
9393
9394     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9395
9396     right = IC_RIGHT(ic);
9397     result = IC_RESULT(ic) ;
9398
9399     /* depending on the type of pointer we need to
9400     move it to the correct pointer register */
9401     type = operandType(result);
9402     etype = getSpec(type);
9403     /* if left is of type of pointer then it is simple */
9404     if (IS_PTR(type) && !IS_FUNC(type->next)) {
9405         p_type = DCL_TYPE(type);
9406     }
9407     else {
9408         /* we have to go by the storage class */
9409         p_type = PTR_TYPE(SPEC_OCLS(etype));
9410
9411 /*      if (SPEC_OCLS(etype)->codesp ) { */
9412 /*          p_type = CPOINTER ;  */
9413 /*      } */
9414 /*      else */
9415 /*          if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
9416 /*              p_type = FPOINTER ; */
9417 /*          else */
9418 /*              if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
9419 /*                  p_type = PPOINTER ; */
9420 /*              else */
9421 /*                  if (SPEC_OCLS(etype) == idata ) */
9422 /*                      p_type = IPOINTER ; */
9423 /*                  else */
9424 /*                      p_type = POINTER ; */
9425     }
9426
9427     /* now that we have the pointer type we assign
9428     the pointer values */
9429     switch (p_type) {
9430
9431     case POINTER:
9432     case IPOINTER:
9433         genNearPointerSet (right,result,ic);
9434         break;
9435
9436     case PPOINTER:
9437         genPagedPointerSet (right,result,ic);
9438         break;
9439
9440     case FPOINTER:
9441         genFarPointerSet (right,result,ic);
9442         break;
9443
9444     case GPOINTER:
9445         genGenPointerSet (right,result,ic);
9446         break;
9447
9448     default:
9449       werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
9450               "genPointerSet: illegal pointer type");
9451     }
9452 }
9453
9454 /*-----------------------------------------------------------------*/
9455 /* genIfx - generate code for Ifx statement                        */
9456 /*-----------------------------------------------------------------*/
9457 static void genIfx (iCode *ic, iCode *popIc)
9458 {
9459   operand *cond = IC_COND(ic);
9460   int isbit =0;
9461
9462   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9463
9464   pic16_aopOp(cond,ic,FALSE);
9465
9466   /* get the value into acc */
9467   if (AOP_TYPE(cond) != AOP_CRY)
9468     pic16_toBoolean(cond);
9469   else
9470     isbit = 1;
9471   /* the result is now in the accumulator */
9472   pic16_freeAsmop(cond,NULL,ic,TRUE);
9473
9474   /* if there was something to be popped then do it */
9475   if (popIc)
9476     genIpop(popIc);
9477
9478   /* if the condition is  a bit variable */
9479   if (isbit && IS_ITEMP(cond) && 
9480       SPIL_LOC(cond)) {
9481     genIfxJump(ic,SPIL_LOC(cond)->rname);
9482     DEBUGpic16_emitcode ("; isbit  SPIL_LOC","%s",SPIL_LOC(cond)->rname);
9483   }
9484   else {
9485     if (isbit && !IS_ITEMP(cond))
9486       genIfxJump(ic,OP_SYMBOL(cond)->rname);
9487     else
9488       genIfxJump(ic,"a");
9489   }
9490   ic->generated = 1;
9491
9492 }
9493
9494 /*-----------------------------------------------------------------*/
9495 /* genAddrOf - generates code for address of                       */
9496 /*-----------------------------------------------------------------*/
9497 #if 0
9498 static void genAddrOf (iCode *ic)
9499 {
9500   operand *right, *result, *left;
9501   int size, offset ;
9502
9503   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9504
9505
9506   //pic16_aopOp(IC_RESULT(ic),ic,FALSE);
9507
9508   pic16_aopOp((left=IC_LEFT(ic)),ic,FALSE);
9509   pic16_aopOp((right=IC_RIGHT(ic)),ic,FALSE);
9510   pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9511
9512   DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
9513
9514   size = AOP_SIZE(IC_RESULT(ic));
9515   offset = 0;
9516
9517
9518   while (size--) {
9519     pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),offset));
9520     pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9521     offset++;
9522   }
9523
9524
9525   pic16_freeAsmop(left,NULL,ic,FALSE);
9526   pic16_freeAsmop(result,NULL,ic,TRUE);
9527
9528 }
9529
9530 #else   /* new genAddrOf */
9531
9532 static void genAddrOf (iCode *ic)
9533 {
9534   operand *result, *left;
9535   int size;
9536   symbol *sym;  // = OP_SYMBOL(IC_LEFT(ic));
9537   pCodeOp *pcop0, *pcop1, *pcop2;
9538
9539         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9540
9541         pic16_aopOp((left=IC_LEFT(ic)), ic, FALSE);
9542         pic16_aopOp((result=IC_RESULT(ic)),ic,TRUE);
9543
9544         sym = OP_SYMBOL( left );
9545
9546         size = AOP_SIZE(IC_RESULT(ic));
9547
9548         if(pic16_debug_verbose) {
9549                 fprintf(stderr, "%s:%d %s symbol %s , codespace=%d\n",
9550                         __FILE__, __LINE__, __FUNCTION__, sym->name, IN_CODESPACE( SPEC_OCLS(sym->etype)));
9551         }
9552         
9553         /* Assume that what we want the address of is in data space
9554          * since there is no stack on the PIC, yet! -- VR */
9555         /* low */
9556         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9557
9558         /* high */
9559         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9560         
9561         /* upper */
9562         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
9563         
9564
9565         if (size == 3) {
9566                 pic16_emitpcode(POC_MOVLW, pcop0);
9567                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
9568                 pic16_emitpcode(POC_MOVLW, pcop1);
9569                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
9570                 pic16_emitpcode(POC_MOVLW, pcop2);
9571                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
9572         } else
9573         if (size == 2) {
9574                 pic16_emitpcode(POC_MOVLW, pcop0);
9575                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9576                 pic16_emitpcode(POC_MOVLW, pcop1);
9577                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
9578         } else {
9579                 pic16_emitpcode(POC_MOVLW, pcop0);
9580                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
9581         }
9582
9583         pic16_freeAsmop(result,NULL,ic,TRUE);
9584         pic16_freeAsmop(left, NULL, ic, FALSE);
9585 }
9586
9587 #endif  /* new genAddrOf */
9588
9589 #if 0
9590 /*-----------------------------------------------------------------*/
9591 /* genFarFarAssign - assignment when both are in far space         */
9592 /*-----------------------------------------------------------------*/
9593 static void genFarFarAssign (operand *result, operand *right, iCode *ic)
9594 {
9595     int size = AOP_SIZE(right);
9596     int offset = 0;
9597     char *l ;
9598     /* first push the right side on to the stack */
9599     while (size--) {
9600         l = pic16_aopGet(AOP(right),offset++,FALSE,FALSE);
9601         MOVA(l);
9602         pic16_emitcode ("push","acc");
9603     }
9604     
9605     pic16_freeAsmop(right,NULL,ic,FALSE);
9606     /* now assign DPTR to result */
9607     pic16_aopOp(result,ic,FALSE);
9608     size = AOP_SIZE(result);
9609     while (size--) {
9610         pic16_emitcode ("pop","acc");
9611         pic16_aopPut(AOP(result),"a",--offset);
9612     }
9613     pic16_freeAsmop(result,NULL,ic,FALSE);
9614         
9615 }
9616 #endif
9617
9618 /*-----------------------------------------------------------------*/
9619 /* genAssign - generate code for assignment                        */
9620 /*-----------------------------------------------------------------*/
9621 static void genAssign (iCode *ic)
9622 {
9623   operand *result, *right;
9624   int size, offset,know_W;
9625   unsigned long lit = 0L;
9626
9627   result = IC_RESULT(ic);
9628   right  = IC_RIGHT(ic) ;
9629
9630   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9631   
9632   /* if they are the same */
9633   if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic)))
9634     return ;
9635
9636   pic16_aopOp(right,ic,FALSE);
9637   pic16_aopOp(result,ic,TRUE);
9638
9639   DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9640
9641   /* if they are the same registers */
9642   if (pic16_sameRegs(AOP(right),AOP(result)))
9643     goto release;
9644
9645   /* if the result is a bit */
9646   if (AOP_TYPE(result) == AOP_CRY) {
9647     /* if the right size is a literal then
9648        we know what the value is */
9649     if (AOP_TYPE(right) == AOP_LIT) {
9650           
9651       pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9652                   pic16_popGet(AOP(result),0));
9653
9654       if (((int) operandLitValue(right))) 
9655         pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9656                        AOP(result)->aopu.aop_dir,
9657                        AOP(result)->aopu.aop_dir);
9658       else
9659         pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9660                        AOP(result)->aopu.aop_dir,
9661                        AOP(result)->aopu.aop_dir);
9662       goto release;
9663     }
9664
9665     /* the right is also a bit variable */
9666     if (AOP_TYPE(right) == AOP_CRY) {
9667       pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9668       pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9669       pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9670
9671       pic16_emitcode("bcf","(%s >> 3),(%s & 7)",
9672                      AOP(result)->aopu.aop_dir,
9673                      AOP(result)->aopu.aop_dir);
9674       pic16_emitcode("btfsc","(%s >> 3),(%s & 7)",
9675                      AOP(right)->aopu.aop_dir,
9676                      AOP(right)->aopu.aop_dir);
9677       pic16_emitcode("bsf","(%s >> 3),(%s & 7)",
9678                      AOP(result)->aopu.aop_dir,
9679                      AOP(result)->aopu.aop_dir);
9680       goto release ;
9681     }
9682
9683     /* we need to or */
9684     pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9685     pic16_toBoolean(right);
9686     emitSKPZ;
9687     pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9688     //pic16_aopPut(AOP(result),"a",0);
9689     goto release ;
9690   }
9691
9692   /* bit variables done */
9693   /* general case */
9694   size = AOP_SIZE(result);
9695   offset = 0 ;
9696   if(AOP_TYPE(right) == AOP_LIT)
9697     lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
9698
9699 /* VR - What is this?! */
9700   if( AOP_TYPE(right) == AOP_DIR  && (AOP_TYPE(result) == AOP_REG) && size==1)  {
9701   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9702     if(aopIdx(AOP(result),0) == 4) {
9703   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9704       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9705       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9706       goto release;
9707     } else
9708       DEBUGpic16_emitcode ("; WARNING","%s  %d ignoring register storage",__FUNCTION__,__LINE__);
9709   }
9710
9711   know_W=-1;
9712   while (size--) {
9713   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9714     if(AOP_TYPE(right) == AOP_LIT) {
9715       if(lit&0xff) {
9716         if(know_W != (lit&0xff))
9717           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
9718         know_W = lit&0xff;
9719         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9720       } else
9721         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9722
9723       lit >>= 8;
9724
9725     } else if (AOP_TYPE(right) == AOP_CRY) {
9726       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
9727       if(offset == 0) {
9728         pic16_emitpcode(POC_BTFSS, pic16_popGet(AOP(right),0));
9729         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
9730       }
9731     } else {
9732   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9733
9734 #if 1
9735         /* This is a hack to turn MOVFW/MOVWF pairs to MOVFF command. It
9736            normally should work, but mind that the W register live range
9737            is not checked, so if the code generator assumes that the W
9738            is already loaded after such a pair, wrong code will be generated.
9739            
9740            Checking the live range is the next step.
9741            This is experimental code yet and has not been fully tested yet.
9742            USE WITH CARE. Revert to old code by setting 0 to the condition above.
9743            Vangelis Rokas 030603 (vrokas@otenet.gr) */
9744            
9745         pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
9746 #else   
9747         /* This is the old code, which is assumed(?!) that works fine(!?) */
9748
9749         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
9750         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
9751 #endif
9752     }
9753             
9754     offset++;
9755   }
9756
9757     
9758  release:
9759   pic16_freeAsmop (right,NULL,ic,FALSE);
9760   pic16_freeAsmop (result,NULL,ic,TRUE);
9761 }   
9762
9763 /*-----------------------------------------------------------------*/
9764 /* genJumpTab - generates code for jump table                       */
9765 /*-----------------------------------------------------------------*/
9766 static void genJumpTab (iCode *ic)
9767 {
9768     symbol *jtab;
9769     char *l;
9770
9771     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
9772
9773     pic16_aopOp(IC_JTCOND(ic),ic,FALSE);
9774     /* get the condition into accumulator */
9775     l = pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE);
9776     MOVA(l);
9777     /* multiply by three */
9778     pic16_emitcode("add","a,acc");
9779     pic16_emitcode("add","a,%s",pic16_aopGet(AOP(IC_JTCOND(ic)),0,FALSE,FALSE));
9780
9781     jtab = newiTempLabel(NULL);
9782     pic16_emitcode("mov","dptr,#%05d_DS_",jtab->key+100);
9783     pic16_emitcode("jmp","@a+dptr");
9784     pic16_emitcode("","%05d_DS_:",jtab->key+100);
9785
9786     pic16_emitpcode(POC_MOVLW, pic16_popGetLabel(jtab->key));
9787     pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_JTCOND(ic)),0));
9788     emitSKPNC;
9789     pic16_emitpcode(POC_INCF, pic16_popCopyReg(&pic16_pc_pclath));
9790     pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(&pic16_pc_pcl));
9791     pic16_emitpLabel(jtab->key);
9792
9793     pic16_freeAsmop(IC_JTCOND(ic),NULL,ic,TRUE);
9794
9795     /* now generate the jump labels */
9796     for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
9797          jtab = setNextItem(IC_JTLABELS(ic))) {
9798         pic16_emitcode("ljmp","%05d_DS_",jtab->key+100);
9799         pic16_emitpcode(POC_GOTO,pic16_popGetLabel(jtab->key));
9800         
9801     }
9802
9803 }
9804
9805 /*-----------------------------------------------------------------*/
9806 /* genMixedOperation - gen code for operators between mixed types  */
9807 /*-----------------------------------------------------------------*/
9808 /*
9809   TSD - Written for the PIC port - but this unfortunately is buggy.
9810   This routine is good in that it is able to efficiently promote 
9811   types to different (larger) sizes. Unfortunately, the temporary
9812   variables that are optimized out by this routine are sometimes
9813   used in other places. So until I know how to really parse the 
9814   iCode tree, I'm going to not be using this routine :(.
9815 */
9816 static int genMixedOperation (iCode *ic)
9817 {
9818 #if 0
9819   operand *result = IC_RESULT(ic);
9820   sym_link *ctype = operandType(IC_LEFT(ic));
9821   operand *right = IC_RIGHT(ic);
9822   int ret = 0;
9823   int big,small;
9824   int offset;
9825
9826   iCode *nextic;
9827   operand *nextright=NULL,*nextleft=NULL,*nextresult=NULL;
9828
9829   pic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9830
9831   nextic = ic->next;
9832   if(!nextic)
9833     return 0;
9834
9835   nextright = IC_RIGHT(nextic);
9836   nextleft  = IC_LEFT(nextic);
9837   nextresult = IC_RESULT(nextic);
9838
9839   pic16_aopOp(right,ic,FALSE);
9840   pic16_aopOp(result,ic,FALSE);
9841   pic16_aopOp(nextright,  nextic, FALSE);
9842   pic16_aopOp(nextleft,   nextic, FALSE);
9843   pic16_aopOp(nextresult, nextic, FALSE);
9844
9845   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_RIGHT(nextic)))) {
9846
9847     operand *t = right;
9848     right = nextright;
9849     nextright = t; 
9850
9851     pic16_emitcode(";remove right +","");
9852
9853   } else   if (pic16_sameRegs(AOP(IC_RESULT(ic)), AOP(IC_LEFT(nextic)))) {
9854 /*
9855     operand *t = right;
9856     right = nextleft;
9857     nextleft = t; 
9858 */
9859     pic16_emitcode(";remove left +","");
9860   } else
9861     return 0;
9862
9863   big = AOP_SIZE(nextleft);
9864   small = AOP_SIZE(nextright);
9865
9866   switch(nextic->op) {
9867
9868   case '+':
9869     pic16_emitcode(";optimize a +","");
9870     /* if unsigned or not an integral type */
9871     if (AOP_TYPE(IC_LEFT(nextic)) == AOP_CRY) {
9872       pic16_emitcode(";add a bit to something","");
9873     } else {
9874
9875       pic16_emitcode("movf","%s,w",AOP(nextright)->aopu.aop_dir);
9876
9877       if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ) {
9878         pic16_emitcode("addwf","%s,w",AOP(nextleft)->aopu.aop_dir);
9879         pic16_emitcode("movwf","%s",pic16_aopGet(AOP(IC_RESULT(nextic)),0,FALSE,FALSE));
9880       } else
9881         pic16_emitcode("addwf","%s,f",AOP(nextleft)->aopu.aop_dir);
9882
9883       offset = 0;
9884       while(--big) {
9885
9886         offset++;
9887
9888         if(--small) {
9889           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9890             pic16_emitcode("movf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9891             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9892           }
9893
9894           pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9895           emitSKPNC;
9896           pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9897                    AOP(IC_RIGHT(nextic))->aopu.aop_dir,
9898                    AOP(IC_RIGHT(nextic))->aopu.aop_dir);
9899           pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9900           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE));
9901
9902         } else {
9903           pic16_emitcode("rlf","known_zero,w");
9904
9905           /*
9906             if right is signed
9907               btfsc  right,7
9908                addlw ff
9909           */
9910           if (!pic16_sameRegs(AOP(IC_LEFT(nextic)), AOP(IC_RESULT(nextic))) ){
9911             pic16_emitcode("addwf","%s,w",pic16_aopGet(AOP(IC_LEFT(nextic)),offset,FALSE,FALSE));
9912             pic16_emitcode("movwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9913           } else {
9914             pic16_emitcode("addwf","%s,f",pic16_aopGet(AOP(IC_RESULT(nextic)),offset,FALSE,FALSE) );
9915           }
9916         }
9917       }
9918       ret = 1;
9919     }
9920   }
9921   ret = 1;
9922
9923 release:
9924   pic16_freeAsmop(right,NULL,ic,TRUE);
9925   pic16_freeAsmop(result,NULL,ic,TRUE);
9926   pic16_freeAsmop(nextright,NULL,ic,TRUE);
9927   pic16_freeAsmop(nextleft,NULL,ic,TRUE);
9928   if(ret)
9929     nextic->generated = 1;
9930
9931   return ret;
9932 #else
9933   return 0;
9934 #endif
9935 }
9936 /*-----------------------------------------------------------------*/
9937 /* genCast - gen code for casting                                  */
9938 /*-----------------------------------------------------------------*/
9939 static void genCast (iCode *ic)
9940 {
9941   operand *result = IC_RESULT(ic);
9942   sym_link *ctype = operandType(IC_LEFT(ic));
9943   sym_link *rtype = operandType(IC_RIGHT(ic));
9944   operand *right = IC_RIGHT(ic);
9945   int size, offset ;
9946
9947         DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9948         /* if they are equivalent then do nothing */
9949         if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
9950                 return ;
9951
9952         pic16_aopOp(right,ic,FALSE) ;
9953         pic16_aopOp(result,ic,FALSE);
9954
9955         DEBUGpic16_pic16_AopType(__LINE__,NULL,right,result);
9956
9957         /* if the result is a bit */
9958         if (AOP_TYPE(result) == AOP_CRY) {
9959         
9960                 /* if the right size is a literal then
9961                  * we know what the value is */
9962                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
9963
9964                 if (AOP_TYPE(right) == AOP_LIT) {
9965                         pic16_emitpcode(  ( ((int) operandLitValue(right)) ? POC_BSF : POC_BCF),
9966                                 pic16_popGet(AOP(result),0));
9967
9968                         if (((int) operandLitValue(right))) 
9969                                 pic16_emitcode("bsf","(%s >> 3), (%s & 7)",
9970                                         AOP(result)->aopu.aop_dir,
9971                                         AOP(result)->aopu.aop_dir);
9972                         else
9973                                 pic16_emitcode("bcf","(%s >> 3), (%s & 7)",
9974                                         AOP(result)->aopu.aop_dir,
9975                                         AOP(result)->aopu.aop_dir);
9976                         goto release;
9977                 }
9978
9979                 /* the right is also a bit variable */
9980                 if (AOP_TYPE(right) == AOP_CRY) {
9981                         emitCLRC;
9982                         pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
9983
9984                         pic16_emitcode("clrc","");
9985                         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
9986                                 AOP(right)->aopu.aop_dir,
9987                                 AOP(right)->aopu.aop_dir);
9988                         pic16_aopPut(AOP(result),"c",0);
9989                         goto release ;
9990                 }
9991
9992                 /* we need to or */
9993                 if (AOP_TYPE(right) == AOP_REG) {
9994                         pic16_emitpcode(POC_BCF,    pic16_popGet(AOP(result),0));
9995                         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),0,0));
9996                         pic16_emitpcode(POC_BSF,    pic16_popGet(AOP(result),0));
9997                 }
9998                 pic16_toBoolean(right);
9999                 pic16_aopPut(AOP(result),"a",0);
10000                 goto release ;
10001         }
10002
10003         if ((AOP_TYPE(right) == AOP_CRY) && (AOP_TYPE(result) == AOP_REG)) {
10004           int offset = 1;
10005
10006                 size = AOP_SIZE(result);
10007
10008                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10009
10010                 pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),0));
10011                 pic16_emitpcode(POC_BTFSC,  pic16_popGet(AOP(right),0));
10012                 pic16_emitpcode(POC_INCF,   pic16_popGet(AOP(result),0));
10013
10014                 while (size--)
10015                         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10016
10017                 goto release;
10018         }
10019
10020         /* if they are the same size : or less */
10021         if (AOP_SIZE(result) <= AOP_SIZE(right)) {
10022
10023                 /* if they are in the same place */
10024                 if (pic16_sameRegs(AOP(right),AOP(result)))
10025                         goto release;
10026
10027                 DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10028 #if 0
10029                 if (IS_PTR_CONST(rtype))
10030 #else
10031                 if (IS_CODEPTR(rtype))
10032 #endif
10033                         DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
10034
10035 #if 0
10036                 if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
10037 #else
10038                 if (IS_CODEPTR(operandType(IC_RESULT(ic))))
10039 #endif
10040                         DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
10041
10042 #if 0
10043                 if(AOP_TYPE(right) == AOP_IMMD) {
10044                   pCodeOp *pcop0, *pcop1, *pcop2;
10045                   symbol *sym = OP_SYMBOL( right );
10046
10047                         size = AOP_SIZE(result);
10048                         /* low */
10049                         pcop0 = PCOP(pic16_newpCodeOpImmd(sym->rname, 0, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10050                         /* high */
10051                         pcop1 = PCOP(pic16_newpCodeOpImmd(sym->rname, 1, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10052                         /* upper */
10053                         pcop2 = PCOP(pic16_newpCodeOpImmd(sym->rname, 2, 0, IN_CODESPACE( SPEC_OCLS(sym->etype))));
10054         
10055                         if (size == 3) {
10056                                 pic16_emitpcode(POC_MOVLW, pcop0);
10057                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
10058                                 pic16_emitpcode(POC_MOVLW, pcop1);
10059                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
10060                                 pic16_emitpcode(POC_MOVLW, pcop2);
10061                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 2));
10062                         } else
10063                         if (size == 2) {
10064                                 pic16_emitpcode(POC_MOVLW, pcop0);
10065                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10066                                 pic16_emitpcode(POC_MOVLW, pcop1);
10067                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10068                         } else {
10069                                 pic16_emitpcode(POC_MOVLW, pcop0);
10070                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10071                         }
10072                 } else
10073 #endif
10074                 if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10075                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),0));
10076                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
10077                         pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),1));
10078                         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),1));
10079                         if(AOP_SIZE(result) <2)
10080                                 fprintf(stderr,"%d -- result is not big enough to hold a ptr\n",__LINE__);
10081                 } else {
10082                         /* if they in different places then copy */
10083                         size = AOP_SIZE(result);
10084                         offset = 0 ;
10085                         while (size--) {
10086                                 pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),offset));
10087                                 pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10088                                 offset++;
10089                         }
10090                 }
10091                 goto release;
10092         }
10093
10094         /* if the result is of type pointer */
10095         if (IS_PTR(ctype)) {
10096           int p_type;
10097           sym_link *type = operandType(right);
10098           sym_link *etype = getSpec(type);
10099
10100                 DEBUGpic16_emitcode("; ***","%s  %d - pointer cast",__FUNCTION__,__LINE__);
10101
10102                 /* pointer to generic pointer */
10103                 if (IS_GENPTR(ctype)) {
10104                   char *l = zero;
10105             
10106                         if (IS_PTR(type)) 
10107                                 p_type = DCL_TYPE(type);
10108                         else {
10109                 /* we have to go by the storage class */
10110                 p_type = PTR_TYPE(SPEC_OCLS(etype));
10111
10112 /*              if (SPEC_OCLS(etype)->codesp )  */
10113 /*                  p_type = CPOINTER ;  */
10114 /*              else */
10115 /*                  if (SPEC_OCLS(etype)->fmap && !SPEC_OCLS(etype)->paged) */
10116 /*                      p_type = FPOINTER ; */
10117 /*                  else */
10118 /*                      if (SPEC_OCLS(etype)->fmap && SPEC_OCLS(etype)->paged) */
10119 /*                          p_type = PPOINTER; */
10120 /*                      else */
10121 /*                          if (SPEC_OCLS(etype) == idata ) */
10122 /*                              p_type = IPOINTER ; */
10123 /*                          else */
10124 /*                              p_type = POINTER ; */
10125             }
10126                 
10127             /* the first two bytes are known */
10128       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast2",__FUNCTION__,__LINE__);
10129             size = GPTRSIZE - 1; 
10130             offset = 0 ;
10131             while (size--) {
10132               if(offset < AOP_SIZE(right)) {
10133       DEBUGpic16_emitcode("; ***","%s  %d - pointer cast3",__FUNCTION__,__LINE__);
10134                 if ((AOP_TYPE(right) == AOP_PCODE) && 
10135                     AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
10136                   pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
10137                   pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
10138                 } else { 
10139                   pic16_aopPut(AOP(result),
10140                          pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10141                          offset);
10142                 }
10143               } else 
10144                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),offset));
10145               offset++;
10146             }
10147             /* the last byte depending on type */
10148             switch (p_type) {
10149             case IPOINTER:
10150             case POINTER:
10151                 pic16_emitpcode(POC_CLRF,pic16_popGet(AOP(result),GPTRSIZE - 1));
10152                 break;
10153             case FPOINTER:
10154               pic16_emitcode(";BUG!? ","%d",__LINE__);
10155                 l = one;
10156                 break;
10157             case CPOINTER:
10158               pic16_emitcode(";BUG!? ","%d",__LINE__);
10159                 l = "#0x02";
10160                 break;                          
10161             case PPOINTER:
10162               pic16_emitcode(";BUG!? ","%d",__LINE__);
10163                 l = "#0x03";
10164                 break;
10165                 
10166             default:
10167                 /* this should never happen */
10168                 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10169                        "got unknown pointer type");
10170                 exit(1);
10171             }
10172             //pic16_aopPut(AOP(result),l, GPTRSIZE - 1);            
10173             goto release ;
10174         }
10175         
10176         /* just copy the pointers */
10177         size = AOP_SIZE(result);
10178         offset = 0 ;
10179         while (size--) {
10180             pic16_aopPut(AOP(result),
10181                    pic16_aopGet(AOP(right),offset,FALSE,FALSE),
10182                    offset);
10183             offset++;
10184         }
10185         goto release ;
10186     }
10187     
10188
10189
10190     /* so we now know that the size of destination is greater
10191     than the size of the source.
10192     Now, if the next iCode is an operator then we might be
10193     able to optimize the operation without performing a cast.
10194     */
10195     if(genMixedOperation(ic))
10196       goto release;
10197
10198     DEBUGpic16_emitcode("; ***","%s  %d",__FUNCTION__,__LINE__);
10199     
10200     /* we move to result for the size of source */
10201     size = AOP_SIZE(right);
10202     offset = 0 ;
10203     while (size--) {
10204       pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(right),offset));
10205       pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset));
10206       offset++;
10207     }
10208
10209     /* now depending on the sign of the destination */
10210     size = AOP_SIZE(result) - AOP_SIZE(right);
10211     /* if unsigned or not an integral type */
10212     if (SPEC_USIGN(rtype) || !IS_SPEC(rtype)) {
10213       while (size--)
10214         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset++));
10215     } else {
10216       /* we need to extend the sign :( */
10217
10218       if(size == 1) {
10219         /* Save one instruction of casting char to int */
10220         pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(result),offset));
10221         pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10222         pic16_emitpcode(POC_DECF,   pic16_popGet(AOP(result),offset));
10223       } else {
10224         pic16_emitpcode(POC_CLRF,pic16_popCopyReg(&pic16_pc_wreg));
10225
10226         if(offset)
10227           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset-1,FALSE,FALSE),7,0));
10228         else
10229           pic16_emitpcode(POC_BTFSC,   pic16_newpCodeOpBit(pic16_aopGet(AOP(right),offset,FALSE,FALSE),7,0));
10230         
10231         pic16_emitpcode(POC_MOVLW,   pic16_popGetLit(0xff));
10232
10233         while (size--)
10234           pic16_emitpcode(POC_MOVWF,   pic16_popGet(AOP(result),offset++));
10235       }
10236     }
10237
10238 release:
10239     pic16_freeAsmop(right,NULL,ic,TRUE);
10240     pic16_freeAsmop(result,NULL,ic,TRUE);
10241
10242 }
10243
10244 /*-----------------------------------------------------------------*/
10245 /* genDjnz - generate decrement & jump if not zero instrucion      */
10246 /*-----------------------------------------------------------------*/
10247 static int genDjnz (iCode *ic, iCode *ifx)
10248 {
10249     symbol *lbl, *lbl1;
10250     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10251
10252     if (!ifx)
10253         return 0;
10254     
10255     /* if the if condition has a false label
10256        then we cannot save */
10257     if (IC_FALSE(ifx))
10258         return 0;
10259
10260     /* if the minus is not of the form 
10261        a = a - 1 */
10262     if (!isOperandEqual(IC_RESULT(ic),IC_LEFT(ic)) ||
10263         !IS_OP_LITERAL(IC_RIGHT(ic)))
10264         return 0;
10265
10266     if (operandLitValue(IC_RIGHT(ic)) != 1)
10267         return 0;
10268
10269     /* if the size of this greater than one then no
10270        saving */
10271     if (getSize(operandType(IC_RESULT(ic))) > 1)
10272         return 0;
10273
10274     /* otherwise we can save BIG */
10275     lbl = newiTempLabel(NULL);
10276     lbl1= newiTempLabel(NULL);
10277
10278     pic16_aopOp(IC_RESULT(ic),ic,FALSE);
10279     
10280     if (IS_AOP_PREG(IC_RESULT(ic))) {
10281         pic16_emitcode("dec","%s",
10282                  pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10283         pic16_emitcode("mov","a,%s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10284         pic16_emitcode("jnz","%05d_DS_",lbl->key+100);
10285     } else {    
10286
10287
10288       pic16_emitpcode(POC_DECFSZ,pic16_popGet(AOP(IC_RESULT(ic)),0));
10289       pic16_emitpcode(POC_GOTO,pic16_popGetLabel(IC_TRUE(ifx)->key));
10290
10291       pic16_emitcode("decfsz","%s,f",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
10292       pic16_emitcode ("goto","_%05d_DS_",IC_TRUE(ifx)->key+100 + labelOffset);
10293
10294     }
10295 /*     pic16_emitcode ("sjmp","%05d_DS_",lbl1->key+100); */
10296 /*     pic16_emitcode ("","%05d_DS_:",lbl->key+100); */
10297 /*     pic16_emitcode ("ljmp","%05d_DS_",IC_TRUE(ifx)->key+100); */
10298 /*     pic16_emitcode ("","%05d_DS_:",lbl1->key+100); */
10299
10300     
10301     pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10302     ifx->generated = 1;
10303     return 1;
10304 }
10305
10306 /*-----------------------------------------------------------------*/
10307 /* genReceive - generate code for a receive iCode                  */
10308 /*-----------------------------------------------------------------*/
10309 static void genReceive (iCode *ic)
10310 {    
10311         DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
10312
10313         if (isOperandInFarSpace(IC_RESULT(ic)) && 
10314                 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
10315                 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
10316
10317           int size = getSize(operandType(IC_RESULT(ic)));
10318           int offset =  pic16_fReturnSizePic - size;
10319
10320                 while (size--) {
10321                         pic16_emitcode ("push","%s", (strcmp(fReturn[pic16_fReturnSizePic - offset - 1],"a") ?
10322                                         fReturn[pic16_fReturnSizePic - offset - 1] : "acc"));
10323                         offset++;
10324                 }
10325
10326                 DEBUGpic16_emitcode ("; ***","1 %s  %d",__FUNCTION__,__LINE__);
10327
10328                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10329                 size = AOP_SIZE(IC_RESULT(ic));
10330                 offset = 0;
10331                 while (size--) {
10332                         pic16_emitcode ("pop","acc");
10333                         pic16_aopPut (AOP(IC_RESULT(ic)),"a",offset++);
10334                 }
10335         } else {
10336                 DEBUGpic16_emitcode ("; ***","2 %s  %d",__FUNCTION__,__LINE__);
10337
10338                 _G.accInUse++;
10339                 pic16_aopOp(IC_RESULT(ic),ic,FALSE);  
10340                 _G.accInUse--;
10341                 assignResultValue(IC_RESULT(ic));       
10342         }
10343
10344         pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
10345 }
10346
10347 /*-----------------------------------------------------------------*/
10348 /* genDummyRead - generate code for dummy read of volatiles        */
10349 /*-----------------------------------------------------------------*/
10350 static void
10351 genDummyRead (iCode * ic)
10352 {
10353   pic16_emitcode ("; genDummyRead","");
10354   pic16_emitcode ("; not implemented","");
10355
10356   ic = ic;
10357 }
10358
10359 /*-----------------------------------------------------------------*/
10360 /* genpic16Code - generate code for pic16 based controllers        */
10361 /*-----------------------------------------------------------------*/
10362 /*
10363  * At this point, ralloc.c has gone through the iCode and attempted
10364  * to optimize in a way suitable for a PIC. Now we've got to generate
10365  * PIC instructions that correspond to the iCode.
10366  *
10367  * Once the instructions are generated, we'll pass through both the
10368  * peep hole optimizer and the pCode optimizer.
10369  *-----------------------------------------------------------------*/
10370
10371 void genpic16Code (iCode *lic)
10372 {
10373     iCode *ic;
10374     int cln = 0;
10375
10376     lineHead = lineCurr = NULL;
10377
10378     pb = pic16_newpCodeChain(GcurMemmap,0,pic16_newpCodeCharP("; Starting pCode block"));
10379     pic16_addpBlock(pb);
10380
10381 #if 0
10382     /* if debug information required */
10383     if (options.debug && currFunc) {
10384       if (currFunc) {
10385         cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
10386         _G.debugLine = 1;
10387         if (IS_STATIC(currFunc->etype)) {
10388           pic16_emitcode("",";F%s$%s$0$0     %d",moduleName,currFunc->name,__LINE__);
10389           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(moduleName,currFunc->name));
10390         } else {
10391           pic16_emitcode("",";G$%s$0$0   %d",currFunc->name,__LINE__);
10392           //pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(NULL,currFunc->name));
10393         }
10394         _G.debugLine = 0;
10395       }
10396     }
10397 #endif
10398
10399 //    dumpiCode(lic);
10400
10401     for (ic = lic ; ic ; ic = ic->next ) {
10402
10403 //      fprintf(stderr, "; VR = %c %x\n", ic->op, ic->op);
10404 //      DEBUGpic16_emitcode("; VR", "");
10405       DEBUGpic16_emitcode(";ic ", "\t%c 0x%x",ic->op, ic->op);
10406         if ( cln != ic->lineno ) {
10407             if ( options.debug ) {
10408                 _G.debugLine = 1;
10409                 pic16_emitcode("",";C$%s$%d$%d$%d ==.",
10410                          FileBaseName(ic->filename),ic->lineno,
10411                          ic->level,ic->block);
10412                 _G.debugLine = 0;
10413             }
10414             
10415             if(!options.noCcodeInAsm) {
10416                 pic16_addpCode2pBlock(pb,
10417                         pic16_newpCodeCSource(ic->lineno, ic->filename, 
10418                                 printCLine(ic->filename, ic->lineno)));
10419             }
10420
10421             cln = ic->lineno ;
10422         }
10423         
10424         if(options.iCodeInAsm) {
10425                 /* insert here code to print iCode as comment */
10426                 pic16_emitcomment("; ic:%d: %s", ic->seq, printILine(ic));
10427         }
10428         
10429         /* if the result is marked as
10430            spilt and rematerializable or code for
10431            this has already been generated then
10432            do nothing */
10433         if (resultRemat(ic) || ic->generated ) 
10434             continue ;
10435         
10436         /* depending on the operation */
10437         switch (ic->op) {
10438         case '!' :
10439             pic16_genNot(ic);
10440             break;
10441             
10442         case '~' :
10443             pic16_genCpl(ic);
10444             break;
10445             
10446         case UNARYMINUS:
10447             genUminus (ic);
10448             break;
10449             
10450         case IPUSH:
10451             genIpush (ic);
10452             break;
10453             
10454         case IPOP:
10455             /* IPOP happens only when trying to restore a 
10456                spilt live range, if there is an ifx statement
10457                following this pop then the if statement might
10458                be using some of the registers being popped which
10459                would destroy the contents of the register so
10460                we need to check for this condition and handle it */
10461             if (ic->next            && 
10462                 ic->next->op == IFX &&
10463                 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) 
10464                 genIfx (ic->next,ic);
10465             else
10466                 genIpop (ic);
10467             break; 
10468             
10469         case CALL:
10470             genCall (ic);
10471             break;
10472             
10473         case PCALL:
10474             genPcall (ic);
10475             break;
10476             
10477         case FUNCTION:
10478             genFunction (ic);
10479             break;
10480             
10481         case ENDFUNCTION:
10482             genEndFunction (ic);
10483             break;
10484             
10485         case RETURN:
10486             genRet (ic);
10487             break;
10488             
10489         case LABEL:
10490             genLabel (ic);
10491             break;
10492             
10493         case GOTO:
10494             genGoto (ic);
10495             break;
10496             
10497         case '+' :
10498             pic16_genPlus (ic) ;
10499             break;
10500             
10501         case '-' :
10502             if ( ! genDjnz (ic,ifxForOp(IC_RESULT(ic),ic)))
10503                 pic16_genMinus (ic);
10504             break;
10505             
10506         case '*' :
10507             genMult (ic);
10508             break;
10509             
10510         case '/' :
10511             genDiv (ic) ;
10512             break;
10513             
10514         case '%' :
10515             genMod (ic);
10516             break;
10517             
10518         case '>' :
10519             genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
10520             break;
10521             
10522         case '<' :
10523             genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
10524             break;
10525             
10526         case LE_OP:
10527         case GE_OP:
10528         case NE_OP:
10529             
10530             /* note these two are xlated by algebraic equivalence
10531                during parsing SDCC.y */
10532             werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
10533                    "got '>=' or '<=' shouldn't have come here");
10534             break;      
10535             
10536         case EQ_OP:
10537             genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
10538             break;          
10539             
10540         case AND_OP:
10541             genAndOp (ic);
10542             break;
10543             
10544         case OR_OP:
10545             genOrOp (ic);
10546             break;
10547             
10548         case '^' :
10549             genXor (ic,ifxForOp(IC_RESULT(ic),ic));
10550             break;
10551             
10552         case '|' :
10553                 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
10554             break;
10555             
10556         case BITWISEAND:
10557             genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
10558             break;
10559             
10560         case INLINEASM:
10561             genInline (ic);
10562             break;
10563             
10564         case RRC:
10565             genRRC (ic);
10566             break;
10567             
10568         case RLC:
10569             genRLC (ic);
10570             break;
10571             
10572         case GETHBIT:
10573             genGetHbit (ic);
10574             break;
10575             
10576         case LEFT_OP:
10577             genLeftShift (ic);
10578             break;
10579             
10580         case RIGHT_OP:
10581             genRightShift (ic);
10582             break;
10583             
10584         case GET_VALUE_AT_ADDRESS:
10585             genPointerGet(ic);
10586             break;
10587             
10588         case '=' :
10589             if (POINTER_SET(ic))
10590                 genPointerSet(ic);
10591             else
10592                 genAssign(ic);
10593             break;
10594             
10595         case IFX:
10596             genIfx (ic,NULL);
10597             break;
10598             
10599         case ADDRESS_OF:
10600             genAddrOf (ic);
10601             break;
10602             
10603         case JUMPTABLE:
10604             genJumpTab (ic);
10605             break;
10606             
10607         case CAST:
10608             genCast (ic);
10609             break;
10610             
10611         case RECEIVE:
10612             genReceive(ic);
10613             break;
10614             
10615         case SEND:
10616             addSet(&_G.sendSet,ic);
10617             break;
10618
10619         case DUMMY_READ_VOLATILE:
10620           genDummyRead (ic);
10621           break;
10622
10623         default :
10624             ic = ic;
10625         }
10626     }
10627
10628
10629     /* now we are ready to call the
10630        peep hole optimizer */
10631     if (!options.nopeep) {
10632       peepHole (&lineHead);
10633     }
10634     /* now do the actual printing */
10635     printLine (lineHead,codeOutFile);
10636
10637 #ifdef PCODE_DEBUG
10638     DFPRINTF((stderr,"printing pBlock\n\n"));
10639     pic16_printpBlock(stdout,pb);
10640 #endif
10641
10642     return;
10643 }
10644